import {useOptimisticCart} from '@shopify/hydrogen'; import {Link} from 'react-router'; import type {CartApiQueryFragment} from 'storefrontapi.generated'; import {useAside} from '~/components/Aside'; import {CartLineItem, type CartLine} from '~/components/CartLineItem'; import {CartSummary} from './CartSummary'; export type CartLayout = 'page' | 'aside'; export type CartMainProps = { cart: CartApiQueryFragment | null; layout: CartLayout; }; export type LineItemChildrenMap = {[parentId: string]: CartLine[]}; /** Returns a map of all line items and their children. */ function getLineItemChildrenMap(lines: CartLine[]): LineItemChildrenMap { const children: LineItemChildrenMap = {}; for (const line of lines) { if ('parentRelationship' in line && line.parentRelationship?.parent) { const parentId = line.parentRelationship.parent.id; if (!children[parentId]) children[parentId] = []; children[parentId].push(line); } if ('lineComponents' in line) { const children = getLineItemChildrenMap(line.lineComponents); for (const [parentId, childIds] of Object.entries(children)) { if (!children[parentId]) children[parentId] = []; children[parentId].push(...childIds); } } } return children; } /** * The main cart component that displays the cart items and summary. * It is used by both the /cart route and the cart aside dialog. */ export function CartMain({layout, cart: originalCart}: CartMainProps) { // The useOptimisticCart hook applies pending actions to the cart // so the user immediately sees feedback when they modify the cart. const cart = useOptimisticCart(originalCart); const linesCount = Boolean(cart?.lines?.nodes?.length || 0); const withDiscount = cart && Boolean(cart?.discountCodes?.filter((code) => code.applicable)?.length); const className = `cart-main ${withDiscount ? 'with-discount' : ''}`; const cartHasItems = cart?.totalQuantity ? cart.totalQuantity > 0 : false; const childrenMap = getLineItemChildrenMap(cart?.lines?.nodes ?? []); return (
); } function CartEmpty({ hidden = false, }: { hidden: boolean; layout?: CartMainProps['layout']; }) { const {close} = useAside(); return ( ); }