Add online menu management, modernized and hardened
Adds a public menu page (menu.php) and an admin CRUD interface (admin/menu.php + admin/menu.js) backed by new menu_categories and menu_items tables, replacing the "menu lives on Facebook" placeholder on the homepage. The admin JS/PHP came out of an AI-assisted pass that used outdated JS (var, .then() chains, string-built HTML) and had some rough edges security-wise, so this also: - Rewrites the admin JS to modern ES (const/let, async/await, template literals, dataset API) and splits it out of admin/menu.php into admin/menu.js for proper separation of concerns - Adds declare(strict_types=1) and PHP 8 match-based action dispatch in place of an if-chain - Validates category_id/item_id/category_id server-side before use, so a bad ID returns a clean JSON error instead of an uncaught PDOException or a null item breaking the client - Rejects non-string POST fields instead of crashing trim() on them - Replaces the category-save handler's full-page location.reload() with in-place DOM updates (panel insert/update, resort by sort_order, keep the item modal's category dropdown in sync), so every admin action is now AJAX with no reload - Sets data-name/data-desc via dataset assignment rather than string- interpolating them into an HTML attribute, closing a stored-XSS path through the category name/description fields Removes seed-menu.php, a leftover stub with no working code left in it after the AI's one-time seeding run. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
21ad6c31cf
commit
f1bbf59548
8 files changed
+1382
-27
No files matched your search
+22
-14
@@ -1,4 +1,6 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Database connection & schema management for SQLite
|
||||
*/
|
||||
@@ -55,6 +57,26 @@ function init_db_schema(PDO $pdo): void {
|
||||
show_in_hours INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS menu_categories (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS menu_items (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
category_id INTEGER NOT NULL REFERENCES menu_categories(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NULL,
|
||||
price TEXT NOT NULL,
|
||||
badge TEXT NULL,
|
||||
is_available INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
");
|
||||
|
||||
// Seed default admin user if table is empty (username: admin / password: password)
|
||||
@@ -65,18 +87,4 @@ function init_db_schema(PDO $pdo): void {
|
||||
$insert = $pdo->prepare("INSERT INTO users (username, password_hash, role) VALUES (?, ?, 'admin')");
|
||||
$insert->execute(['admin', $defaultPassHash]);
|
||||
}
|
||||
|
||||
// Seed default Labor Day announcement row if table is empty
|
||||
$stmtAnn = $pdo->query("SELECT COUNT(*) as count FROM announcements");
|
||||
$annCount = $stmtAnn->fetchColumn();
|
||||
if ($annCount == 0) {
|
||||
$insertAnn = $pdo->prepare("
|
||||
INSERT INTO announcements (
|
||||
is_active, type, headline, message, start_date, end_date, show_banner, show_in_hours
|
||||
) VALUES (
|
||||
1, 'holiday', 'Labor Day Closure', 'The Old Fitz will be closed Thursday, Sept 3 through Saturday, Sept 5 for the holiday weekend. Doors reopen Thursday, Sept 10 at 4:00 PM!', NULL, NULL, 1, 1
|
||||
)
|
||||
");
|
||||
$insertAnn->execute();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user