diff --git a/app/home/(user)/_components/booking/time-slots.tsx b/app/home/(user)/_components/booking/time-slots.tsx index 58190b1..783b5f6 100644 --- a/app/home/(user)/_components/booking/time-slots.tsx +++ b/app/home/(user)/_components/booking/time-slots.tsx @@ -186,7 +186,7 @@ const TimeSlots = ({ return (
diff --git a/app/home/(user)/_components/cart/cart-form-content.tsx b/app/home/(user)/_components/cart/cart-form-content.tsx index 7082b74..3ec18ce 100644 --- a/app/home/(user)/_components/cart/cart-form-content.tsx +++ b/app/home/(user)/_components/cart/cart-form-content.tsx @@ -1,7 +1,11 @@ 'use client'; import { formatCurrency } from '@/packages/shared/src/utils'; -import { StoreCart, StoreCartLineItem } from '@medusajs/types'; +import { + StoreCart, + StoreCartLineItem, + StoreCartPromotion, +} from '@medusajs/types'; import { Loader2 } from 'lucide-react'; import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -30,7 +34,9 @@ export default function CartFormContent({ isInitiatingSession, getBalanceSummarySelection, }: { - cart: StoreCart; + cart: StoreCart & { + promotions: StoreCartPromotion[]; + }; synlabAnalyses: StoreCartLineItem[]; ttoServiceItems: EnrichedCartItem[]; unavailableLineItemIds?: string[]; diff --git a/app/home/(user)/_components/cart/cart-item.tsx b/app/home/(user)/_components/cart/cart-item.tsx index 7ec9406..a12074c 100644 --- a/app/home/(user)/_components/cart/cart-item.tsx +++ b/app/home/(user)/_components/cart/cart-item.tsx @@ -20,7 +20,7 @@ export default function CartItem({ } = useTranslation(); return ( - +

- {formatCurrency({ - value: item.total, - currencyCode, - locale: language, - })} + {item.total && + formatCurrency({ + value: item.total, + currencyCode, + locale: language, + })} diff --git a/app/home/(user)/_components/cart/cart-items.tsx b/app/home/(user)/_components/cart/cart-items.tsx index e0529e8..786f288 100644 --- a/app/home/(user)/_components/cart/cart-items.tsx +++ b/app/home/(user)/_components/cart/cart-items.tsx @@ -10,6 +10,7 @@ import { import { Trans } from '@kit/ui/trans'; import CartItem from './cart-item'; +import MobileCartItems from './mobile-cart-items'; export default function CartItems({ cart, @@ -25,37 +26,54 @@ export default function CartItems({ } return ( - - - - - - - - - - - - - - - - - - - + <> +
+ + + + + + + + + + + + + + + + + + + {items + .sort((a, b) => + (a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1, + ) + .map((item) => ( + + ))} + +
+ +

{items .sort((a, b) => (a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1, ) .map((item) => ( - ))} - - +
+ ); } diff --git a/app/home/(user)/_components/cart/cart-service-item.tsx b/app/home/(user)/_components/cart/cart-service-item.tsx index eed6fcd..73a20b6 100644 --- a/app/home/(user)/_components/cart/cart-service-item.tsx +++ b/app/home/(user)/_components/cart/cart-service-item.tsx @@ -1,76 +1,26 @@ 'use client'; -import { useState } from 'react'; - import { formatCurrency, formatDateAndTime } from '@/packages/shared/src/utils'; import { useTranslation } from 'react-i18next'; import { Button } from '@kit/ui/button'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogHeader, - DialogTitle, -} from '@kit/ui/dialog'; import { TableCell, TableRow } from '@kit/ui/table'; import { Trans } from '@kit/ui/trans'; -import BookingContainer from '../booking/booking-container'; import CartItemDelete from './cart-item-delete'; import { EnrichedCartItem } from './types'; -const EditCartServiceItemModal = ({ - item, - onComplete, -}: { - item: EnrichedCartItem | null; - onComplete: () => void; -}) => { - if (!item) return null; - - return ( - - - - - - - - - - -
- {item.product && item.reservation.countryCode ? ( - - ) : ( -

- -

- )} -
-
-
- ); -}; - export default function CartServiceItem({ item, currencyCode, isUnavailable, + setEditingItem, }: { item: EnrichedCartItem; currencyCode: string; isUnavailable?: boolean; + setEditingItem: (item: EnrichedCartItem | null) => void; }) { - const [editingItem, setEditingItem] = useState(null); const { i18n: { language }, } = useTranslation(); @@ -106,11 +56,12 @@ export default function CartServiceItem({
- {formatCurrency({ - value: item.total, - currencyCode, - locale: language, - })} + {item.total && + formatCurrency({ + value: item.total, + currencyCode, + locale: language, + })} @@ -137,10 +88,6 @@ export default function CartServiceItem({
)} - setEditingItem(null)} - /> ); } diff --git a/app/home/(user)/_components/cart/cart-service-items.tsx b/app/home/(user)/_components/cart/cart-service-items.tsx index ad5cc12..cedf44e 100644 --- a/app/home/(user)/_components/cart/cart-service-items.tsx +++ b/app/home/(user)/_components/cart/cart-service-items.tsx @@ -1,5 +1,14 @@ +import { useState } from 'react'; + import { StoreCart } from '@medusajs/types'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, +} from '@kit/ui/shadcn/dialog'; import { Table, TableBody, @@ -9,9 +18,52 @@ import { } from '@kit/ui/table'; import { Trans } from '@kit/ui/trans'; +import BookingContainer from '../booking/booking-container'; import CartServiceItem from './cart-service-item'; +import MobileCartServiceItems from './mobile-cart-service-items'; import { EnrichedCartItem } from './types'; +const EditCartServiceItemModal = ({ + item, + onComplete, +}: { + item: EnrichedCartItem | null; + onComplete: () => void; +}) => { + if (!item) return null; + + return ( + + + + + + + + + + +
+ {item.product && item.reservation.countryCode ? ( + + ) : ( +

+ +

+ )} +
+
+
+ ); +}; + export default function CartServiceItems({ cart, items, @@ -23,50 +75,75 @@ export default function CartServiceItems({ productColumnLabelKey: string; unavailableLineItemIds?: string[]; }) { + const [editingItem, setEditingItem] = useState(null); if (!items || items.length === 0) { return null; } return ( - - - - - - - - - - - - - - - - - - - - - - - - - - + <> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + {items + .sort((a, b) => + (a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1, + ) + .map((item) => ( + + ))} + +
+
{items .sort((a, b) => (a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1, ) .map((item) => ( - ))} - - +
+ + setEditingItem(null)} + /> + ); } diff --git a/app/home/(user)/_components/cart/discount-code.tsx b/app/home/(user)/_components/cart/discount-code.tsx index d4ca87f..57379aa 100644 --- a/app/home/(user)/_components/cart/discount-code.tsx +++ b/app/home/(user)/_components/cart/discount-code.tsx @@ -3,7 +3,7 @@ import React, { useState } from 'react'; import { convertToLocale } from '@lib/util/money'; -import { StoreCart, StorePromotion } from '@medusajs/types'; +import { StoreCart, StoreCartPromotion } from '@medusajs/types'; import { Badge, Text } from '@medusajs/ui'; import Trash from '@modules/common/icons/trash'; import { useFormContext } from 'react-hook-form'; @@ -24,7 +24,7 @@ export default function DiscountCode({ cart, }: { cart: StoreCart & { - promotions: StorePromotion[]; + promotions: StoreCartPromotion[]; }; }) { const { t } = useTranslation('cart'); diff --git a/app/home/(user)/_components/cart/index.tsx b/app/home/(user)/_components/cart/index.tsx index e6db902..092b5a9 100644 --- a/app/home/(user)/_components/cart/index.tsx +++ b/app/home/(user)/_components/cart/index.tsx @@ -4,7 +4,11 @@ import { useCallback, useState } from 'react'; import { useRouter } from 'next/navigation'; -import { StoreCart, StoreCartLineItem } from '@medusajs/types'; +import { + StoreCart, + StoreCartLineItem, + StoreCartPromotion, +} from '@medusajs/types'; import { useTranslation } from 'react-i18next'; import { AccountBalanceSummary } from '@kit/accounts/services/account-balance.service'; @@ -23,7 +27,11 @@ export default function Cart({ balanceSummary, }: { accountId: string; - cart: StoreCart | null; + cart: + | (StoreCart & { + promotions: StoreCartPromotion[]; + }) + | null; synlabAnalyses: StoreCartLineItem[]; ttoServiceItems: EnrichedCartItem[]; balanceSummary: AccountBalanceSummary | null; diff --git a/app/home/(user)/_components/cart/mobile-cart-items.tsx b/app/home/(user)/_components/cart/mobile-cart-items.tsx new file mode 100644 index 0000000..9b21f86 --- /dev/null +++ b/app/home/(user)/_components/cart/mobile-cart-items.tsx @@ -0,0 +1,56 @@ +import React from 'react'; + +import { formatCurrency } from '@/packages/shared/src/utils'; +import { StoreCartLineItem } from '@medusajs/types'; +import { useTranslation } from 'react-i18next'; + +import { Table, TableBody } from '@kit/ui/shadcn/table'; + +import MobileCartRow from './mobile-cart-row'; + +const MobileCartItems = ({ + item, + currencyCode, + productColumnLabelKey, +}: { + item: StoreCartLineItem; + currencyCode: string; + productColumnLabelKey: string; +}) => { + const { + i18n: { language }, + } = useTranslation(); + + return ( + + + + + + + +
+ ); +}; + +export default MobileCartItems; diff --git a/app/home/(user)/_components/cart/mobile-cart-row.tsx b/app/home/(user)/_components/cart/mobile-cart-row.tsx new file mode 100644 index 0000000..9e31234 --- /dev/null +++ b/app/home/(user)/_components/cart/mobile-cart-row.tsx @@ -0,0 +1,29 @@ +import React from 'react'; + +import { Trans } from '@kit/ui/makerkit/trans'; +import { TableCell, TableHead, TableRow } from '@kit/ui/shadcn/table'; + +const MobileCartRow = ({ + titleKey, + value, +}: { + titleKey?: string; + value?: string | number; +}) => ( + + + + + + +

+ {value} +

+
+
+); + +export default MobileCartRow; diff --git a/app/home/(user)/_components/cart/mobile-cart-service-items.tsx b/app/home/(user)/_components/cart/mobile-cart-service-items.tsx new file mode 100644 index 0000000..d73b929 --- /dev/null +++ b/app/home/(user)/_components/cart/mobile-cart-service-items.tsx @@ -0,0 +1,91 @@ +import React from 'react'; + +import { formatCurrency, formatDateAndTime } from '@/packages/shared/src/utils'; +import { useTranslation } from 'react-i18next'; + +import { Trans } from '@kit/ui/makerkit/trans'; +import { Button } from '@kit/ui/shadcn/button'; +import { Table, TableBody, TableCell, TableRow } from '@kit/ui/shadcn/table'; + +import CartItemDelete from './cart-item-delete'; +import MobileCartRow from './mobile-cart-row'; +import { EnrichedCartItem } from './types'; + +const MobileCartServiceItems = ({ + item, + currencyCode, + isUnavailable, + productColumnLabelKey, + setEditingItem, +}: { + item: EnrichedCartItem; + currencyCode: string; + isUnavailable?: boolean; + productColumnLabelKey: string; + setEditingItem: (item: EnrichedCartItem | null) => void; +}) => { + const { + i18n: { language }, + } = useTranslation(); + + return ( + + + + + + + + + + + + + + + + + {isUnavailable && ( + + + + + + )} + +
+ ); +}; + +export default MobileCartServiceItems; diff --git a/packages/features/medusa-storefront/src/lib/data/cart.ts b/packages/features/medusa-storefront/src/lib/data/cart.ts index a252159..d82cefc 100644 --- a/packages/features/medusa-storefront/src/lib/data/cart.ts +++ b/packages/features/medusa-storefront/src/lib/data/cart.ts @@ -5,7 +5,7 @@ import { redirect } from 'next/navigation'; import { sdk } from '@lib/config'; import medusaError from '@lib/util/medusa-error'; -import { HttpTypes, StoreCart } from '@medusajs/types'; +import { HttpTypes, StoreCart, StoreCartPromotion } from '@medusajs/types'; import { getLogger } from '@kit/shared/logger'; @@ -25,7 +25,9 @@ import { getRegion } from './regions'; * @param cartId - optional - The ID of the cart to retrieve. * @returns The cart object if found, or null if not found. */ -export async function retrieveCart(cartId?: string) { +export async function retrieveCart( + cartId?: string, +): Promise<(StoreCart & { promotions: StoreCartPromotion[] }) | null> { const id = cartId || (await getCartId()); if (!id) {