Add menu enable toggle, user status, and mobile/UI polish
- Admin menu page: mobile item cards now put Actions in the top-right
corner next to Status, matching the desktop row layout instead of
stacking at the bottom; same treatment applied to announcements and
users for consistency across all three admin lists
- Center button label text everywhere via .btn { justify-content: center }
instead of one-off overrides
- Add a Disable/Enable Menu toggle to the admin menu toolbar; the public
menu page shows its existing "menu being updated" message while disabled
- Add an Enabled/Disabled status to user accounts, with its own toggle
badge, guardrails against disabling your own account or the last
enabled account, and an immediate session kick for anyone disabled
mid-session
- Fix the announcement banner / hero tagline "·" separators to hide only
when their neighboring text actually wraps onto a different line,
instead of a fixed breakpoint or always-on dot
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
eab20899de
commit
cd4c6c1969
13 files changed
+405
-50
No files matched your search
+14
-1
@@ -25,6 +25,19 @@ function require_auth(): void {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// A user disabled mid-session should lose access immediately rather
|
||||
// than keep it until their session expires — re-check against the DB
|
||||
// instead of trusting the session's now-possibly-stale copy.
|
||||
$pdo = get_db();
|
||||
$stmt = $pdo->prepare("SELECT is_enabled FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['admin_user_id']]);
|
||||
$stillEnabled = $stmt->fetchColumn();
|
||||
if ($stillEnabled === false || (int) $stillEnabled !== 1) {
|
||||
logout_user();
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function get_logged_in_user(): ?array {
|
||||
@@ -44,7 +57,7 @@ function authenticate_user(string $username, string $password): bool {
|
||||
$stmt->execute([trim($username)]);
|
||||
$user = $stmt->fetch();
|
||||
|
||||
if ($user && password_verify($password, $user['password_hash'])) {
|
||||
if ($user && (int) $user['is_enabled'] === 1 && password_verify($password, $user['password_hash'])) {
|
||||
session_regenerate_id(true);
|
||||
$_SESSION['admin_user_id'] = $user['id'];
|
||||
$_SESSION['admin_username'] = $user['username'];
|
||||
|
||||
+31
@@ -42,6 +42,7 @@ function init_db_schema(PDO $pdo): void {
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
role TEXT NOT NULL DEFAULT 'admin',
|
||||
is_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
@@ -86,8 +87,31 @@ function init_db_schema(PDO $pdo): void {
|
||||
kitchen_close_time TEXT NULL,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
-- Single-row table (id is pinned to 1) for site-wide toggles that
|
||||
-- don't belong to any one record — starting with whether the
|
||||
-- public menu page shows its items at all.
|
||||
CREATE TABLE IF NOT EXISTS site_settings (
|
||||
id INTEGER PRIMARY KEY CHECK (id = 1),
|
||||
menu_enabled INTEGER NOT NULL DEFAULT 1,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
");
|
||||
|
||||
// users.is_enabled shipped after the initial release — CREATE TABLE IF
|
||||
// NOT EXISTS above is a no-op against an existing table, so an install
|
||||
// from before this needs the column added explicitly, once.
|
||||
$hasIsEnabled = false;
|
||||
foreach ($pdo->query("PRAGMA table_info(users)") as $col) {
|
||||
if ($col['name'] === 'is_enabled') {
|
||||
$hasIsEnabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$hasIsEnabled) {
|
||||
$pdo->exec("ALTER TABLE users ADD COLUMN is_enabled INTEGER NOT NULL DEFAULT 1");
|
||||
}
|
||||
|
||||
// Seed default admin user if table is empty (username: admin / password: password)
|
||||
$stmt = $pdo->query("SELECT COUNT(*) as count FROM users");
|
||||
$userCount = $stmt->fetchColumn();
|
||||
@@ -125,4 +149,11 @@ function init_db_schema(PDO $pdo): void {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Seed the singleton settings row (menu on by default) if it doesn't exist yet.
|
||||
$stmt = $pdo->query("SELECT COUNT(*) as count FROM site_settings");
|
||||
$settingsCount = $stmt->fetchColumn();
|
||||
if ($settingsCount == 0) {
|
||||
$pdo->exec("INSERT INTO site_settings (id, menu_enabled) VALUES (1, 1)");
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,22 @@ declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/db.php';
|
||||
|
||||
// Whether the public menu page should show its items at all — separate
|
||||
// from any individual item's is_available, this is the admin-facing "take
|
||||
// the whole menu down for maintenance" switch. Defaults to enabled if the
|
||||
// singleton settings row is somehow missing.
|
||||
function is_menu_enabled(): bool {
|
||||
$pdo = get_db();
|
||||
$value = $pdo->query("SELECT menu_enabled FROM site_settings WHERE id = 1")->fetchColumn();
|
||||
return $value === false ? true : (bool) $value;
|
||||
}
|
||||
|
||||
function set_menu_enabled(bool $enabled): void {
|
||||
$pdo = get_db();
|
||||
$stmt = $pdo->prepare("UPDATE site_settings SET menu_enabled = ?, updated_at = CURRENT_TIMESTAMP WHERE id = 1");
|
||||
$stmt->execute([$enabled ? 1 : 0]);
|
||||
}
|
||||
|
||||
function get_full_menu(bool $availableOnly = false): array {
|
||||
$pdo = get_db();
|
||||
|
||||
|
||||
+13
-2
@@ -13,13 +13,13 @@ require_once __DIR__ . '/db.php';
|
||||
|
||||
function get_all_users(): array {
|
||||
$pdo = get_db();
|
||||
$stmt = $pdo->query("SELECT id, username, role, created_at FROM users ORDER BY username ASC");
|
||||
$stmt = $pdo->query("SELECT id, username, role, is_enabled, created_at FROM users ORDER BY username ASC");
|
||||
return $stmt->fetchAll() ?: [];
|
||||
}
|
||||
|
||||
function get_user_by_id(int $id): ?array {
|
||||
$pdo = get_db();
|
||||
$stmt = $pdo->prepare("SELECT id, username, role, created_at FROM users WHERE id = ?");
|
||||
$stmt = $pdo->prepare("SELECT id, username, role, is_enabled, created_at FROM users WHERE id = ?");
|
||||
$stmt->execute([$id]);
|
||||
$res = $stmt->fetch();
|
||||
return $res ?: null;
|
||||
@@ -30,6 +30,17 @@ function count_users(): int {
|
||||
return (int) $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
}
|
||||
|
||||
function count_enabled_users(): int {
|
||||
$pdo = get_db();
|
||||
return (int) $pdo->query("SELECT COUNT(*) FROM users WHERE is_enabled = 1")->fetchColumn();
|
||||
}
|
||||
|
||||
function toggle_user_enabled(int $id): bool {
|
||||
$pdo = get_db();
|
||||
$stmt = $pdo->prepare("UPDATE users SET is_enabled = CASE WHEN is_enabled = 1 THEN 0 ELSE 1 END WHERE id = ?");
|
||||
return $stmt->execute([$id]);
|
||||
}
|
||||
|
||||
function username_exists(string $username, ?int $excludeId = null): bool {
|
||||
$pdo = get_db();
|
||||
if ($excludeId !== null) {
|
||||
|
||||
Reference in new issue
Block a user