'use client'; import clsx from 'clsx'; import { addItem } from 'components/cart/actions'; import LoadingDots from 'components/loading-dots'; import { ProductVariant } from 'lib/shopify/types'; import { useTranslations } from 'next-intl'; import { useRouter, useSearchParams } from 'next/navigation'; import { useTransition } from 'react'; export function AddToCart({ variants, availableForSale }: { variants: ProductVariant[]; availableForSale: boolean; }) { const router = useRouter(); const searchParams = useSearchParams(); const t = useTranslations('Index'); const [isPending, startTransition] = useTransition(); const defaultVariantId = variants.length === 1 ? variants[0]?.id : undefined; const variant = variants.find((variant: ProductVariant) => variant.selectedOptions.every( (option) => option.value === searchParams.get(option.name.toLowerCase()) ) ); const selectedVariantId = variant?.id || defaultVariantId; const title = !availableForSale ? 'Out of stock' : !selectedVariantId ? 'Please select options' : undefined; return ( <button aria-label="Add item to cart" disabled={isPending || !availableForSale || !selectedVariantId} title={title} onClick={() => { // Safeguard in case someone messes with `disabled` in devtools. if (!availableForSale || !selectedVariantId) return; startTransition(async () => { const error = await addItem(selectedVariantId); if (error) { // Trigger the error boundary in the root error.js throw new Error(error.toString()); } router.refresh(); }); }} className={clsx( 'relative flex w-full items-center justify-center bg-white p-4 font-serif text-xl tracking-wide text-black hover:opacity-90', { 'cursor-not-allowed opacity-60 hover:opacity-60': !availableForSale || !selectedVariantId, 'cursor-not-allowed': isPending } )} > {!isPending ? ( <span>{availableForSale ? t('cart.add') : t('cart.out-of-stock')}</span> ) : ( <LoadingDots className="my-3 bg-black" /> )} </button> ); }