Files
KCal/src/db/schema.sql
T
ort 66b8fc5d4d Add self-hosted kids calendar app
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.
2026-08-15 13:48:01 -04:00

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);