'use client' import { useState, useEffect } from 'react' import { useRouter } from 'next/navigation' import usePlacesAutocomplete, { getGeocode, getLatLng } from 'use-places-autocomplete' import { api } from '@/lib/api' import { useCart } from '@/lib/cart' // ============================================================ // CHECKOUT PAGE // 1. Address input + zone check // 2. Tip selection // 3. Transparent pricing breakdown // 4. Virtual payment (mock — no Stripe required) // ============================================================ export default function CheckoutPage() { const { items, subtotal, restaurantId, restaurantName, clearCart, deliveryFee } = useCart() const router = useRouter() const [streetAddress, setStreetAddress] = useState('') const [city, setCity] = useState('') const [postalCode, setPostalCode] = useState('') const [coords, setCoords] = useState<{ lng: number; lat: number } | null>(null) const [tip, setTip] = useState(0) const [instructions, setInstructions] = useState('') const [orderId, setOrderId] = useState('') const [step, setStep] = useState<'address' | 'payment'>('address') const [zoneError, setZoneError] = useState('') const [loading, setLoading] = useState(false) const [mapsReady, setMapsReady] = useState(false) const [paymentBreakdown, setPaymentBreakdown] = useState(null) const cartSubtotal = subtotal() const total = cartSubtotal + deliveryFee + tip // Auth guard — redirect unauthenticated users to login useEffect(() => { const token = localStorage.getItem('vibe_token') || localStorage.getItem('token') if (!token) router.replace('/login?redirect=/checkout') }, []) // Redirect if cart is empty (but not after payment when cart is intentionally cleared) useEffect(() => { if (items.length === 0 && step === 'address') router.replace('/restaurants') }, [items.length, step]) // Load Google Maps Places API useEffect(() => { const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY if (!apiKey) return // No key → fall back to plain inputs if (typeof window !== 'undefined' && (window as any).google?.maps?.places) { setMapsReady(true) return } const existing = document.querySelector('script[data-gmaps]') if (existing) { existing.addEventListener('load', () => setMapsReady(true)); return } const script = document.createElement('script') script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places` script.async = true script.setAttribute('data-gmaps', '1') script.onload = () => setMapsReady(true) document.head.appendChild(script) }, []) const handleProceedToPayment = async () => { if (!streetAddress.trim()) return // Fall back to Liberty Village centre if no geocode available const deliveryCoords = coords ?? { lng: -79.4196, lat: 43.6389 } const fullAddress = [streetAddress, city, postalCode].filter(Boolean).join(', ') setLoading(true) setZoneError('') try { // 1. Verify delivery address is in service area const zoneCheck = await api.get('/zones/check', { params: { lng: deliveryCoords.lng, lat: deliveryCoords.lat }, }) if (!zoneCheck.data.inServiceArea) { setZoneError("Sorry, your address is outside our current service area. We're expanding soon!") setLoading(false) return } // 2. Place order const orderData = await api.post('/orders', { restaurantId, items: items.map((i) => ({ menuItemId: i.menuItemId, quantity: i.quantity })), deliveryAddress: fullAddress, deliveryLng: deliveryCoords.lng, deliveryLat: deliveryCoords.lat, tipAmount: tip, specialInstructions: instructions, }) const order = orderData.data.order setOrderId(order.id) // 3. Process virtual payment immediately const payData = await api.post(`/payments/orders/${order.id}/pay-virtual`) setPaymentBreakdown(payData.data.breakdown) setStep('payment') } catch (err: any) { setZoneError(err.response?.data?.message || 'Failed to place order. Please try again.') } finally { setLoading(false) } } const TIP_OPTIONS = [0, 2, 3, 5, 8] const canProceed = streetAddress.trim().length > 0 if (step === 'payment') { return ( { const id = orderId clearCart() router.push(`/orders/${id}/track`) }} /> ) } return (

Checkout

{/* Restaurant */}

Ordering from

{restaurantName}

{/* Delivery address */}

Delivery Address

{mapsReady ? ( { setStreetAddress(street) setCity(resolvedCity) setPostalCode(resolvedPostal) setCoords(resolvedCoords) }} /> ) : ( setStreetAddress(e.target.value)} placeholder="Street address" className="w-full border border-slate-200 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-vibe-teal" /> )}
setCity(e.target.value)} placeholder="Toronto" className="w-full border border-slate-200 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-vibe-teal" />
setPostalCode(e.target.value)} placeholder="M6J 1E6" className="w-full border border-slate-200 rounded-xl px-4 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-vibe-teal" />
{zoneError && (

{zoneError}

)}