Skip to content

Commit

Permalink
fulfill selected
Browse files Browse the repository at this point in the history
  • Loading branch information
SheepTester committed May 4, 2024
1 parent 7629d92 commit f93f5d1
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 32 deletions.
55 changes: 38 additions & 17 deletions src/components/admin/store/PickupOrder/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Button, Typography } from '@/components/common';
import { OrderStatusIndicator } from '@/components/store';
import { StoreAPI } from '@/lib/api';
import { PublicOrderItemWithQuantity, PublicOrderWithItems } from '@/lib/types/apiResponses';
import { UUID } from '@/lib/types';
import { PublicOrderWithItems } from '@/lib/types/apiResponses';
import { OrderStatus } from '@/lib/types/enums';
import { getOrderItemQuantities, reportError } from '@/lib/utils';
import { getOrderItemQuantities, itemToString, reportError } from '@/lib/utils';
import { useState } from 'react';
import styles from './style.module.scss';

interface PickupOrderProps {
Expand All @@ -13,27 +15,23 @@ interface PickupOrderProps {
onOrderUpdate: (orders: PublicOrderWithItems) => void;
}

const itemToString = (item: PublicOrderItemWithQuantity): string => {
if (item.option.metadata !== null)
return `${item.option.item.itemName} (${item.option.metadata.type}: ${item.option.metadata.value})`;
return item.option.item.itemName;
};

const PickupOrder = ({ token, canFulfill, order, onOrderUpdate }: PickupOrderProps) => {
const showFulfill = canFulfill && order.status === OrderStatus.PLACED;
const itemQuantities = getOrderItemQuantities(order.items);
const [unselected, setUnselected] = useState(new Set<UUID>());

return (
<tr className={styles.row}>
<td>
<Typography variant="h5/regular">{`${order.user.firstName} ${order.user.lastName}`}</Typography>
<OrderStatusIndicator orderStatus={order.status} />
{showFulfill && itemQuantities.length > 1 ? (
{canFulfill ? (
<Button
size="small"
onClick={async () => {
try {
const newOrder = await StoreAPI.fulfillOrderPickup(token, order.uuid, order.items);
const itemUuids = order.items.map(item => item.uuid);
const items = order.items.filter(item => !unselected.has(item.uuid));
const newOrder = await StoreAPI.fulfillOrderPickup(token, order.uuid, items);
const itemUuids = items.map(item => item.uuid);
onOrderUpdate({
...newOrder,
items: order.items.map(item =>
Expand All @@ -45,18 +43,41 @@ const PickupOrder = ({ token, canFulfill, order, onOrderUpdate }: PickupOrderPro
}
}}
>
Fulfill
Fulfill {unselected.size > 0 ? 'Selected' : 'All'}
</Button>
) : null}
</td>
<td>
<ul className={styles.itemList}>
{itemQuantities.map(item => {
return (
<li key={item.uuid}>
<Typography variant="h5/regular">{`${item.quantity} x ${itemToString(
item
)}`}</Typography>
<li key={item.uuids[0]}>
<Typography variant="h5/regular">
{`${item.quantity} x ${itemToString(item)}`}{' '}
{(order.status === OrderStatus.FULFILLED ||
order.status === OrderStatus.PARTIALLY_FULFILLED) &&
!item.fulfilled ? (
<span className={styles.notFulfilled}>Not fulfilled</span>
) : null}
</Typography>
{canFulfill
? item.uuids.map(uuid => (
<input
key={uuid}
type="checkbox"
checked={!unselected.has(uuid)}
onChange={e => {
const copy = new Set(unselected);
if (e.currentTarget.checked) {
copy.delete(uuid);
} else {
copy.add(uuid);
}
setUnselected(copy);
}}
/>
))
: null}
</li>
);
})}
Expand Down
6 changes: 6 additions & 0 deletions src/components/admin/store/PickupOrder/style.module.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@use 'src/styles/vars.scss' as vars;

.row {
border-top: 1px solid var(--theme-accent-line-2);

Expand All @@ -13,6 +15,10 @@
display: flex;
flex-wrap: wrap;
gap: 10px;

.notFulfilled {
color: vars.$red;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export type Styles = {
itemList: string;
notFulfilled: string;
row: string;
};

Expand Down
17 changes: 6 additions & 11 deletions src/components/admin/store/PickupOrdersPrepareDisplay/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import PickupOrder from '@/components/admin/store/PickupOrder';
import { Typography } from '@/components/common';
import { PublicOrderItemWithQuantity, PublicOrderWithItems } from '@/lib/types/apiResponses';
import { getOrderItemQuantities } from '@/lib/utils';
import { PublicOrderWithItems } from '@/lib/types/apiResponses';
import { OrderStatus } from '@/lib/types/enums';
import { OrderItemQuantity, getOrderItemQuantities, itemToString } from '@/lib/utils';
import { useMemo } from 'react';
import styles from './style.module.scss';

Expand All @@ -12,19 +13,13 @@ interface PickupOrdersDisplayPrepareProps {
onOrderUpdate: (orders: PublicOrderWithItems[]) => void;
}

const itemToString = (item: PublicOrderItemWithQuantity): string => {
if (item.option.metadata !== null)
return `${item.option.item.itemName} (${item.option.metadata.type}: ${item.option.metadata.value})`;
return item.option.item.itemName;
};

const PickupOrdersPrepareDisplay = ({
token,
canFulfill,
orders,
onOrderUpdate,
}: PickupOrdersDisplayPrepareProps) => {
const itemBreakdown: PublicOrderItemWithQuantity[] = useMemo(() => {
const itemBreakdown: OrderItemQuantity[] = useMemo(() => {
// Concatenate all items together into one large order to display the item breakdown.
const allItems = orders.flatMap(a => a.items);
return getOrderItemQuantities(allItems);
Expand All @@ -48,7 +43,7 @@ const PickupOrdersPrepareDisplay = ({
<tbody>
{itemBreakdown.map(item => {
return (
<tr key={item.uuid}>
<tr key={item.uuids[0]}>
<td>
<Typography variant="h5/regular">{item.quantity}</Typography>
</td>
Expand Down Expand Up @@ -77,7 +72,7 @@ const PickupOrdersPrepareDisplay = ({
<tbody>
{orders.map(order => (
<PickupOrder
canFulfill={canFulfill}
canFulfill={canFulfill && order.status === OrderStatus.PLACED}
order={order}
onOrderUpdate={newOrder =>
onOrderUpdate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@
padding: 1rem 1.5rem;
text-align: left;
}

td {
padding: 1.5rem;
}

tbody tr {
border-top: 1px solid var(--theme-accent-line-2);
}
}
17 changes: 13 additions & 4 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import defaultProfilePictures from '@/lib/constants/profilePictures';
import ranks from '@/lib/constants/ranks';
import showToast from '@/lib/showToast';
import type { URL } from '@/lib/types';
import type { URL, UUID } from '@/lib/types';
import type {
ApiResponse,
CustomErrorBody,
Expand Down Expand Up @@ -388,25 +388,34 @@ export const isOrderPickupEvent = (
event: PublicOrderPickupEvent | PublicEvent
): event is PublicOrderPickupEvent => 'status' in event;

export type OrderItemQuantity = Omit<PublicOrderItemWithQuantity, 'uuid'> & { uuids: UUID[] };

/**
* Condenses a list of ordered items into unique items with quantities.
*/
export const getOrderItemQuantities = (items: PublicOrderItem[]): PublicOrderItemWithQuantity[] => {
const itemMap = new Map<string, PublicOrderItemWithQuantity>();
export const getOrderItemQuantities = (items: PublicOrderItem[]): OrderItemQuantity[] => {
const itemMap = new Map<string, OrderItemQuantity>();

items.forEach(item => {
const hash = `${item.option.uuid} ${item.fulfilled}`;
const existingItem = itemMap.get(hash);
if (existingItem) {
existingItem.quantity += 1;
existingItem.uuids.push(item.uuid);
} else {
itemMap.set(hash, { ...item, quantity: 1 });
itemMap.set(hash, { ...item, quantity: 1, uuids: [item.uuid] });
}
});

return Array.from(itemMap.values());
};

export const itemToString = (item: Pick<PublicOrderItem, 'option'>): string => {
if (item.option.metadata !== null)
return `${item.option.item.itemName} (${item.option.metadata.type}: ${item.option.metadata.value})`;
return item.option.item.itemName;
};

export function isEnum<T extends Record<string, string>>(
Enum: T,
value: string
Expand Down

0 comments on commit f93f5d1

Please sign in to comment.