diff --git a/src/components/admin/store/PickupOrdersPrepareDisplay/index.tsx b/src/components/admin/store/PickupOrdersPrepareDisplay/index.tsx
index 7848cdf7..56f8dd11 100644
--- a/src/components/admin/store/PickupOrdersPrepareDisplay/index.tsx
+++ b/src/components/admin/store/PickupOrdersPrepareDisplay/index.tsx
@@ -1,6 +1,6 @@
import { Typography } from '@/components/common';
-import { PublicOrderItemWithQuantity, PublicOrderWithItems } from '@/lib/types/apiResponses';
-import { getOrderItemQuantities } from '@/lib/utils';
+import { PublicOrderWithItems } from '@/lib/types/apiResponses';
+import { OrderItemQuantity, getOrderItemQuantities } from '@/lib/utils';
import { useMemo } from 'react';
import styles from './style.module.scss';
@@ -8,14 +8,14 @@ interface PickupOrdersDisplayPrepareProps {
orders: PublicOrderWithItems[];
}
-const itemToString = (item: PublicOrderItemWithQuantity): string => {
+const itemToString = (item: OrderItemQuantity): 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 = ({ orders }: 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);
@@ -34,7 +34,7 @@ const PickupOrdersPrepareDisplay = ({ orders }: PickupOrdersDisplayPrepareProps)
{itemBreakdown.map(item => {
return (
-
{item.quantity}
|
@@ -65,10 +65,10 @@ const PickupOrdersPrepareDisplay = ({ orders }: PickupOrdersDisplayPrepareProps)
{itemQuantities.map(item => (
- -
- {`${item.quantity} x ${itemToString(
- item
- )}`}
+
-
+ {`${item.fulfilled ? '✅' : '❌'} ${
+ item.quantity
+ } x ${itemToString(item)}`}
))}
diff --git a/src/components/store/OrderSummary/index.tsx b/src/components/store/OrderSummary/index.tsx
index f8d9810c..1af3d397 100644
--- a/src/components/store/OrderSummary/index.tsx
+++ b/src/components/store/OrderSummary/index.tsx
@@ -5,21 +5,17 @@ import PickupEventPreviewModal from '@/components/store/PickupEventPreviewModal'
import { config } from '@/lib';
import { PublicOrderPickupEvent, PublicOrderWithItems } from '@/lib/types/apiResponses';
import { OrderStatus } from '@/lib/types/enums';
-import { capitalize, getDefaultOrderItemPhoto, getOrderItemQuantities } from '@/lib/utils';
+import {
+ OrderItemQuantity,
+ capitalize,
+ getDefaultOrderItemPhoto,
+ getOrderItemQuantities,
+} from '@/lib/utils';
import Image from 'next/image';
import Link from 'next/link';
import { useState } from 'react';
import styles from './style.module.scss';
-interface OrderSummaryProps {
- order: PublicOrderWithItems;
- orderStatus: OrderStatus;
- futurePickupEvents: PublicOrderPickupEvent[];
- pickupEvent: PublicOrderPickupEvent;
- reschedulePickupEvent: (pickup: PublicOrderPickupEvent) => Promise;
- cancelOrder: () => Promise;
-}
-
const isOrderActionable = (status: OrderStatus, pickupEvent: PublicOrderPickupEvent): boolean => {
if (status === OrderStatus.CANCELLED || status === OrderStatus.FULFILLED) {
// If the order is cancelled by the user or fulfilled, no further action can be taken.
@@ -30,16 +26,108 @@ const isOrderActionable = (status: OrderStatus, pickupEvent: PublicOrderPickupEv
const now = new Date();
const eventStart = new Date(pickupEvent.start);
eventStart.setDate(eventStart.getDate() - 2);
- if (
- now > eventStart &&
- status !== OrderStatus.PICKUP_MISSED &&
- status !== OrderStatus.PICKUP_CANCELLED
- ) {
+ if (status === OrderStatus.PLACED && now > eventStart) {
return false;
}
return true;
};
+interface OrderItemPreviewProps {
+ item: OrderItemQuantity;
+ orderStatus: OrderStatus;
+}
+
+const OrderItemPreview = ({ item, orderStatus }: OrderItemPreviewProps) => {
+ if (item.fulfilled && orderStatus === OrderStatus.PLACED) {
+ /*
+ * When a partially fulfilled order is rescheduled,
+ * the status is changed to PLACED, but all items remain (some as fulfilled).
+ * These items should be hidden.
+ */
+ return null;
+ }
+
+ return (
+
+
+
+
+
+ {item.option.item.itemName}
+
+ Price:
+
+
+
+ Quantity:
+ {item.quantity}
+
+ {item.option.metadata ? (
+
+ {`${capitalize(
+ item.option.metadata.type
+ )}: `}
+ {item.option.metadata.value}
+
+ ) : null}
+
+
+ );
+};
+
+interface OrderItemsSummaryProps {
+ items: OrderItemQuantity[];
+ orderStatus: OrderStatus;
+}
+
+const OrderItemsSummary = ({ items, orderStatus }: OrderItemsSummaryProps) => {
+ if (orderStatus !== OrderStatus.PARTIALLY_FULFILLED) {
+ return (
+ <>
+ {items.map(item => (
+
+ ))}
+ >
+ );
+ }
+ const pickedUpItems = items.filter(item => item.fulfilled);
+ const notPickedUpItems = items.filter(item => !item.fulfilled);
+
+ return (
+
+
+ Items Picked Up:
+
+ {pickedUpItems.map(item => (
+
+ ))}
+
+
+
+ Awaiting Pickup:
+
+ {notPickedUpItems.map(item => (
+
+ ))}
+
+ );
+};
+
+interface OrderSummaryProps {
+ order: PublicOrderWithItems;
+ orderStatus: OrderStatus;
+ futurePickupEvents: PublicOrderPickupEvent[];
+ pickupEvent: PublicOrderPickupEvent;
+ reschedulePickupEvent: (pickup: PublicOrderPickupEvent) => Promise;
+ cancelOrder: () => Promise;
+}
+
const OrderSummary = ({
order,
orderStatus,
@@ -73,45 +161,7 @@ const OrderSummary = ({
onClose={() => setCancelModalOpen(false)}
cancelOrder={cancelOrder}
/>
- {items.map(item => (
-
-
-
-
-
- {item.option.item.itemName}
-
- Price:
-
-
-
- Quantity:
- {item.quantity}
-
- {item.option.metadata ? (
-
- {`${capitalize(
- item.option.metadata.type
- )}: `}
- {item.option.metadata.value}
-
- ) : null}
-
-
- ))}
+
diff --git a/src/components/store/OrderSummary/style.module.scss b/src/components/store/OrderSummary/style.module.scss
index abf27420..700ca3bb 100644
--- a/src/components/store/OrderSummary/style.module.scss
+++ b/src/components/store/OrderSummary/style.module.scss
@@ -3,6 +3,10 @@
.container {
margin-top: 0.75rem;
+ .partiallyFulfilledText {
+ padding: 0.75rem 1.5rem;
+ }
+
.itemInfo {
display: flex;
flex-direction: row;
@@ -36,8 +40,7 @@
.divider {
border-top: 1px solid var(--theme-elevated-stroke);
height: 0.1rem;
- margin: 0 1rem;
- margin-top: 0.75rem;
+ margin: 0.75rem 1rem;
width: auto;
}
diff --git a/src/components/store/OrderSummary/style.module.scss.d.ts b/src/components/store/OrderSummary/style.module.scss.d.ts
index 49ffe448..4f312057 100644
--- a/src/components/store/OrderSummary/style.module.scss.d.ts
+++ b/src/components/store/OrderSummary/style.module.scss.d.ts
@@ -7,6 +7,7 @@ export type Styles = {
itemInfo: string;
itemSummary: string;
label: string;
+ partiallyFulfilledText: string;
totalDiamonds: string;
totalPrice: string;
};
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
index 9ab7ac56..b35a2ca1 100644
--- a/src/lib/utils.ts
+++ b/src/lib/utils.ts
@@ -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,
@@ -314,7 +314,7 @@ export const getDefaultMerchItemPhoto = (
return NoImage.src;
};
-export const getDefaultOrderItemPhoto = (item: PublicOrderItem): string => {
+export const getDefaultOrderItemPhoto = (item: Pick ): string => {
if (item.option.item.uploadedPhoto) {
return item.option.item.uploadedPhoto;
}
@@ -385,18 +385,22 @@ export const isOrderPickupEvent = (
event: PublicOrderPickupEvent | PublicEvent
): event is PublicOrderPickupEvent => 'status' in event;
+export type OrderItemQuantity = Omit & { uuids: UUID[] };
+
/**
* Condenses a list of ordered items into unique items with quantities.
*/
-export const getOrderItemQuantities = (items: PublicOrderItem[]): PublicOrderItemWithQuantity[] => {
- const itemMap = new Map();
+export const getOrderItemQuantities = (items: PublicOrderItem[]): OrderItemQuantity[] => {
+ const itemMap = new Map();
items.forEach(item => {
- const existingItem = itemMap.get(item.option.uuid);
+ 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(item.option.uuid, { ...item, quantity: 1 });
+ itemMap.set(hash, { ...item, quantity: 1, uuids: [item.uuid] });
}
});
|