This commit is contained in:
Your Name committed 2026-06-21 07:04:03 -04:00
1 parent f7ac94ca0d
commit 335f3b4f59
41 files changed
+809 -413

No files matched your search

+32 -32
View File
@@ -32,41 +32,41 @@ export default function CartDrawer() {
/>
{/* Drawer */}
<div className="relative w-full max-w-md h-full bg-spa-light shadow-2xl flex flex-col animate-slide-left">
<div className="relative w-full max-w-md h-full bg-pop-bg shadow-2xl flex flex-col animate-slide-left">
{/* Header */}
<div className="p-6 border-b border-spa-stone/10 flex items-center justify-between bg-spa-light">
<div className="p-6 border-b border-pop-black/10 flex items-center justify-between bg-pop-bg">
<h2 className="text-xl font-bold flex items-center gap-2 text-pop-black">
<ShoppingBag className="w-5 h-5 text-spa-forest" />
<ShoppingBag className="w-5 h-5 text-pop-pink" />
{t('cart.title')}
<span className="text-sm font-normal text-spa-stone bg-spa-sage px-2 py-0.5 rounded-full ml-2">
<span className="text-sm font-normal text-pop-black bg-pop-black/5 px-2 py-0.5 rounded-full ml-2">
{t('cart.items', { count: items.length })}
</span>
</h2>
<button
onClick={() => toggleCart(false)}
className="p-2 hover:bg-spa-sage rounded-full transition-colors"
className="p-2 hover:bg-pop-black/5 rounded-full transition-colors"
>
<X className="w-5 h-5 text-spa-stone hover:text-pop-black" />
<X className="w-5 h-5 text-pop-black/50 hover:text-pop-black" />
</button>
</div>
{/* Cart Items */}
<div className="flex-1 overflow-y-auto p-6 space-y-4">
{items.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-spa-stone space-y-4">
<div className="h-full flex flex-col items-center justify-center text-pop-black/50 space-y-4">
<ShoppingBag className="w-16 h-16 opacity-20" />
<p>{t('cart.empty')}</p>
<button
onClick={() => toggleCart(false)}
className="text-spa-forest hover:underline tracking-widest uppercase text-xs font-bold"
className="text-pop-pink hover:underline tracking-widest uppercase text-xs font-bold"
>
{t('cart.continueShopping')}
</button>
</div>
) : (
items.map((item) => (
<div key={item.cartItemId} className="flex gap-4 p-4 rounded-2xl bg-spa-light border border-spa-stone/10 shadow-sm group relative">
<div className="w-18 h-22 rounded-lg bg-spa-sage/30 overflow-hidden flex-shrink-0" style={{ width: '72px', height: '88px' }}>
<div key={item.cartItemId} className="flex gap-4 p-4 rounded-2xl bg-pop-bg border border-pop-black/10 shadow-sm group relative">
<div className="w-18 h-22 rounded-lg bg-pop-black/5 overflow-hidden flex-shrink-0" style={{ width: '72px', height: '88px' }}>
<img
src={item.productImage || '/images/fallback-product.svg'}
alt={item.productName}
@@ -75,33 +75,33 @@ export default function CartDrawer() {
</div>
<div className="flex-1 flex flex-col pt-1 space-y-1 relative min-w-0">
<h3 className="font-bold text-sm text-spa-forest leading-tight pr-6 truncate">{item.productName}</h3>
<h3 className="font-bold text-sm text-pop-black leading-tight pr-6 truncate">{item.productName}</h3>
{item.variantSize && (
<p className="text-xs text-spa-stone">{item.variantSize}</p>
<p className="text-xs text-pop-black/60">{item.variantSize}</p>
)}
{/* Price row */}
<div className="flex items-baseline gap-1.5 mt-0.5">
<span className="text-xs text-spa-stone/80">{formatPrice(item.price)}</span>
<span className="text-xs text-spa-stone/60">×</span>
<span className="text-xs text-spa-stone/80">{item.quantity}</span>
<span className="text-xs text-spa-stone/60">=</span>
<span className="text-xs text-pop-black/80">{formatPrice(item.price)}</span>
<span className="text-xs text-pop-black/60">×</span>
<span className="text-xs text-pop-black/80">{item.quantity}</span>
<span className="text-xs text-pop-black/60">=</span>
<span className="text-sm font-bold text-rose-500">{formatPrice(item.price * item.quantity)}</span>
</div>
{/* Quantity controls */}
<div className="flex items-center gap-2 mt-1">
<div className="flex items-center gap-2 bg-spa-sage/50 rounded-lg border border-spa-stone/5">
<div className="flex items-center gap-2 bg-pop-black/5 rounded-lg border border-pop-black/5">
<button
onClick={() => updateQuantity(item.cartItemId, item.quantity - 1)}
className="p-1.5 text-spa-stone hover:text-spa-forest transition-colors"
className="p-1.5 text-pop-black/50 hover:text-pop-black transition-colors"
>
<Minus className="w-3 h-3" />
</button>
<span className="w-5 text-center text-xs font-bold text-pop-black">{item.quantity}</span>
<button
onClick={() => updateQuantity(item.cartItemId, item.quantity + 1)}
className="p-1.5 text-spa-stone hover:text-spa-forest transition-colors"
className="p-1.5 text-pop-black/50 hover:text-pop-black transition-colors"
>
<Plus className="w-3 h-3" />
</button>
@@ -110,7 +110,7 @@ export default function CartDrawer() {
<button
onClick={() => removeFromCart(item.cartItemId)}
className="absolute top-0 right-0 p-1.5 text-spa-stone/50 hover:text-rose-500 transition-colors"
className="absolute top-0 right-0 p-1.5 text-pop-black/50 hover:text-rose-500 transition-colors"
title="Remove item"
>
<Trash2 className="w-3.5 h-3.5" />
@@ -214,7 +214,7 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
const total = Math.max(0, subtotalAfterL2 - discountAmount)
return (
<div className="p-5 border-t border-spa-stone/10 bg-spa-light space-y-4">
<div className="p-5 border-t border-pop-black/10 bg-pop-bg space-y-4">
{/* Coupon Input */}
{!savedCoupon && (
@@ -225,12 +225,12 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
value={couponInput}
onChange={e => setCouponInput(e.target.value.toUpperCase())}
placeholder={t('cart.couponPlaceholder', 'Discount Code')}
className="flex-1 bg-spa-light border border-spa-stone/20 rounded-lg px-3 py-2 text-sm text-pop-black focus:border-spa-forest outline-none uppercase tracking-widest placeholder:text-spa-stone/50"
className="flex-1 bg-pop-bg border border-pop-black/20 rounded-lg px-3 py-2 text-sm text-pop-black focus:border-pop-pink outline-none uppercase tracking-widest placeholder:text-pop-black/50"
/>
<button
onClick={handleApplyCoupon}
disabled={couponLoading || !couponInput.trim()}
className="px-4 bg-spa-stone/10 hover:bg-spa-stone/20 border border-spa-stone/10 rounded-lg text-xs font-bold uppercase tracking-widest disabled:opacity-50 transition-all text-pop-black"
className="px-4 bg-pop-black/5 hover:bg-pop-black/10 border border-pop-black/10 rounded-lg text-xs font-bold uppercase tracking-widest disabled:opacity-50 transition-all text-pop-black"
>
{couponLoading ? '...' : t('cart.applyCoupon', 'Apply')}
</button>
@@ -241,30 +241,30 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
{/* Totals */}
<div className="space-y-2 text-sm text-pop-black">
<div className="flex justify-between text-spa-stone">
<div className="flex justify-between text-pop-black/60">
<span>ราคาสินค้า</span>
<span>{formatPrice(subtotal)}</span>
</div>
{promoLevel1Disc > 0 && (
<div className="flex justify-between text-spa-forest font-medium">
<div className="flex justify-between text-pop-pink font-medium">
<span>{promoLevel1?.name}</span>
<span>- {formatPrice(promoLevel1Disc)}</span>
</div>
)}
{promoLevel2Disc > 0 && (
<div className="flex justify-between text-spa-forest font-medium">
<div className="flex justify-between text-pop-pink font-medium">
<span>{promoLevel2?.name}</span>
<span>- {formatPrice(promoLevel2Disc)}</span>
</div>
)}
{(discountAmount > 0 || isFreeShipping) && savedCoupon && (
<div className="flex justify-between text-spa-forest font-medium">
<div className="flex justify-between text-pop-pink font-medium">
<span className="flex items-center gap-1.5">
ส่วนลดคูปอง
<span className="text-[10px] font-bold bg-spa-sage px-1.5 py-0.5 rounded tracking-widest text-spa-forest">
<span className="text-[10px] font-bold bg-pop-pink/10 px-1.5 py-0.5 rounded tracking-widest text-pop-pink">
{savedCoupon}
</span>
<button onClick={removeCoupon} className="text-spa-stone/50 hover:text-rose-500 transition-colors" title="ยกเลิก">
<button onClick={removeCoupon} className="text-pop-black/50 hover:text-rose-500 transition-colors" title="ยกเลิก">
<X className="w-3 h-3" />
</button>
</span>
@@ -276,13 +276,13 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
<span className="flex items-center gap-1.5">
<Tag className="w-3 h-3" />
คูปอง <span className="font-bold tracking-widest">{savedCoupon}</span> (ยังไม่ถึงยอดขั้นต่ำ)
<button onClick={removeCoupon} className="text-spa-stone/50 hover:text-rose-500 transition-colors">
<button onClick={removeCoupon} className="text-pop-black/50 hover:text-rose-500 transition-colors">
<X className="w-3 h-3" />
</button>
</span>
</div>
)}
<div className="flex justify-between font-bold text-base pt-2 border-t border-spa-stone/10 text-pop-black">
<div className="flex justify-between font-bold text-base pt-2 border-t border-pop-black/10 text-pop-black">
<span>รวมสุทธิ</span>
<span className="text-rose-500">{formatPrice(total)}</span>
</div>
@@ -292,7 +292,7 @@ function CartDrawerFooter({ subtotal, onClose, t }: { subtotal: number; onClose:
<Link
to="/checkout"
onClick={onClose}
className="flex items-center justify-center gap-2 w-full py-4 bg-spa-forest text-spa-light font-bold rounded-xl uppercase tracking-widest text-sm hover:bg-spa-stone hover:shadow-lg transition-all duration-300 group"
className="flex items-center justify-center gap-2 w-full py-4 bg-pop-pink text-pop-bg font-bold rounded-xl uppercase tracking-widest text-sm hover:bg-pop-black hover:text-pop-bg hover:shadow-lg transition-all duration-300 group"
>
<ShoppingBag className="w-4 h-4" />
ดำเนินการชำระเงิน