Files
vula-e994460c/src/app/cart/page.tsx
T
Vula Builder 8a0b016925 Deploy
2026-07-29 19:04:21 +00:00

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>
)
}