diff --git a/src/app/admin/page.tsx b/src/app/admin/page.tsx index dc05ef4..23f5460 100644 --- a/src/app/admin/page.tsx +++ b/src/app/admin/page.tsx @@ -646,13 +646,30 @@ function MenuSection({ items, setItems, images, onToast }: any) { const [overIdx, setOverIdx] = useState(null); const save = async (item: MenuItem) => { + if (!item.category || !item.name || !item.price) { + onToast('Category, name, and price are required', 'error'); + return; + } try { - const res = await fetch(`/api/menu/${item.id}`, { + const url = item.id ? `/api/menu/${item.id}` : '/api/menu/'; + const res = await fetch(url, { method: item.id ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(item), }); - if (res.ok) { setEditing(null); setItems((i: any) => i.map((x: any) => x.id === item.id ? item : x)); onToast('Menu item saved!', 'success'); } + if (res.ok) { + const data = await res.json(); + setEditing(null); + if (item.id) { + setItems((i: any) => i.map((x: any) => x.id === item.id ? data.data : x)); + } else { + setItems((i: any) => [...i, data.data]); + } + onToast('Menu item saved!', 'success'); + } else { + const err = await res.json().catch(() => ({})); + onToast(err.error || 'Failed to save menu item', 'error'); + } } catch { onToast('Error', 'error'); } }; @@ -726,7 +743,7 @@ function MenuSection({ items, setItems, images, onToast }: any) {
handleDragStart(idx)} + onDragStart={(e: any) => { e.dataTransfer!.effectAllowed = 'move'; handleDragStart(idx); }} onDragOver={(e) => handleDragOver(e, idx)} onDragEnd={handleDragEnd} onDragEnter={() => setOverIdx(idx)} @@ -1130,7 +1147,7 @@ export default function AdminPage() { fetch('/api/rooms'), fetch('/api/calendar_events'), fetch('/api/social_events/public'), - fetch('/api/menu'), + fetch('/api/admin/menu'), fetch('/api/places'), fetch('/api/reviews'), fetch('/api/admin/images').catch(() => null), @@ -1139,7 +1156,7 @@ export default function AdminPage() { if (roomsRes.ok) { const d = await roomsRes.json(); setRooms(Array.isArray(d) ? d : []); } if (calRes.ok) { const d = await calRes.json(); setEvents(Array.isArray(d) ? d : []); } if (socialRes.ok) { const d = await socialRes.json(); setSocialEvents(Array.isArray(d) ? d : []); } - if (menuRes.ok) { const d = await menuRes.json(); setMenuItems(Array.isArray(d) ? d : []); } + if (menuRes.ok) { const d = await menuRes.json(); setMenuItems(Array.isArray(d) ? d : (d.data || [])); } if (placesRes.ok) { const d = await placesRes.json(); setPlaces(Array.isArray(d) ? d : []); } if (reviewsRes.ok) { const d = await reviewsRes.json(); setReviews(Array.isArray(d) ? d : []); } if (imagesRes?.ok) { const d = await imagesRes.json(); setImages(Array.isArray(d) ? d : []); } diff --git a/src/app/api/admin/menu/route.ts b/src/app/api/admin/menu/route.ts new file mode 100644 index 0000000..2b6802b --- /dev/null +++ b/src/app/api/admin/menu/route.ts @@ -0,0 +1,17 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { requireRole } from '@/lib/auth'; +import { db } from '@/lib/db'; + +// GET /api/admin/menu — returns ALL menu items (including inactive) +export async function GET() { + try { + await requireRole('admin'); + const { rows } = await db.query( + 'SELECT * FROM menu_items ORDER BY sort_order, id' + ); + return NextResponse.json({ data: rows }); + } catch (error: any) { + console.error('GET /api/admin/menu error:', error); + return NextResponse.json({ error: error.message || 'Failed to fetch menu' }, { status: 500 }); + } +}