anycoder-adadf141 / components /CartSidebar.jsx
puwanath's picture
Upload components/CartSidebar.jsx with huggingface_hub
5f6c3de verified
import React, { useState, useEffect } from 'react';
import {
ShoppingBag,
Plus,
Minus,
Trash2,
CreditCard,
Receipt,
CheckCircle,
X,
ArrowLeft,
User
} from 'lucide-react';
const CartSidebar = ({
cart,
isOpen,
onClose,
onRemoveItem,
onUpdateQuantity,
onCheckout
}) => {
const [discount, setDiscount] = useState(0);
const [taxRate, setTaxRate] = useState(7);
const [paymentMethod, setPaymentMethod] = useState('cash');
const [showSuccess, setShowSuccess] = useState(false);
useEffect(() => {
// Reset form when cart is empty
if (cart.length === 0) {
setShowSuccess(false);
}
}, [cart]);
const subtotal = cart.reduce((sum, item) => {
const price = item.discount > 0
? item.price * (1 - item.discount/100)
: item.price;
return sum + (price * item.quantity);
}, 0);
const tax = subtotal * (taxRate / 100);
const total = subtotal + tax - discount;
const formatPrice = (price) => {
return new Intl.NumberFormat('th-TH', {
style: 'currency',
currency: 'THB'
}).format(price);
};
const handleCheckout = () => {
if (cart.length === 0) return;
setShowSuccess(true);
setTimeout(() => {
setShowSuccess(false);
onCheckout();
}, 3000);
};
if (isOpen && cart.length === 0 && !showSuccess) {
return (
<div className="fixed inset-0 bg-black/50 z-40 flex items-center justify-center">
<div className="bg-white rounded-2xl p-8 max-w-md w-full mx-4 text-center">
<div className="w-20 h-20 bg-pos-bg rounded-full flex items-center justify-center mx-auto mb-6">
<ShoppingBag className="w-10 h-10 text-pos-text-secondary" />
</div>
<h3 className="text-xl font-bold text-pos-text mb-2">ตะกร้าสินค้าว่างเปล่า</h3>
<p className="text-pos-text-secondary mb-6">เริ่มเลือกสินค้าเพื่อเริ่มต้นขาย</p>
<button
onClick={onClose}
className="px-6 py-3 bg-primary-600 text-white rounded-xl font-medium hover:bg-primary-700 transition-colors"
>
กลับไปเลือกสินค้า
</button>
</div>
</div>
);
}
return (
<>
{/* Overlay */}
<div
className={`fixed inset-0 bg-black/50 z-40 transition-opacity duration-300 ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
onClick={onClose}
/>
{/* Sidebar */}
<div
className={`
fixed right-0 top-0 h-full w-full md:w-96 bg-white shadow-2xl z-50 transform transition-transform duration-300
${isOpen ? 'translate-x-0' : 'translate-x-full'}
`}
>
{showSuccess ? (
<div className="h-full flex flex-col items-center justify-center p-8 text-center">
<div className="w-24 h-24 bg-success/10 rounded-full flex items-center justify-center mb-6">
<CheckCircle className="w-12 h-12 text-success" />
</div>
<h3 className="text-2xl font-bold text-pos-text mb-2">ขายสำเร็จ!</h3>
<p className="text-pos-text-secondary mb-6">คำสั่งซื้อ #{Math.floor(Math.random() * 10000)} เสร็จสมบูรณ์</p>
<div className="w-full bg-pos-bg p-4 rounded-xl mb-8">
<div className="flex justify-between mb-2">
<span className="text-pos-text-secondary">ยอดรวม</span>
<span className="font-medium">{formatPrice(subtotal)}</span>
</div>
<div className="flex justify-between mb-2">
<span className="text-pos-text-secondary">ภาษี (7%)</span>
<span className="font-medium">{formatPrice(tax)}</span>
</div>
<div className="flex justify-between mb-2">
<span className="text-pos-text-secondary">ส่วนลด</span>
<span className="font-medium text-danger">-{formatPrice(discount)}</span>
</div>
<div className="border-t border-pos-border pt-2 mt-2 flex justify-between font-bold text-lg">
<span>ยอดรวมทั้งสิ้น</span>
<span className="text-primary-600">{formatPrice(total)}</span>
</div>
</div>
<p className="text-sm text-pos-text-secondary">กำลังสร้างใบเสร็จ...</p>
</div>
) : (
<div className="h-full flex flex-col">
{/* Header */}
<div className="p-4 border-b border-pos-border flex items-center justify-between">
<div className="flex items-center gap-2">
<button
onClick={onClose}
className="p-2 rounded-lg hover:bg-pos-bg transition-colors md:hidden"
>
<ArrowLeft className="w-5 h-5 text-pos-text" />
</button>
<div>
<h2 className="text-lg font-bold text-pos-text">ตะกร้าสินค้า</h2>
<p className="text-sm text-pos-text-secondary">{cart.length} รายการ</p>
</div>
</div>
<button
onClick={() => {
if (window.confirm('ต้องการลบสินค้าทั้งหมดในตะกร้าหรือไม่?')) {
onCheckout(true);
}
className="p-2 text-danger hover:bg-danger/10 rounded-lg transition-colors"
>
<Trash2 className="w-5 h-5" />
</button>
</div>
{/* Cart Items */}
<div className="flex-1 overflow-y-auto p-4">
{cart.length === 0 ? (
<div className="h-full flex flex-col items-center justify-center text-center opacity-50">
<ShoppingBag className="w-16 h-16 mb-4 text-pos-text-secondary" />
<p className="text-pos-text-secondary">ไม่มีสินค้าในตะกร้า</p>
</div>
) : (
<div className="space-y-4">
{cart.map((item) => {
const price = item.discount > 0
? item.price * (1 - item.discount/100)
: item.price;
const itemTotal = price * item.quantity;
return (
<div key={item.id} className="flex gap-4 bg-pos-bg p-3 rounded-xl">
<div className="w-20 h-20 flex-shrink-0 rounded-lg overflow-hidden">
<img
src={item.image}
alt={item.name}
className="w-full h-full object-cover"
/>
</div>
<div className="flex-1 flex flex-col justify-between">
<div>
<h3 className="font-medium text-pos-text line-clamp-1">{item.name}</h3>
<p className="text-sm text-pos-text-secondary">
{formatPrice(price)} x {item.quantity}
</p>
</div>
<div className="flex items-center justify-between mt-2">
<div className="flex items-center gap-2 bg-white rounded-lg p-1">
<button
onClick={() => onUpdateQuantity(item.id, Math.max(1, item.quantity - 1))}
className="w-6 h-6 flex items-center justify-center rounded-md bg-pos-bg hover:bg-primary-100 text-primary-600 transition-colors"
>
<Minus className="w-3 h-3" />
</button>
<span className="text-sm font-medium w-6 text-center">{item.quantity}</span>
<button
onClick={() => onUpdateQuantity(item.id, item.quantity + 1)}
className="w-6 h-6 flex items-center justify-center rounded-md bg-pos-bg hover:bg-primary-100 text-primary-600 transition-colors"
>
<Plus className="w-3 h-3" />
</button>
</div>
<div className="flex flex-col items-end">
<span className="font-bold text-primary-600">{formatPrice(itemTotal)}</span>
{item.discount > 0 && (
<span className="text-xs text-danger">
-{item.discount}% ลดให้
</span>
)}
</div>
</div>
</div>
</div>
);
})}
</div>
)}
</div>
{/* Cart Summary */}
<div className="border-t border-pos-border p-4 bg-white">
<div className="space-y-3 mb-4">
<div className="flex justify-between items-center">
<span className="text-pos-text-secondary">ยอดรวมสินค้า</span>
<span className="font-medium">{formatPrice(subtotal)}</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<span className="text-pos-text-secondary">ส่วนลด</span>
<div className="relative">
<input
type="number"
value={discount}
onChange={(e) => setDiscount(Math.max(0, Math.min(subtotal, parseFloat(e.target.value) || 0)))}
className="w-20 p-2 rounded-lg border border-pos-border focus:ring-2 focus:ring-primary-500 focus:border-transparent outline-none text-right"
placeholder="0.00"
/>
<span className="absolute right-3 top-1/2 transform -translate-y-1/2 text-pos-text-secondary">฿</span>
</div>
</div>
<span className="text-danger font-medium">-{formatPrice(discount)}</span>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-2">
<span className="text-pos-text-secondary">ภาษี ({taxRate}%)</span>
<span className="font-medium">{formatPrice(tax)}</span>
</div>
</div>
<div className="border-t border-pos-border pt-3 flex justify-between items-center">
<span className="text-lg font-bold text-pos-text">ยอดรวมทั้งสิ้น</span>
<span className="text-2xl font-bold text-primary-600">{formatPrice(total)}</span>
</div>
</div>
{/* Payment Options */}
<div className="mb-4">
<h3 className="text-sm font-medium text-pos-text mb-2">วิธีการชำระเงิน</h3>
<div className="grid grid-cols-3 gap-2">
{[
{ id: 'cash', icon: 'Cash', label: 'เงินสด' },
{ id: 'card', icon: 'CreditCard', label: 'บัตรเครดิต' },
{ id: 'qr', icon: 'Smartphone', label: 'QR Code' },
].map((method) => (
<button
key={method.id}
onClick={() => setPaymentMethod(method.id)}
className={`flex flex-col items-center p-3 rounded-xl border transition-all ${
paymentMethod === method.id
? 'border-primary-600 bg-primary-50 text-primary-600'
: 'border-pos-border hover:bg-pos-bg'
}`}
>
{method.id === 'cash' && <span className="text-lg font-bold mb-1">Cash</span>}
{method.id === 'card' && <CreditCard className="w-5 h-5 mb-1" />}
{method.id === 'qr' && <span className="text-lg font-bold mb-1">QR</span>}
<span className="text-xs font-medium">{method.label}</span>
</button>
))}
</div>
</div>
{/* Checkout Button */}
<button
onClick={handleCheckout}
disabled={cart.length === 0}
className="w-full py-4 bg-primary-600 text-white rounded-xl font-bold text-lg hover:bg-primary-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
>
<ShoppingBag className="w-5 h-5" />
{cart.length === 0 ? 'ตะกร้าว่างเปล่า' : `ชำระเงิน (${formatPrice(total)})`}
</button>
</div>
</div>
)}
</div>
</>
);
};
export default CartSidebar;