71 lines
4.2 KiB
TypeScript
71 lines
4.2 KiB
TypeScript
'use client'
|
|
import { useRouter } from 'next/navigation'
|
|
import Link from 'next/link'
|
|
import Image from 'next/image'
|
|
import { useVulaCart } from '@/hooks/useVulaCart'
|
|
import { ArrowRight, Minus, Plus, ShoppingBag, Trash2 } from 'lucide-react'
|
|
|
|
function fmt(amount: number) { return `R${(amount / 100).toFixed(2)}` }
|
|
|
|
export default function CartPage() {
|
|
const { items, subtotal, itemCount, updateQty, removeFromCart } = useVulaCart()
|
|
const router = useRouter()
|
|
|
|
if (!itemCount) return (
|
|
<main className="min-h-screen bg-background flex flex-col items-center justify-center gap-6 text-center px-4">
|
|
<ShoppingBag className="w-16 h-16 text-muted-foreground" />
|
|
<h2 className="text-2xl font-semibold">Your cart is empty</h2>
|
|
<Link href="/products" className="bg-primary text-primary-foreground px-6 py-3 rounded-lg font-medium hover:opacity-90 transition-opacity">
|
|
Continue Shopping
|
|
</Link>
|
|
</main>
|
|
)
|
|
|
|
return (
|
|
<main className="min-h-screen bg-background py-12 px-4">
|
|
<div className="max-w-4xl mx-auto">
|
|
<h1 className="text-3xl font-bold mb-8">Your Cart ({itemCount} item{itemCount !== 1 ? 's' : ''})</h1>
|
|
<div className="grid md:grid-cols-3 gap-8">
|
|
<div className="md:col-span-2 space-y-4">
|
|
{items.map(item => (
|
|
<div key={item.variantId} className="flex gap-4 p-4 bg-card rounded-xl border border-border">
|
|
{item.thumbnail && (
|
|
<div className="relative w-20 h-20 rounded-lg overflow-hidden shrink-0 bg-muted">
|
|
<Image src={item.thumbnail} alt={item.title} fill className="object-cover" />
|
|
</div>
|
|
)}
|
|
<div className="flex-1 min-w-0">
|
|
<p className="font-semibold truncate">{item.title}</p>
|
|
{item.variant_title !== 'Default' && <p className="text-sm text-muted-foreground">{item.variant_title}</p>}
|
|
<p className="text-sm font-medium mt-1">{fmt(item.unit_price)}</p>
|
|
</div>
|
|
<div className="flex flex-col items-end gap-2">
|
|
<button onClick={() => removeFromCart(item.variantId)} className="text-muted-foreground hover:text-destructive transition-colors">
|
|
<Trash2 className="w-4 h-4" />
|
|
</button>
|
|
<div className="flex items-center gap-2 border border-border rounded-lg">
|
|
<button onClick={() => updateQty(item.variantId, item.quantity - 1)} className="p-1.5 hover:bg-muted transition-colors"><Minus className="w-3 h-3" /></button>
|
|
<span className="w-6 text-center text-sm font-medium">{item.quantity}</span>
|
|
<button onClick={() => updateQty(item.variantId, item.quantity + 1)} className="p-1.5 hover:bg-muted transition-colors"><Plus className="w-3 h-3" /></button>
|
|
</div>
|
|
<p className="text-sm font-semibold">{fmt(item.unit_price * item.quantity)}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="bg-card rounded-xl border border-border p-6 h-fit space-y-4">
|
|
<h3 className="font-semibold text-lg">Order Summary</h3>
|
|
<div className="flex justify-between text-sm"><span className="text-muted-foreground">Subtotal</span><span>{fmt(subtotal)}</span></div>
|
|
<div className="flex justify-between text-sm"><span className="text-muted-foreground">Delivery</span><span className="text-muted-foreground">Calculated at checkout</span></div>
|
|
<div className="border-t border-border pt-4 flex justify-between font-semibold"><span>Total</span><span>{fmt(subtotal)}</span></div>
|
|
<button onClick={() => router.push('/checkout')} className="w-full bg-primary text-primary-foreground py-3 rounded-lg font-medium hover:opacity-90 transition-opacity flex items-center justify-center gap-2">
|
|
Proceed to Checkout <ArrowRight className="w-4 h-4" />
|
|
</button>
|
|
<Link href="/products" className="block text-center text-sm text-muted-foreground hover:text-foreground transition-colors">Continue Shopping</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
)
|
|
}
|