Files
sent-shop/components/cart/add-to-cart.tsx
2026-01-19 20:21:14 +01:00

116 lines
3.1 KiB
TypeScript

'use client';
import { Button } from '@/components/ui/Button';
import { addItem } from 'components/cart/actions';
import { useProduct } from 'components/product/product-context';
import { Product, ProductVariant } from 'lib/shopify/types';
import { useState, useTransition } from 'react';
import { useCart } from './cart-context';
function SubmitButton({
availableForSale,
selectedVariantId,
isLoading
}: {
availableForSale: boolean;
selectedVariantId: string | undefined;
isLoading: boolean;
}) {
if (!availableForSale) {
return (
<Button
disabled
variant="primary"
size="lg"
fullWidth
>
Out Of Stock
</Button>
);
}
if (!selectedVariantId) {
return (
<Button
aria-label="Please select an option"
disabled
variant="primary"
size="lg"
fullWidth
>
Please Select Options
</Button>
);
}
return (
<Button
aria-label="Add to cart"
disabled={isLoading}
variant="primary"
size="lg"
fullWidth
>
{isLoading ? 'Adding...' : 'Add to Cart'}
</Button>
);
}
export function AddToCart({ product, quantity = 1 }: { product: Product; quantity?: number }) {
const { variants, availableForSale } = product;
const { addCartItem } = useCart();
const { state } = useProduct();
const [isPending, startTransition] = useTransition();
const [isLoading, setIsLoading] = useState(false);
const variant = variants.find((variant: ProductVariant) =>
variant.selectedOptions.every((option) => option.value === state[option.name.toLowerCase()])
);
const defaultVariantId = variants.length === 1 ? variants[0]?.id : undefined;
const selectedVariantId = variant?.id || defaultVariantId;
const finalVariant = variants.find((variant) => variant.id === selectedVariantId)!;
const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
// Don't proceed if the form is already being processed
if (isLoading) return;
// Don't proceed if there's no variant ID
if (!selectedVariantId) return;
// Set loading state
setIsLoading(true);
// Use the quantity prop passed to the component
// No need to get it from formData since there's no quantity input in the form
const finalVariant = variants.find((v) => v.id === selectedVariantId);
if (!finalVariant) return;
// Call the server action to add the item to the cart
// @ts-ignore - We know our server action accepts quantity
addItem(null, selectedVariantId, quantity)
.then(() => {
// Add to context cart for immediate UI feedback
addCartItem(finalVariant, product, quantity);
});
// Add a small delay before removing loading state for better UX
setTimeout(() => {
setIsLoading(false);
}, 500);
};
return (
<form onSubmit={handleSubmit} className="w-full">
<SubmitButton
availableForSale={availableForSale}
selectedVariantId={selectedVariantId}
isLoading={isLoading}
/>
</form>
);
}