import { ChangeEvent, FocusEventHandler, useEffect, useState } from 'react'; import cn from 'clsx'; import Image from 'next/image'; import Link from 'next/link'; import s from './CartItem.module.css'; import { useUI } from '@components/ui/context'; import type { LineItem } from '@commerce/types/cart'; import usePrice from '@framework/product/use-price'; import useUpdateItem from '@framework/cart/use-update-item'; import useRemoveItem from '@framework/cart/use-remove-item'; import Quantity from '@components/ui/Quantity'; type ItemOption = { name: string; nameId: number; value: string; valueId: number; }; const placeholderImg = '/product-img-placeholder.svg'; const CartItem = ({ item, variant = 'default', currencyCode, ...rest }: { variant?: 'default' | 'display'; item: LineItem; currencyCode: string; }) => { const { closeSidebarIfPresent } = useUI(); const [removing, setRemoving] = useState(false); const [quantity, setQuantity] = useState(item.quantity); const removeItem = useRemoveItem(); const updateItem = useUpdateItem({ item }); const { price } = usePrice({ amount: item.variant.price * item.quantity, baseAmount: item.variant.listPrice * item.quantity, currencyCode, }); const handleChange = async ({ target: { value }, }: ChangeEvent) => { setQuantity(Number(value)); await updateItem({ quantity: Number(value) }); }; const increaseQuantity = async (n = 1) => { const val = Number(quantity) + n; setQuantity(val); await updateItem({ quantity: val }); }; const handleRemove = async () => { setRemoving(true); try { await removeItem(item); } catch (error) { setRemoving(false); } }; // TODO: Add a type for this const options = (item as any).options; useEffect(() => { // Reset the quantity state if the item quantity changes if (item.quantity !== Number(quantity)) { setQuantity(item.quantity); } // TODO: currently not including quantity in deps is intended, but we should // do this differently as it could break easily // eslint-disable-next-line react-hooks/exhaustive-deps }, [item.quantity]); return (
  • closeSidebarIfPresent()} className={s.productImage} width={150} height={150} src={item.variant.image?.url || placeholderImg} alt={item.variant.image?.altText || 'Product Image'} unoptimized />
    closeSidebarIfPresent()} > {item.name} {options && options.length > 0 && (
    {options.map((option: ItemOption, i: number) => (
    {option.name} {option.name === 'Color' ? ( ) : ( {option.value} )} {i === options.length - 1 ? '' : }
    ))}
    )} {variant === 'display' && (
    {quantity}x
    )}
    {price}
    {variant === 'default' && ( increaseQuantity(1)} decrease={() => increaseQuantity(-1)} /> )}
  • ); }; export default CartItem;