Scan a QR at the table, browse a live menu with images & categories, place orders tied to that table, track status in real-time, and call a waiter when ready to pay. Admins manage items, images, and orders with bulk cleanup.
Uploads via Multer → static hosting at /uploads. Category chips for quick filtering.
Each QR embeds a token; the app resolves it to a table and scopes orders accordingly.
PATCH /api/order/:id enforces valid transitions: pending → accepted → preparing → served.
Socket.IO emits order:new and order:status span> so admins and customers see instant changes.
Bulk delete served/cancelled orders via DELETE /api/order/cleanup to keep the board tidy.
Detects available columns/tables with PRAGMA, avoiding “no such column” errors during incremental migrations.
Client (React) - Vite, Axios - Context cart - Socket.IO client - Image prefix: VITE_API_URL Server (Express) - Routers: /menu, /order, /table, /media - Multer uploads → /uploads - Socket.IO emits: order:new, order:status, table:call SQLite (file, single connection) - menu_items (image_url, category/category_id) - orders (table_id, item_id, quantity, status) - tables (id, number, token) - categories (optional)
POST /api/order
Content-Type: application/json
{
"table_id": 12,
"items": [
{ "item_id": 1, "quantity": 2 },
{ "item_id": 7, "quantity": 1 }
]
}