diff --git a/admin/menu.js b/admin/menu.js
index 33bde7b..e48a2bc 100644
--- a/admin/menu.js
+++ b/admin/menu.js
@@ -277,10 +277,10 @@ function updateOrInsertItemRow(item, isNew) {
const badgeCell = existingRow.querySelector('.item-badge-cell');
badgeCell.innerHTML = item.badge
- ? `
';
- existingRow.querySelector('.btn-toggle-item').textContent = isAvail ? 'Sold Out' : 'Available';
+ existingRow.querySelector('.btn-toggle-item').textContent = isAvail ? 'Mark Sold Out' : 'Mark Available';
return;
}
@@ -298,13 +298,13 @@ function updateOrInsertItemRow(item, isNew) {
tr.innerHTML = `
`;
@@ -320,10 +320,10 @@ function categoryPanelHtml(category) {
return `
-
+
${escapeHtml(category.name)}
-
${escapeHtml(category.description || '')}
+
${escapeHtml(category.description || '')}
@@ -345,7 +345,7 @@ function categoryPanelHtml(category) {
- | No items in this category yet. |
+ No items in this category yet. |
diff --git a/admin/menu.php b/admin/menu.php
index 0530b0a..2893cb7 100644
--- a/admin/menu.php
+++ b/admin/menu.php
@@ -11,124 +11,131 @@ $user = get_logged_in_user();
* Safely read a trimmed string from a POST payload, guarding against
* unexpected non-string input (e.g. a spoofed `name[]=` array field).
*/
-function post_str(array $data, string $key, string $default = ''): string {
- $value = $data[$key] ?? $default;
- return is_string($value) ? trim($value) : $default;
+function post_str(array $data, string $key, string $default = ''): string
+{
+ $value = $data[$key] ?? $default;
+ return is_string($value) ? trim($value) : $default;
}
-function handle_save_item(array $post): array {
- $categoryId = (int)($post['category_id'] ?? 0);
- if (!category_exists($categoryId)) {
- return ['success' => false, 'error' => 'Please choose a valid menu category.'];
- }
+function handle_save_item(array $post): array
+{
+ $categoryId = (int) ($post['category_id'] ?? 0);
+ if (!category_exists($categoryId)) {
+ return ['success' => false, 'error' => 'Please choose a valid menu category.'];
+ }
- $name = post_str($post, 'name');
- $price = post_str($post, 'price');
- if ($name === '' || $price === '') {
- return ['success' => false, 'error' => 'Item name and price are required.'];
- }
+ $name = post_str($post, 'name');
+ $price = post_str($post, 'price');
+ if ($name === '' || $price === '') {
+ return ['success' => false, 'error' => 'Item name and price are required.'];
+ }
- $itemId = !empty($post['item_id']) ? (int)$post['item_id'] : null;
- if ($itemId !== null && ($itemId <= 0 || !get_menu_item_by_id($itemId))) {
- return ['success' => false, 'error' => 'Menu item not found.'];
- }
+ $itemId = !empty($post['item_id']) ? (int) $post['item_id'] : null;
+ if ($itemId !== null && ($itemId <= 0 || !get_menu_item_by_id($itemId))) {
+ return ['success' => false, 'error' => 'Menu item not found.'];
+ }
- $savedId = save_menu_item([
- 'category_id' => $categoryId,
- 'name' => $name,
- 'description' => post_str($post, 'description'),
- 'price' => $price,
- 'badge' => post_str($post, 'badge'),
- 'is_available' => isset($post['is_available']) ? 1 : 0,
- 'sort_order' => (int)($post['sort_order'] ?? 0),
- ], $itemId);
+ $savedId = save_menu_item([
+ 'category_id' => $categoryId,
+ 'name' => $name,
+ 'description' => post_str($post, 'description'),
+ 'price' => $price,
+ 'badge' => post_str($post, 'badge'),
+ 'is_available' => isset($post['is_available']) ? 1 : 0,
+ 'sort_order' => (int) ($post['sort_order'] ?? 0),
+ ], $itemId);
- return ['success' => true, 'item' => get_menu_item_by_id($savedId), 'is_new' => $itemId === null];
+ return ['success' => true, 'item' => get_menu_item_by_id($savedId), 'is_new' => $itemId === null];
}
-function handle_toggle_item(array $post): array {
- $itemId = (int)($post['item_id'] ?? 0);
- if ($itemId <= 0 || !get_menu_item_by_id($itemId)) {
- return ['success' => false, 'error' => 'Menu item not found.'];
- }
+function handle_toggle_item(array $post): array
+{
+ $itemId = (int) ($post['item_id'] ?? 0);
+ if ($itemId <= 0 || !get_menu_item_by_id($itemId)) {
+ return ['success' => false, 'error' => 'Menu item not found.'];
+ }
- toggle_menu_item_availability($itemId);
- $item = get_menu_item_by_id($itemId);
+ toggle_menu_item_availability($itemId);
+ $item = get_menu_item_by_id($itemId);
- return [
- 'success' => true,
- 'is_available' => (bool)$item['is_available'],
- 'status_badge' => $item['is_available'] ? '● Available' : '○ Sold Out / Hidden',
- 'status_class' => $item['is_available'] ? 'active' : 'inactive',
- 'btn_text' => $item['is_available'] ? 'Sold Out' : 'Available',
- ];
+ return [
+ 'success' => true,
+ 'is_available' => (bool) $item['is_available'],
+ 'status_badge' => $item['is_available'] ? '● Available' : '○ Sold Out / Hidden',
+ 'status_class' => $item['is_available'] ? 'active' : 'inactive',
+ 'btn_text' => $item['is_available'] ? 'Mark Sold Out' : 'Mark Available',
+ ];
}
-function handle_delete_item(array $post): array {
- $itemId = (int)($post['item_id'] ?? 0);
- if ($itemId <= 0) {
- return ['success' => false, 'error' => 'Menu item not found.'];
- }
+function handle_delete_item(array $post): array
+{
+ $itemId = (int) ($post['item_id'] ?? 0);
+ if ($itemId <= 0) {
+ return ['success' => false, 'error' => 'Menu item not found.'];
+ }
- delete_menu_item($itemId);
- return ['success' => true];
+ delete_menu_item($itemId);
+ return ['success' => true];
}
-function handle_save_category(array $post): array {
- $name = post_str($post, 'name');
- if ($name === '') {
- return ['success' => false, 'error' => 'Category name is required.'];
- }
+function handle_save_category(array $post): array
+{
+ $name = post_str($post, 'name');
+ if ($name === '') {
+ return ['success' => false, 'error' => 'Category name is required.'];
+ }
- $catId = !empty($post['category_id']) ? (int)$post['category_id'] : null;
- if ($catId !== null && ($catId <= 0 || !get_category_by_id($catId))) {
- return ['success' => false, 'error' => 'Category not found.'];
- }
+ $catId = !empty($post['category_id']) ? (int) $post['category_id'] : null;
+ if ($catId !== null && ($catId <= 0 || !get_category_by_id($catId))) {
+ return ['success' => false, 'error' => 'Category not found.'];
+ }
- $savedId = save_category([
- 'name' => $name,
- 'description' => post_str($post, 'description'),
- 'sort_order' => (int)($post['sort_order'] ?? 0),
- ], $catId);
+ $savedId = save_category([
+ 'name' => $name,
+ 'description' => post_str($post, 'description'),
+ 'sort_order' => (int) ($post['sort_order'] ?? 0),
+ ], $catId);
- return ['success' => true, 'category' => get_category_by_id($savedId), 'is_new' => $catId === null];
+ return ['success' => true, 'category' => get_category_by_id($savedId), 'is_new' => $catId === null];
}
-function handle_delete_category(array $post): array {
- $catId = (int)($post['category_id'] ?? 0);
- if ($catId <= 0) {
- return ['success' => false, 'error' => 'Category not found.'];
- }
+function handle_delete_category(array $post): array
+{
+ $catId = (int) ($post['category_id'] ?? 0);
+ if ($catId <= 0) {
+ return ['success' => false, 'error' => 'Category not found.'];
+ }
- delete_category($catId);
- return ['success' => true];
+ delete_category($catId);
+ return ['success' => true];
}
-function handle_menu_action(string $action, array $post): array {
- return match ($action) {
- 'save_item' => handle_save_item($post),
- 'toggle_item' => handle_toggle_item($post),
- 'delete_item' => handle_delete_item($post),
- 'save_category' => handle_save_category($post),
- 'delete_category' => handle_delete_category($post),
- default => ['success' => false, 'error' => 'Unknown action'],
- };
+function handle_menu_action(string $action, array $post): array
+{
+ return match ($action) {
+ 'save_item' => handle_save_item($post),
+ 'toggle_item' => handle_toggle_item($post),
+ 'delete_item' => handle_delete_item($post),
+ 'save_category' => handle_save_category($post),
+ 'delete_category' => handle_delete_category($post),
+ default => ['success' => false, 'error' => 'Unknown action'],
+ };
}
// Handle AJAX actions (JSON response)
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
- header('Content-Type: application/json; charset=utf-8');
+ header('Content-Type: application/json; charset=utf-8');
- $csrfToken = $_POST['csrf_token'] ?? null;
- if (!verify_csrf_token(is_string($csrfToken) ? $csrfToken : null)) {
- http_response_code(403);
- echo json_encode(['success' => false, 'error' => 'Session expired or invalid security token. Please refresh.']);
- exit;
- }
-
- $action = is_string($_POST['action'] ?? null) ? $_POST['action'] : '';
- echo json_encode(handle_menu_action($action, $_POST));
+ $csrfToken = $_POST['csrf_token'] ?? null;
+ if (!verify_csrf_token(is_string($csrfToken) ? $csrfToken : null)) {
+ http_response_code(403);
+ echo json_encode(['success' => false, 'error' => 'Session expired or invalid security token. Please refresh.']);
exit;
+ }
+
+ $action = is_string($_POST['action'] ?? null) ? $_POST['action'] : '';
+ echo json_encode(handle_menu_action($action, $_POST));
+ exit;
}
$categories = get_all_categories();
@@ -136,6 +143,7 @@ $menuGrouped = get_full_menu(false);
?>
+
@@ -145,6 +153,7 @@ $menuGrouped = get_full_menu(false);
+
-
+
-
+
= htmlspecialchars($category['name']) ?>
-
= htmlspecialchars($category['description'] ?? '') ?>
+
= htmlspecialchars($category['description'] ?? '') ?>
-
-
+
| Status |
@@ -224,11 +233,11 @@ $menuGrouped = get_full_menu(false);
- | No items in this category yet. |
+ No items in this category yet. |
- '>
+
'>
|
● Available
@@ -238,30 +247,30 @@ $menuGrouped = get_full_menu(false);
|
= htmlspecialchars($item['name']) ?>
-
+
= htmlspecialchars($item['description'] ?? '') ?>
|
-
+ |
= htmlspecialchars($item['price']) ?>
|
- = htmlspecialchars($item['badge']) ?>
+ = htmlspecialchars($item['badge']) ?>
—
|
-
- = (int)$item['sort_order'] ?>
+ |
+ = (int) $item['sort_order'] ?>
|
Edit
-
- = $item['is_available'] ? 'Sold Out' : 'Available' ?>
+
+ = $item['is_available'] ? 'Mark Sold Out' : 'Mark Available' ?>
-
+
Delete
@@ -303,7 +312,7 @@ $menuGrouped = get_full_menu(false);
@@ -334,7 +343,7 @@ $menuGrouped = get_full_menu(false);
-
- |