38883-vm/frontend/src/components/CartDrawer.tsx
2026-02-28 19:37:33 +00:00

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;