Files
theoldfitz/inc/db.php
T
David DyerandClaude Sonnet 5 cd4c6c1969 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>
2026-09-01 14:10:08 -04:00

160 lines
5.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
/**
* Database connection & schema management for SQLite
*/
function get_db(): PDO {
static $pdo = null;
if ($pdo !== null) {
return $pdo;
}
$dbDir = __DIR__ . '/../db';
if (!is_dir($dbDir)) {
mkdir($dbDir, 0755, true);
}
$dbPath = $dbDir . '/fitz.sqlite';
$isNew = !file_exists($dbPath);
$pdo = new PDO('sqlite:' . $dbPath, null, null, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_TIMEOUT => 5
]);
// Enable WAL mode for concurrency and performance
$pdo->exec('PRAGMA journal_mode = WAL;');
$pdo->exec('PRAGMA foreign_keys = ON;');
// Initialize tables if needed
init_db_schema($pdo);
return $pdo;
}
function init_db_schema(PDO $pdo): void {
$pdo->exec("
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
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
);
CREATE TABLE IF NOT EXISTS announcements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
is_active INTEGER NOT NULL DEFAULT 1,
type TEXT NOT NULL DEFAULT 'holiday',
headline TEXT NOT NULL,
message TEXT NOT NULL,
start_date TEXT NULL,
end_date TEXT NULL,
show_banner INTEGER NOT NULL DEFAULT 1,
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
);
CREATE TABLE IF NOT EXISTS pub_hours (
day_of_week INTEGER PRIMARY KEY,
is_open INTEGER NOT NULL DEFAULT 0,
open_time TEXT NULL,
close_time TEXT NULL,
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();
if ($userCount == 0) {
$defaultPassHash = password_hash('password', PASSWORD_DEFAULT);
$insert = $pdo->prepare("INSERT INTO users (username, password_hash, role) VALUES (?, ?, 'admin')");
$insert->execute(['admin', $defaultPassHash]);
}
// Seed default weekly hours if the table is empty: closed Sun–Wed,
// 4–10pm Thu–Sat with the kitchen closing at 9 — matches the hours the
// site originally shipped with as hardcoded copy.
$stmt = $pdo->query("SELECT COUNT(*) as count FROM pub_hours");
$hoursCount = $stmt->fetchColumn();
if ($hoursCount == 0) {
$insert = $pdo->prepare("
INSERT INTO pub_hours (day_of_week, is_open, open_time, close_time, kitchen_close_time)
VALUES (?, ?, ?, ?, ?)
");
// 0=Sunday ... 6=Saturday
$defaults = [
0 => null, // Sunday — closed
1 => null, // Monday — closed
2 => null, // Tuesday — closed
3 => null, // Wednesday — closed
4 => ['16:00', '22:00', '21:00'], // Thursday
5 => ['16:00', '22:00', '21:00'], // Friday
6 => ['16:00', '22:00', '21:00'], // Saturday
];
foreach ($defaults as $day => $times) {
if ($times === null) {
$insert->execute([$day, 0, null, null, null]);
} else {
$insert->execute([$day, 1, $times[0], $times[1], $times[2]]);
}
}
}
// 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)");
}
}