Skip to content

Commit

Permalink
feat(common): APPEX-202 implement orders page designs
Browse files Browse the repository at this point in the history
  • Loading branch information
bc-zachary committed Dec 7, 2021
1 parent 63f9dd9 commit 440b28e
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 3 deletions.
3 changes: 2 additions & 1 deletion components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ export const TabRoutes = {
};

const HeaderlessRoutes = [
'/orders/[orderId]',
'/orders/[orderId]/labels',
'/orders/[orderId]/modal',
]
];

const InnerRoutes = [
'/products/[pid]',
Expand Down
19 changes: 18 additions & 1 deletion lib/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import useSWR from 'swr';
import { useSession } from '../context/session';
import { ErrorProps, ListItem, Order, QueryParams } from '../types';
import { ErrorProps, ListItem, Order, QueryParams, ShippingAndProductsInfo } from '../types';

async function fetcher(url: string, query: string) {
const res = await fetch(`${url}?${query}`);
Expand Down Expand Up @@ -75,3 +75,20 @@ export const useOrder = (orderId: number) => {
error,
};
}

export const useShippingAndProductsInfo = (orderId: number) => {
const { context } = useSession();
const params = new URLSearchParams({ context }).toString();
const shouldFetch = context && orderId !== undefined;

// Shipping addresses and products are not included in the order data and need to be fetched separately
const { data, error } = useSWR<ShippingAndProductsInfo, ErrorProps>(
shouldFetch ? [`/api/orders/${orderId}/shipping_products`, params] : null, fetcher
);

return {
order: data,
isLoading: !data && !error,
error,
};
}
2 changes: 1 addition & 1 deletion pages/api/orders/[orderId]/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default async function orderId(req: NextApiRequest, res: NextApiResponse)

try {
const { accessToken, storeHash } = await getSession(req);
const bigcommerce = bigcommerceClient(accessToken, storeHash , 'v2');
const bigcommerce = bigcommerceClient(accessToken, storeHash, 'v2');

switch (method) {
case 'GET': {
Expand Down
34 changes: 34 additions & 0 deletions pages/api/orders/[orderId]/shipping_products.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { NextApiRequest, NextApiResponse } from 'next';
import { bigcommerceClient, getSession } from '../../../../lib/auth';

export default async function shippingAddressesAndProducts(req: NextApiRequest, res: NextApiResponse) {
const {
query: { orderId },
method,
} = req;

try {
const { accessToken, storeHash } = await getSession(req);
const bigcommerce = bigcommerceClient(accessToken, storeHash, 'v2');

switch (method) {
case 'GET': {
const shipping_addresses = await bigcommerce.get(`/orders/${orderId}/shipping_addresses`);
const products = await bigcommerce.get(`/orders/${orderId}/products`);

res.status(200).json({ shipping_addresses, products });

break;
}

default: {
res.setHeader('Allow', ['GET']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}

} catch (error) {
const { message, response } = error;
res.status(response?.status || 500).json({ message });
}
}
77 changes: 77 additions & 0 deletions pages/orders/[orderId]/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Button, Flex, H1, Panel, StatefulTable, Text } from '@bigcommerce/big-design';
import { useRouter } from 'next/router';

import ErrorMessage from '../../../components/error';
import Loading from '../../../components/loading';
import { useShippingAndProductsInfo } from '../../../lib/hooks';
import { BillingAddress, OrderProduct, ShippingAndProductsInfo } from '../../../types';

const InternalOrderPage = (order: ShippingAndProductsInfo) => {
const { shipping_addresses = [], products = [] } = order
const items = shipping_addresses.map(address => {
const addressProducts = products.filter(({ order_address_id }) => order_address_id === address.id);

return { address, addressProducts }
});

const Address = (address: BillingAddress) => (
<>
<Text margin='none'>{address.first_name} {address.last_name}</Text>
<Text margin='none'>{address.street_1} {address.street_2}</Text>
<Text margin='none'>{address.city}, {address.state} {address.zip}</Text>
</>
);

const renderOrderProducts = (addressProducts: OrderProduct[]) => (
<>
{addressProducts.map(product => <Text key={product.id}>{product.name}</Text>)}
</>
);

const renderOrderProductsQuantities = (addressProducts: OrderProduct[]) => (
<>
{addressProducts.map(product => <Text key={product.id}>{product.quantity}</Text>)}
</>
);

return (
<>
<Flex justifyContent="space-between" marginBottom="medium">
<H1>Order details</H1>
<Button>Create shipment</Button>
</Flex>
<Panel>
<StatefulTable
columns={[
{ header: 'Ship to', hash: 'address', render: ({ address }) => <Address {...address} /> },
{
header: 'Products',
hash: 'addressProducts',
render: ({ addressProducts }) => renderOrderProducts(addressProducts),
},
{
header: 'Quantity',
hash: 'quantity',
render: ({ addressProducts }) => renderOrderProductsQuantities(addressProducts),
},
]}
items={items}
/>
</Panel>
</>
);
};

const OrderPage = () => {
const router = useRouter();
const { orderId } = router.query;
const { isLoading, order, error }= useShippingAndProductsInfo(parseInt(`${orderId}`, 10));

if (isLoading) return <Loading />;

if (error) return <ErrorMessage error={error} />;

return <InternalOrderPage {...order} />;
};

export default OrderPage;
25 changes: 25 additions & 0 deletions types/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,26 @@ export interface BillingAddress {
country: string;
}

export interface ShippingAddress {
[key: string]: unknown;
first_name: string;
last_name: string;
street_1: string;
street_2: string;
city: string;
state: string;
zip: string;
country: string;
}

export interface OrderProduct {
[key: string]: unknown;
id: number;
name: string;
quantity: number;
order_address_id: number;
}

export interface Order {
// Additional fields exist, type as needed
[key: string]: unknown;
Expand All @@ -28,3 +48,8 @@ export interface Order {
total_inc_tax: string;
total_tax: string;
}

export interface ShippingAndProductsInfo {
shipping_addresses: ShippingAddress[];
products: OrderProduct[];
}

0 comments on commit 440b28e

Please sign in to comment.