import React, { useEffect, useMemo, useState } from 'react'; import { IonButton, IonButtons, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonList, IonLoading, IonPage, IonText, IonTitle, IonToolbar, useIonViewWillEnter, } from '@ionic/react'; import { addOutline, bagHandleOutline, removeOutline, trashOutline, } from 'ionicons/icons'; import { useHistory } from 'react-router-dom'; import { supabase } from '../supabase'; import type { TablesInsert } from '../database.types'; import { CartItem, LAST_ORDER_STORAGE_KEY, readCart, writeCart } from './Home'; import { setStatusBarBackground, setStatusBarStyle, Style, } from '../utils/statusBar'; const Cart: React.FC = () => { const history = useHistory(); const [cart, setCart] = useState([]); const [isSubmitting, setIsSubmitting] = useState(false); const [errorMessage, setErrorMessage] = useState(''); useIonViewWillEnter(() => { setStatusBarStyle(Style.Dark); setStatusBarBackground('#ffffff'); }); useEffect(() => { setCart(readCart()); }, []); useEffect(() => { const syncCartFromStorage = () => setCart(readCart()); window.addEventListener('storage', syncCartFromStorage); window.addEventListener( 'cart:updated', syncCartFromStorage as EventListener ); return () => { window.removeEventListener('storage', syncCartFromStorage); window.removeEventListener( 'cart:updated', syncCartFromStorage as EventListener ); }; }, []); const syncCart = (nextCart: CartItem[]) => { setCart(nextCart); writeCart(nextCart); }; const showError = (message: string) => { setErrorMessage(message); window.setTimeout(() => setErrorMessage(''), 4000); }; const itemCount = useMemo( () => cart.reduce((sum, item) => sum + item.quantity, 0), [cart] ); const subtotal = useMemo( () => cart.reduce((sum, item) => sum + item.price * item.quantity, 0), [cart] ); const deliveryFee = cart.length > 0 ? 2.99 : 0; const total = subtotal + deliveryFee; const updateQuantity = (id: string, delta: number) => { const nextCart = cart .map((item) => item.id === id ? { ...item, quantity: item.quantity + delta } : item ) .filter((item) => item.quantity > 0); syncCart(nextCart); }; const removeItem = (id: string) => { syncCart(cart.filter((item) => item.id !== id)); }; const placeOrder = async () => { if (cart.length === 0 || isSubmitting) { return; } setIsSubmitting(true); const orderNumber = `QC-${Date.now().toString().slice(-6)}`; const orderPayload: TablesInsert<'orders'> = { order_number: orderNumber, subtotal, delivery_fee: deliveryFee, total, item_count: itemCount, status: 'confirmed', }; const { data: order, error: orderError } = await supabase .from('orders') .insert(orderPayload) .select() .single(); if (orderError || !order) { setIsSubmitting(false); showError('We could not place your order. Please try again.'); return; } const itemsPayload: TablesInsert<'order_items'>[] = cart.map((item) => ({ order_id: order.id, product_id: item.id, product_name: item.name, unit_price: item.price, quantity: item.quantity, })); const { error: itemsError } = await supabase .from('order_items') .insert(itemsPayload); if (itemsError) { await supabase.from('orders').delete().eq('id', order.id); setIsSubmitting(false); showError('We could not save your order items. Please try again.'); return; } localStorage.setItem( LAST_ORDER_STORAGE_KEY, JSON.stringify({ id: order.id, orderNumber: order.order_number, total: Number(order.total), itemCount: order.item_count, status: order.status, }) ); writeCart([]); setCart([]); setIsSubmitting(false); history.replace('/order-confirmation'); }; return ( history.replace('/home')}> Back Your Cart {errorMessage && (

{errorMessage}

)} {cart.length === 0 ? (

Your cart is empty

Add your first product to place an order.

history.push('/home')}> Browse products
) : ( <>

Items in cart

{itemCount} item{itemCount === 1 ? '' : 's'}

Review your selections before placing the order.

{cart.map((item) => (

{item.name}

${item.price.toFixed(2)} each

${(item.price * item.quantity).toFixed(2)}
updateQuantity(item.id, -1)} > {item.quantity} updateQuantity(item.id, 1)} > removeItem(item.id)} >
))}
Items {itemCount}
Subtotal ${subtotal.toFixed(2)}
Delivery ${deliveryFee.toFixed(2)}
Total ${total.toFixed(2)}
Place order
)}
); }; export default Cart;