Express + SQLite (node:sqlite, no native build step) family calendar: parent accounts with household invites, per-child calendars with save/duplicate/print, a token-gated read-only kiosk view for tablets, and polling to keep parent and kiosk views in sync. Defaults to port 3007.
77 lines
3.4 KiB
SQL
77 lines
3.4 KiB
SQL
CREATE TABLE IF NOT EXISTS households (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
name TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS parents (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
household_id INTEGER NOT NULL REFERENCES households(id) ON DELETE CASCADE,
|
|
email TEXT NOT NULL UNIQUE COLLATE NOCASE,
|
|
password_hash TEXT NOT NULL,
|
|
name TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_parents_household ON parents(household_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS household_invites (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
household_id INTEGER NOT NULL REFERENCES households(id) ON DELETE CASCADE,
|
|
token TEXT NOT NULL UNIQUE,
|
|
created_by_parent_id INTEGER NOT NULL REFERENCES parents(id) ON DELETE CASCADE,
|
|
expires_at TEXT NOT NULL,
|
|
used_at TEXT,
|
|
used_by_parent_id INTEGER REFERENCES parents(id),
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_invites_household ON household_invites(household_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS children (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
household_id INTEGER NOT NULL REFERENCES households(id) ON DELETE CASCADE,
|
|
name TEXT NOT NULL,
|
|
kiosk_token TEXT NOT NULL UNIQUE,
|
|
active_calendar_id INTEGER REFERENCES calendars(id) ON DELETE SET NULL,
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_children_household ON children(household_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS calendars (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
child_id INTEGER NOT NULL REFERENCES children(id) ON DELETE CASCADE,
|
|
title TEXT NOT NULL,
|
|
week_start_date TEXT,
|
|
show_weekend INTEGER NOT NULL DEFAULT 0,
|
|
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_calendars_child ON calendars(child_id);
|
|
|
|
CREATE TABLE IF NOT EXISTS calendar_blocks (
|
|
calendar_id INTEGER NOT NULL REFERENCES calendars(id) ON DELETE CASCADE,
|
|
block_key TEXT NOT NULL CHECK (block_key IN ('morning','school','after','evening')),
|
|
label TEXT NOT NULL,
|
|
PRIMARY KEY (calendar_id, block_key)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS calendar_tasks (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
calendar_id INTEGER NOT NULL REFERENCES calendars(id) ON DELETE CASCADE,
|
|
day_of_week TEXT NOT NULL CHECK (day_of_week IN
|
|
('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday')),
|
|
block_key TEXT NOT NULL CHECK (block_key IN ('morning','school','after','evening')),
|
|
text TEXT NOT NULL,
|
|
done INTEGER NOT NULL DEFAULT 0,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')),
|
|
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_tasks_calendar ON calendar_tasks(calendar_id, day_of_week, block_key);
|
|
|
|
CREATE TABLE IF NOT EXISTS sessions (
|
|
sid TEXT PRIMARY KEY,
|
|
sess TEXT NOT NULL,
|
|
expires_at INTEGER NOT NULL
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_sessions_expires ON sessions(expires_at);
|