hotschpotsh/Pottery-website/components/Cart.tsx

132 lines
8.2 KiB
TypeScript

import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { useNavigate } from 'react-router-dom';
import { useStore } from '../src/context/StoreContext';
const Cart: React.FC = () => {
const { cart, isCartOpen, setCartOpen, removeFromCart, updateQuantity } = useStore();
const navigate = useNavigate();
const subtotal = cart.reduce((total, item) => total + (item.price * item.quantity), 0);
const handleCheckout = () => {
setCartOpen(false);
navigate('/checkout');
};
return (
<AnimatePresence>
{isCartOpen && (
<>
{/* Backdrop */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setCartOpen(false)}
className="fixed inset-0 bg-black/30 backdrop-blur-sm z-[60]"
/>
{/* Drawer */}
<motion.div
initial={{ x: '100%' }}
animate={{ x: 0 }}
exit={{ x: '100%' }}
transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}
className="fixed top-0 right-0 h-full w-full max-w-md bg-white dark:bg-stone-950 z-[70] shadow-2xl flex flex-col"
>
{/* Header */}
<div className="p-8 border-b border-stone-100 dark:border-stone-900 flex justify-between items-center">
<h2 className="font-display text-2xl uppercase tracking-widest text-text-main dark:text-white">Your Bag</h2>
<button
onClick={() => setCartOpen(false)}
className="p-2 hover:bg-stone-50 dark:hover:bg-stone-900 rounded-full transition-colors"
>
<span className="material-symbols-outlined text-stone-500">close</span>
</button>
</div>
{/* Items List */}
<div className="flex-1 overflow-y-auto p-8 space-y-8">
{cart.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-stone-400 space-y-4">
<span className="material-symbols-outlined text-4xl font-light">shopping_bag</span>
<p className="font-light tracking-wide uppercase text-xs">Your bag is empty</p>
<button
onClick={() => setCartOpen(false)}
className="text-text-main dark:text-white underline underline-offset-4 text-xs uppercase tracking-widest pt-4"
>
Start Shopping
</button>
</div>
) : (
cart.map((item) => (
<div key={item.id} className="flex gap-6 group">
<div className="w-24 aspect-[4/5] bg-stone-100 dark:bg-stone-900 overflow-hidden rounded-sm flex-shrink-0">
<img src={item.image} alt={item.title} className="w-full h-full object-cover" />
</div>
<div className="flex-1 flex flex-col justify-between py-1">
<div className="flex justify-between items-start">
<div>
<h3 className="font-display text-lg text-text-main dark:text-white">{item.title}</h3>
<p className="text-xs text-stone-500 uppercase tracking-widest mt-1">Ref. {item.number}</p>
</div>
<button
onClick={() => removeFromCart(item.id)}
className="text-stone-300 hover:text-red-400 transition-colors"
>
<span className="material-symbols-outlined text-sm">delete</span>
</button>
</div>
<div className="flex justify-between items-end">
<div className="flex items-center border border-stone-100 dark:border-stone-800 rounded-sm">
<button
onClick={() => updateQuantity(item.id, item.quantity - 1)}
className="px-2 py-1 hover:bg-stone-50 dark:hover:bg-stone-900 transition-colors"
>
<span className="material-symbols-outlined text-xs">remove</span>
</button>
<span className="px-3 text-xs font-medium w-8 text-center">{item.quantity}</span>
<button
onClick={() => updateQuantity(item.id, item.quantity + 1)}
className="px-2 py-1 hover:bg-stone-50 dark:hover:bg-stone-900 transition-colors"
>
<span className="material-symbols-outlined text-xs">add</span>
</button>
</div>
<p className="text-sm font-light text-text-main dark:text-white">${(item.price * item.quantity).toFixed(2)}</p>
</div>
</div>
</div>
))
)}
</div>
{/* Footer */}
{cart.length > 0 && (
<div className="p-8 border-t border-stone-100 dark:border-stone-900 space-y-6">
<div className="flex justify-between items-center bg-stone-50 dark:bg-stone-900/50 p-6 rounded-sm">
<span className="text-xs uppercase tracking-widest text-stone-500">Subtotal</span>
<span className="text-xl font-display text-text-main dark:text-white">${subtotal.toFixed(2)}</span>
</div>
<button
onClick={handleCheckout}
type="button"
className="w-full bg-black dark:bg-white text-white dark:text-black py-5 uppercase tracking-[0.3em] text-xs font-bold hover:opacity-90 transition-opacity shadow-xl"
>
Proceed to Checkout
</button>
<p className="text-[10px] text-center text-stone-400 uppercase tracking-widest italic">
Shipping & taxes calculated at checkout
</p>
</div>
)}
</motion.div>
</>
)}
</AnimatePresence>
);
};
export default Cart;