From 8068f3724ef444d013991f36a1bae1510c351d1c Mon Sep 17 00:00:00 2001 From: Vula Builder Date: Tue, 23 Jun 2026 08:47:47 +0000 Subject: [PATCH] Deploy --- src/app/menu/page.tsx | 105 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/app/menu/page.tsx diff --git a/src/app/menu/page.tsx b/src/app/menu/page.tsx new file mode 100644 index 0000000..299b478 --- /dev/null +++ b/src/app/menu/page.tsx @@ -0,0 +1,105 @@ +'use client' +import { useState, useEffect } from 'react' +import { useMedusaProducts } from '@/hooks/useMedusaProducts' +import { useMedusaCart } from '@/hooks/useMedusaCart' +import Image from 'next/image' +import Link from 'next/link' +import { ShoppingCart, UtensilsCrossed } from 'lucide-react' + +interface Category { id: string; name: string } + +export default function MenuPage() { + const { products: menuItems, loading, error } = useMedusaProducts(100) + const { addToCart } = useMedusaCart() + const [categories, setCategories] = useState([]) + const [activeCategory, setActiveCategory] = useState(null) + const [adding, setAdding] = useState(null) + + useEffect(() => { + fetch('/api/medusa/store/product-categories?limit=20', { + headers: { 'x-publishable-api-key': process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || '' }, + }) + .then(r => r.json()) + .then(d => setCategories(d.product_categories || [])) + .catch(() => {}) + }, []) + + const filtered = activeCategory + ? menuItems.filter(p => p.categories?.some((c: any) => c.id === activeCategory)) + : menuItems + + const handleAdd = async (variantId: string, itemId: string) => { + setAdding(itemId) + await addToCart(variantId, 1) + setAdding(null) + } + + if (loading) return ( +
+
+
+

Loading menu...

+
+
+ ) + + if (error) return ( +
+

Failed to load menu. Please try again.

+
+ ) + + return ( +
+
+
+

Our Menu

+ + + View Order + +
+ {categories.length > 0 && ( +
+ + {categories.map(cat => ( + + ))} +
+ )} + {filtered.length === 0 ? ( +
+ +

{activeCategory ? 'No items in this category.' : 'Menu coming soon.'}

+
+ ) : ( +
+ {filtered.map((item) => { + const variant = item.variants?.[0] + const price = variant?.prices?.[0] + return ( +
+ {item.thumbnail && ( +
+ {item.title} +
+ )} +
+

{item.title}

+ {item.description &&

{item.description}

} + {price &&

R{(price.amount / 100).toFixed(2)}

} + +
+
+ ) + })} +
+ )} +
+
+ ) +}