113 lines
4.4 KiB
TypeScript
113 lines
4.4 KiB
TypeScript
import React from 'react';
|
|
import { mdiClose, mdiTrashCan, mdiMinus, mdiPlus } from '@mdi/js';
|
|
import { useAppDispatch, useAppSelector } from '../stores/hooks';
|
|
import { removeFromCart, updateQuantity, toggleCart } from '../stores/localCartSlice';
|
|
import BaseButton from './BaseButton';
|
|
import BaseIcon from './BaseIcon';
|
|
|
|
const CartDrawer = () => {
|
|
const dispatch = useAppDispatch();
|
|
const { items, isOpen } = useAppSelector((state) => state.localCart);
|
|
|
|
const totalPrice = items.reduce((sum, item) => sum + item.price * item.quantity, 0);
|
|
|
|
if (!isOpen) return null;
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex justify-end">
|
|
{/* Backdrop */}
|
|
<div
|
|
className="fixed inset-0 bg-black bg-opacity-50 transition-opacity"
|
|
onClick={() => dispatch(toggleCart())}
|
|
></div>
|
|
|
|
{/* Drawer */}
|
|
<div className="relative w-full max-w-md bg-white h-full shadow-xl flex flex-col animate-fade-in-right">
|
|
<div className="p-4 border-b flex items-center justify-between bg-orange-600 text-white">
|
|
<h2 className="text-xl font-bold">Tu Carrito</h2>
|
|
<button onClick={() => dispatch(toggleCart())} className="p-1 hover:bg-orange-700 rounded">
|
|
<BaseIcon path={mdiClose} size={24} />
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex-grow overflow-y-auto p-4 space-y-4">
|
|
{items.length === 0 ? (
|
|
<div className="text-center py-10">
|
|
<p className="text-gray-500 mb-4">Tu carrito está vacío</p>
|
|
<BaseButton
|
|
label="Empezar a comprar"
|
|
color="info"
|
|
onClick={() => dispatch(toggleCart())}
|
|
/>
|
|
</div>
|
|
) : (
|
|
items.map((item) => (
|
|
<div key={item.id} className="flex items-center space-x-4 border-b pb-4">
|
|
{item.image && (
|
|
<img src={item.image} alt={item.name} className="w-16 h-16 object-cover rounded" />
|
|
)}
|
|
<div className="flex-grow">
|
|
<h3 className="font-semibold text-gray-800">{item.name}</h3>
|
|
<p className="text-orange-600 font-bold">${item.price.toFixed(2)}</p>
|
|
<div className="flex items-center space-x-2 mt-2">
|
|
<button
|
|
onClick={() => dispatch(updateQuantity({ id: item.id, quantity: item.quantity - 1 }))}
|
|
className="p-1 border rounded hover:bg-gray-100"
|
|
>
|
|
<BaseIcon path={mdiMinus} size={16} />
|
|
</button>
|
|
<span className="w-8 text-center">{item.quantity}</span>
|
|
<button
|
|
onClick={() => dispatch(updateQuantity({ id: item.id, quantity: item.quantity + 1 }))}
|
|
className="p-1 border rounded hover:bg-gray-100"
|
|
>
|
|
<BaseIcon path={mdiPlus} size={16} />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<button
|
|
onClick={() => dispatch(removeFromCart(item.id))}
|
|
className="text-red-500 hover:text-red-700"
|
|
>
|
|
<BaseIcon path={mdiTrashCan} size={20} />
|
|
</button>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
|
|
{items.length > 0 && (
|
|
<div className="p-4 border-t bg-gray-50">
|
|
<div className="flex justify-between items-center mb-4">
|
|
<span className="text-lg font-semibold text-gray-600">Total:</span>
|
|
<span className="text-2xl font-bold text-orange-600">${totalPrice.toFixed(2)}</span>
|
|
</div>
|
|
<BaseButton
|
|
label="Finalizar Compra"
|
|
color="success"
|
|
className="w-full py-3 text-lg font-bold"
|
|
onClick={() => {
|
|
alert('¡Próximamente! Estamos preparando el proceso de pago.');
|
|
}}
|
|
/>
|
|
<p className="text-xs text-center text-gray-400 mt-2">
|
|
Envío gratuito en pedidos superiores a $50
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<style jsx>{`
|
|
@keyframes fade-in-right {
|
|
from { opacity: 0; transform: translateX(100%); }
|
|
to { opacity: 1; transform: translateX(0); }
|
|
}
|
|
.animate-fade-in-right {
|
|
animation: fade-in-right 0.3s ease-out forwards;
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CartDrawer;
|