← Components/E-commerce

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

More from E-commerce

'use client'
import { useState } from 'react'

const images = ['🖥️', '💻', '⌨️', '🖱️']
const colors = [{ name: 'Space Gray', hex: '#4a4a4a' }, { name: 'Silver', hex: '#c0c0c0' }, { name: 'Gold', hex: '#C9A84C' }]
const sizes = ['8GB / 256GB', '16GB
ProductQuickView
E-commerce