'use client';
import { FC, useState, useEffect, useMemo } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import Confetti from 'react-confetti';
interface Article {
article_id: number;
article_name: string;
actual_price?: number | null;
}
interface CartItem extends Article {
quantity: number;
}
interface ShoppingCartProps {
onOrderSubmit?: (orderData: { cart: CartItem[], orderNote: string, totalPrice: number }) => void;
addToCart: (item: Article, event?: React.MouseEvent<HTMLButtonElement>) => void;
initialCart?: CartItem[];
}
const ShoppingCart: FC<ShoppingCartProps> = ({
onOrderSubmit,
addToCart,
initialCart = []
}) => {
const [cart, setCart] = useState<CartItem[]>(initialCart);
const [orderNote, setOrderNote] = useState('');
const [showCart, setShowCart] = useState(false);
const [showOrderConfetti, setShowOrderConfetti] = useState(false);
// Load cart from localStorage
useEffect(() => {
const storedCart = localStorage.getItem('cart');
if (storedCart) setCart(JSON.parse(storedCart));
// Listen for storage events to update cart when localStorage changes (from other windows)
const handleStorageChange = (event: StorageEvent) => {
if (event.key === 'cart' && event.newValue) {
setCart(JSON.parse(event.newValue));
}
};
// Listen for custom cart updated events (from the same window)
const handleCartUpdate = (event: CustomEvent) => {
setCart(event.detail.cart);
};
window.addEventListener('storage', handleStorageChange);
window.addEventListener('cartUpdated', handleCartUpdate as EventListener);
return () => {
window.removeEventListener('storage', handleStorageChange);
window.removeEventListener('cartUpdated', handleCartUpdate as EventListener);
};
}, []);
// Save cart to localStorage
useEffect(() => {
localStorage.setItem('cart', JSON.stringify(cart));
}, [cart]);
// Remove an item from the cart
const removeFromCart = (itemId: number) => {
setCart((prevCart) =>
prevCart.filter((item) => item.article_id !== itemId)
);
};
// Update the quantity of an item
const updateCartQuantity = (itemId: number, quantity: number) => {
setCart((prevCart) =>
prevCart.map((item) =>
item.article_id === itemId
? { ...item, quantity: Math.max(1, quantity) }
: item
)
);
};
// Clear the cart
const clearCart = () => setCart([]);
// Calculate total cart price
const totalCartPrice = useMemo(() => {
return cart.reduce((sum, item) => {
if (item.actual_price !== null && item.actual_price !== undefined) {
return sum + (item.actual_price * item.quantity);
}
return sum;
}, 0);
}, [cart]);
// Submit the order
const submitOrder = () => {
// If a custom handler is provided, use it
if (onOrderSubmit) {
onOrderSubmit({ cart, orderNote, totalPrice: totalCartPrice });
// Show confetti for successful order
setShowOrderConfetti(true);
setTimeout(() => setShowOrderConfetti(false), 4000);
} else {
// Default implementation
console.log({ cart, orderNote, totalPrice: totalCartPrice });
alert('Вашата поръчка е изпратена!');
// Show confetti for successful order
setShowOrderConfetti(true);
setTimeout(() => setShowOrderConfetti(false), 4000);
}
clearCart();
setOrderNote('');
setShowCart(false);
};
return (
<>
<button
onClick={() => setShowCart(true)}
className="fixed bottom-4 right-4 bg-orange-500 text-white px-4 py-2 rounded-full shadow-lg flex items-center gap-2 hover:bg-orange-600 transition-colors"
>
<span>Поръчка</span>
<span className="bg-white text-orange-500 w-6 h-6 flex items-center justify-center rounded-full font-bold">
{cart.reduce((sum, item) => sum + item.quantity, 0)}
</span>
</button>
{/* Confetti Animation for order success */}
{showOrderConfetti && (
<div className="fixed inset-0 pointer-events-none">
<Confetti
width={window.innerWidth}
height={window.innerHeight}
colors={['#f59e0b', '#d97706', '#fdba74', '#fbbf24', '#f97316']}
recycle={false}
numberOfPieces={300}
gravity={0.2}
initialVelocityX={15}
initialVelocityY={20}
tweenDuration={1000}
/>
</div>
)}
{showCart && (
<div className="fixed inset-0 bg-gray-900 bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white p-6 rounded-lg shadow-lg max-w-md w-full max-h-[90vh] overflow-y-auto">
<h2 className="text-xl font-bold mb-4">Вашата поръчка</h2>
{cart.length === 0 ? (
<p className="text-gray-500 my-6 text-center">Поръчката е празна.</p>
) : (
<>
<ul className="divide-y mb-4 max-h-[40vh] overflow-y-auto">
{cart.map((item) => (
<li key={item.article_id} className="py-3 flex justify-between items-center">
<div className="flex-1">
<p className="font-medium">{item.article_name}</p>
<p className="text-sm text-gray-500">
{item.actual_price !== null && item.actual_price !== undefined
? `${item.actual_price.toFixed(2)} лв x ${item.quantity}`
: `${item.quantity} бр.`}
</p>
</div>
<div className="flex items-center gap-2">
<button
onClick={() => updateCartQuantity(item.article_id, item.quantity - 1)}
className="w-8 h-8 flex items-center justify-center bg-gray-200 rounded-full"
aria-label="Намали количеството"
>
-
</button>
<span className="w-6 text-center">{item.quantity}</span>
<button
onClick={() => updateCartQuantity(item.article_id, item.quantity + 1)}
className="w-8 h-8 flex items-center justify-center bg-gray-200 rounded-full"
aria-label="Увеличи количеството"
>
+
</button>
<button
onClick={() => removeFromCart(item.article_id)}
className="ml-2 text-red-500"
aria-label="Премахни от поръчката"
>
✕
</button>
</div>
</li>
))}
</ul>
<div className="border-t border-b py-3 mb-4">
<div className="flex justify-between font-bold">
<span>Общо:</span>
<span>{totalCartPrice.toFixed(2)} лв</span>
</div>
</div>
</>
)}
<textarea
value={orderNote}
onChange={(e) => setOrderNote(e.target.value)}
placeholder="Добавете бележки към поръчката (по желание)"
className="w-full p-3 border rounded mb-4 bg-white h-24 resize-none"
></textarea>
<div className="flex justify-between items-center gap-2">
<button
onClick={() => setShowCart(false)}
className="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300 transition-colors flex-1"
>
Затвори
</button>
<button
onClick={clearCart}
className="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300 transition-colors"
disabled={cart.length === 0}
>
Изчисти
</button>
<button
onClick={submitOrder}
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition-colors flex-1 disabled:opacity-50 disabled:cursor-not-allowed"
disabled={cart.length === 0}
>
Поръчай
</button>
</div>
</div>
</div>
)}
</>
);
};
export default ShoppingCart;