-- Notification system — persistent, DB-backed nudges and vaccine alerts -- Replaces the previous compute-only approach so read/unread syncs across devices. CREATE TABLE IF NOT EXISTS notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), family_id UUID NOT NULL REFERENCES families(id) ON DELETE CASCADE, child_id UUID REFERENCES children(id) ON DELETE CASCADE, -- Stable type codes: -- Vaccine alerts : "vaccine_BCG", "vaccine_OPV-0", etc. -- Daily nudges : "log_nudge", "memory_nudge" -- Weekly nudge : "garment_nudge" type VARCHAR(80) NOT NULL, title TEXT NOT NULL, message TEXT NOT NULL, action_url TEXT, is_read BOOLEAN NOT NULL DEFAULT false, -- IST date this notification belongs to. -- Nudges: today's IST date → ensures one per day per type -- Vaccines: the vaccine due date → ensures one per vaccine (due date is fixed) -- Garment: Monday of current IST week → ensures one per week scheduled_for DATE NOT NULL, -- Arbitrary extra data (e.g. { "vaccineName": "BCG" } for vaccine rows) metadata JSONB, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- One row per (family, child, type, date-slot) — prevents duplicate notifications CREATE UNIQUE INDEX IF NOT EXISTS notifications_unique_slot ON notifications(family_id, child_id, type, scheduled_for); -- Fast unread count + list query CREATE INDEX IF NOT EXISTS notifications_family_child_idx ON notifications(family_id, child_id, is_read, created_at DESC);