From 40cc9cf6826ee87797bd2b5a2e0c6e78148594c2 Mon Sep 17 00:00:00 2001 From: Vula Builder Date: Tue, 23 Jun 2026 08:47:47 +0000 Subject: [PATCH] Deploy --- src/app/order/page.tsx | 124 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 src/app/order/page.tsx diff --git a/src/app/order/page.tsx b/src/app/order/page.tsx new file mode 100644 index 0000000..b57ae37 --- /dev/null +++ b/src/app/order/page.tsx @@ -0,0 +1,124 @@ +'use client' +import { useState, useEffect } from 'react' +import Link from 'next/link' +import { ArrowLeft, Minus, Plus, ShoppingCart, Trash2 } from 'lucide-react' +import { broadcastCartCount } from '@/hooks/useMedusaCart' + +interface CartItem { + id: string + title: string + product_title?: string + thumbnail: string | null + quantity: number + unit_price: number +} + +const PUB_KEY = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || '' + +async function medusaFetch(path: string, options?: RequestInit) { + const res = await fetch('/api/medusa' + path, { + ...options, + headers: { + 'Content-Type': 'application/json', + 'x-publishable-api-key': PUB_KEY, + ...(options?.headers || {}), + }, + signal: AbortSignal.timeout(30000), + }) + if (!res.ok) throw new Error(await res.text()) + return res.json() +} + +export default function OrderPage() { + const [cartItems, setCartItems] = useState([]) + const [loading, setLoading] = useState(true) + + const loadCart = async () => { + const cartId = localStorage.getItem('medusa_cart_id') + if (!cartId) { setLoading(false); return } + try { + const data = await medusaFetch('/store/carts/' + cartId) + setCartItems((data.cart.items ?? []).map((i: any) => ({ + id: i.id, title: i.title, product_title: i.product_title, + thumbnail: i.thumbnail, quantity: i.quantity, unit_price: i.unit_price, + }))) + } catch { /* ignore */ } + setLoading(false) + } + + useEffect(() => { loadCart() }, []) + + const removeItem = async (lineItemId: string) => { + const cartId = localStorage.getItem('medusa_cart_id') + if (!cartId) return + try { + await medusaFetch('/store/carts/' + cartId + '/line-items/' + lineItemId, { method: 'DELETE' }) + const updated = cartItems.filter(i => i.id !== lineItemId) + setCartItems(updated) + broadcastCartCount(updated.reduce((s, i) => s + i.quantity, 0)) + } catch { /* ignore */ } + } + + const updateQuantity = async (lineItemId: string, qty: number) => { + if (qty < 1) return removeItem(lineItemId) + const cartId = localStorage.getItem('medusa_cart_id') + if (!cartId) return + try { + await medusaFetch('/store/carts/' + cartId + '/line-items/' + lineItemId, { + method: 'POST', body: JSON.stringify({ quantity: qty }), + }) + const updated = cartItems.map(i => i.id === lineItemId ? { ...i, quantity: qty } : i) + setCartItems(updated) + broadcastCartCount(updated.reduce((s, i) => s + i.quantity, 0)) + } catch { /* ignore */ } + } + + const subtotal = cartItems.reduce((s, i) => s + i.unit_price * i.quantity, 0) + + if (loading) return
+ + return ( +
+
+ + Back to Menu + +

+ Your Order +

+ {cartItems.length === 0 ? ( +
+

Your order is empty

+ Browse Menu +
+ ) : ( +
+ {cartItems.map(item => ( +
+ {item.thumbnail && {item.product_title} +
+

{item.product_title || item.title}

+

R{(item.unit_price / 100).toFixed(2)}

+
+
+ + {item.quantity} + + +
+
+ ))} +
+
+ TotalR{(subtotal / 100).toFixed(2)} +
+ + Proceed to Checkout + +
+
+ )} +
+
+ ) +}