chore: transfer repo
This commit is contained in:
115
components/cart/add-to-cart.tsx
Normal file
115
components/cart/add-to-cart.tsx
Normal file
@@ -0,0 +1,115 @@
|
||||
'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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user