CartDrawer
cartdrawer-1779379671435.tsx
'use client'
import { useState } from 'react'
interface CartItem { id: number; name: string; price: number; qty: number; color: string }
const INITIAL_ITEMS: CartItem[] = [
{ id: 1, name: 'Empire UI Pro', price: 19, qty: 1, color: '#C9A84C' },
{ id: 2, name: 'Empire UI Team', price: 49, qty: 1, color: '#6366f1' },
]
export default function CartDrawer() {
const [open, setOpen] = useState(false)
const [items, setItems] = useState(INITIAL_ITEMS)
const [promo, setPromo] = useState('')
const [promoApplied, setPromoApplied] = useState(false)
function setQty(id: number, delta: number) {
setItems(its => its.map(i => i.id === id ? { ...i, qty: Math.max(0, i.qty + delta) } : i).filter(i => i.qty > 0))
}
const subtotal = items.reduce((a, i) => a + i.price * i.qty, 0)
const discount = promoApplied ? subtotal * 0.2 : 0
const total = subtotal - discount
function applyPromo() {
if (promo.toLowerCase() === 'empire20') { setPromoApplied(true) }
else { setPromoApplied(false) }
}
return (
<div style={{ background: '#0A0A0A', padding: 40, display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 300 }}>
<button onClick={() => setOpen(true)} style={{ background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 10, padding: '12px 28px', fontWeight: 700, cursor: 'pointer', fontSize: 14, position: 'relative' }}>
🛒 Open Cart
{items.length > 0 && <span style={{ position: 'absolute', top: -8, right: -8, background: '#ef4444', color: '#fff', borderRadius: '50%', width: 18, height: 18, fontSize: 10, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center', border: '2px solid #0A0A0A' }}>{items.reduce((a, i) => a + i.qty, 0)}</span>}
</button>
{open && (
<>
<div onClick={() => setOpen(false)} style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.6)', backdropFilter: 'blur(4px)', zIndex: 9998 }} />
<div style={{ position: 'fixed', top: 0, right: 0, bottom: 0, width: 380, background: '#111', borderLeft: '1px solid rgba(255,255,255,0.08)', zIndex: 9999, display: 'flex', flexDirection: 'column', animation: 'slideIn 0.25s ease' }}>
<div style={{ padding: '18px 20px', borderBottom: '1px solid rgba(255,255,255,0.06)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div style={{ color: '#F5F5F0', fontSize: 16, fontWeight: 700 }}>Your Cart</div>
<button onClick={() => setOpen(false)} style={{ background: 'rgba(255,255,255,0.06)', border: 'none', color: '#F5F5F0', borderRadius: '50%', width: 32, height: 32, cursor: 'pointer', fontSize: 16 }}>×</button>
</div>
{items.length === 0 ? (
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 12 }}>
<span style={{ fontSize: 48 }}>🛒</span>
<div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 14 }}>Your cart is empty</div>
</div>
) : (
<div style={{ flex: 1, overflowY: 'auto', padding: '16px 20px', display: 'flex', flexDirection: 'column', gap: 14 }}>
{items.map(item => (
<div key={item.id} style={{ display: 'flex', alignItems: 'center', gap: 14, background: '#1a1a1a', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 12, padding: 14 }}>
<div style={{ width: 44, height: 44, borderRadius: 10, background: item.color + '20', border: `1px solid ${item.color}30`, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
<span style={{ color: item.color, fontSize: 20 }}>⬡</span>
</div>
<div style={{ flex: 1 }}>
<div style={{ color: '#F5F5F0', fontSize: 14, fontWeight: 600 }}>{item.name}</div>
<div style={{ color: '#C9A84C', fontSize: 13, fontWeight: 700 }}>${item.price}/mo</div>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
<button onClick={() => setQty(item.id, -1)} style={{ width: 26, height: 26, borderRadius: 6, border: '1px solid rgba(255,255,255,0.1)', background: 'rgba(255,255,255,0.06)', color: '#F5F5F0', cursor: 'pointer', fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>−</button>
<span style={{ color: '#F5F5F0', fontSize: 13, minWidth: 16, textAlign: 'center' }}>{item.qty}</span>
<button onClick={() => setQty(item.id, 1)} style={{ width: 26, height: 26, borderRadius: 6, border: '1px solid rgba(255,255,255,0.1)', background: 'rgba(255,255,255,0.06)', color: '#F5F5F0', cursor: 'pointer', fontSize: 16, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>+</button>
</div>
</div>
))}
</div>
)}
{items.length > 0 && (
<div style={{ padding: 20, borderTop: '1px solid rgba(255,255,255,0.06)', display: 'flex', flexDirection: 'column', gap: 12 }}>
{/* Promo */}
<div style={{ display: 'flex', gap: 8 }}>
<input value={promo} onChange={e => setPromo(e.target.value)} placeholder="Promo code (EMPIRE20)"
style={{ flex: 1, background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 8, color: '#F5F5F0', padding: '9px 12px', fontSize: 13, outline: 'none' }} />
<button onClick={applyPromo} style={{ background: 'rgba(255,255,255,0.08)', border: '1px solid rgba(255,255,255,0.1)', color: '#F5F5F0', borderRadius: 8, padding: '9px 14px', cursor: 'pointer', fontSize: 13 }}>Apply</button>
</div>
{promoApplied && <div style={{ color: '#22c55e', fontSize: 12 }}>✓ 20% discount applied!</div>}
{/* Summary */}
<div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', color: 'rgba(255,255,255,0.5)', fontSize: 13 }}><span>Subtotal</span><span>${subtotal}</span></div>
{promoApplied && <div style={{ display: 'flex', justifyContent: 'space-between', color: '#22c55e', fontSize: 13 }}><span>Discount (20%)</span><span>−${discount.toFixed(0)}</span></div>}
<div style={{ display: 'flex', justifyContent: 'space-between', color: '#F5F5F0', fontSize: 16, fontWeight: 700, marginTop: 4 }}><span>Total</span><span>${total.toFixed(0)}/mo</span></div>
</div>
<button style={{ background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 10, padding: '14px', fontWeight: 800, cursor: 'pointer', fontSize: 15 }}>
Checkout →
</button>
</div>
)}
</div>
</>
)}
<style>{`@keyframes slideIn { from { transform:translateX(100%) } to { transform:translateX(0) } }`}</style>
</div>
)
}Component info
CategoryE-commerce
Frameworkreact
TierFREE
Views0
Copies0
About
Shopping cart slide-in drawer with item management, quantity controls, promo code, and checkout