function CartDrawer({ items, isOpen, onClose, onRemove, onUpdateQty, onClearCart }) { const total = items.reduce((s, i) => s + i.coffee.prices[i.gram] * i.qty, 0); const count = items.reduce((s, i) => s + i.qty, 0); const [checkoutState, setCheckoutState] = React.useState(null); // null | 'form' | 'confirmed' const [coForm, setCoForm] = React.useState({ name: '', email: '' }); const [coErr, setCoErr] = React.useState({}); const [placing, setPlacing] = React.useState(false); const [confirmedOrder, setConfirmedOrder] = React.useState(null); const session = window.UmbraDB?.getSession?.() || null; // Reset checkout state when drawer closes React.useEffect(() => { if (!isOpen) { setCheckoutState(null); setCoForm({ name:'', email:'' }); setCoErr({}); } }, [isOpen]); function placeOrder() { const errs = {}; if (!session) { if (!coForm.name.trim()) errs.name = 'Required'; if (!coForm.email.includes('@')) errs.email = 'Valid email required'; } if (Object.keys(errs).length) { setCoErr(errs); return; } setPlacing(true); setTimeout(() => { const customer = session ? { name: `${session.firstName} ${session.lastName}`, email: session.email } : { name: coForm.name, email: coForm.email }; const address = session?.address || {}; const order = window.UmbraDB?.saveOrder?.(items, customer, address); setConfirmedOrder(order); setCheckoutState('confirmed'); setPlacing(false); }, 900); } return ( <> {/* Backdrop */} {isOpen && (
)} {/* Drawer */}
{/* Header */}
YOUR CART
{count} {count === 1 ? 'ITEM' : 'ITEMS'}
{/* Items */}
{items.length === 0 ? (
Empty
NO ITEMS IN CART
) : items.map((item, idx) => (
{item.coffee.name}
{item.coffee.origin}
{item.gram} · ${item.coffee.prices[item.gram]}
{/* Qty controls */}
{item.qty}
${item.coffee.prices[item.gram] * item.qty}
))}
{/* Checkout footer */} {items.length > 0 && !checkoutState && (
SUBTOTAL ${total}
Shipping calculated at checkout.
Free shipping on orders over $120.
)} {/* Checkout form */} {checkoutState === 'form' && (
Checkout
{!session && ( <> {[['Name', 'name', 'text'], ['Email', 'email', 'email']].map(([l, k, t]) => (
{l.toUpperCase()}{coErr[k] && — {coErr[k]}}
{ setCoForm(f=>({...f,[k]:e.target.value})); setCoErr(r=>({...r,[k]:''})); }} style={{ width:'100%', border:'none', borderBottom:`1px solid ${coErr[k]?'rgba(0,0,0,0.6)':'rgba(0,0,0,0.2)'}`, padding:'8px 0', fontFamily:"'Montserrat',monospace", fontSize:11, background:'none', outline:'none' }} />
))} )} {session && (
Ordering as {session.firstName} {session.lastName}
{session.email}
)}
Total: ${total}
)} {/* Order confirmation */} {checkoutState === 'confirmed' && confirmedOrder && (
Order placed.
#{confirmedOrder.id}
A confirmation will be sent to
{confirmedOrder.customer.email}.
We roast to order — expect dispatch within 48 hours.
)}
); } Object.assign(window, { CartDrawer });