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 (
Line items
{(cart?.lines?.nodes ?? []).map((line) => {
// we do not render non-parent lines at the root of the cart
if (
'parentRelationship' in line &&
line.parentRelationship?.parent
) {
return null;
}
return (
Looks like you haven’t added anything yet, let’s get you started!