From 797eedaeb3668ae7a012f159bb5b3b11f11358b8 Mon Sep 17 00:00:00 2001 From: Mannu Date: Sun, 10 May 2026 05:24:57 +0530 Subject: [PATCH] Add logging schema: feeds, diapers, sleeps, vaccinations, growth, medications --- src/app/api/setup/route.ts | 94 ++++++++++++++++++++++++++++++++++++ src/db/schema/logs.ts | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+) create mode 100644 src/db/schema/logs.ts diff --git a/src/app/api/setup/route.ts b/src/app/api/setup/route.ts index 2f1e545..77bb976 100644 --- a/src/app/api/setup/route.ts +++ b/src/app/api/setup/route.ts @@ -111,6 +111,100 @@ export async function GET() { ) `).catch(() => {}); + // === LOG TABLES === + // Feed type enum + await sql.unsafe("CREATE TYPE feed_type AS ENUM('breast_milk', 'formula', 'solid', 'water', 'other')").catch(() => {}); + await sql.unsafe("CREATE TYPE feed_method AS ENUM('bottle', 'breast_left', 'breast_right', 'breast_both', 'cup', 'spoon', 'finger', 'self')").catch(() => {}); + await sql.unsafe("CREATE TYPE diaper_type AS ENUM('wet', 'dirty', 'both', 'dry')").catch(() => {}); + await sql.unsafe("CREATE TYPE sleep_type AS ENUM('nap', 'night')").catch(() => {}); + + // Feeds table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS feeds ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + type feed_type NOT NULL, + method feed_method, + amount_ml REAL, + notes TEXT, + logged_at TIMESTAMP DEFAULT NOW() NOT NULL, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + + // Diapers table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS diapers_logs ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + type diaper_type NOT NULL, + notes TEXT, + logged_at TIMESTAMP DEFAULT NOW() NOT NULL, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + + // Sleeps table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS sleeps ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + type sleep_type NOT NULL, + started_at TIMESTAMP, + ended_at TIMESTAMP, + duration_minutes INTEGER, + notes TEXT, + logged_at TIMESTAMP DEFAULT NOW() NOT NULL, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + + // Vaccinations table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS vaccinations ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + vaccine_name TEXT NOT NULL, + scheduled_date DATE NOT NULL, + given_date DATE, + status TEXT NOT NULL DEFAULT 'pending', + provider TEXT, + lot_number TEXT, + notes TEXT, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + + // Growth table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS growth ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + measured_at TIMESTAMP NOT NULL, + weight_kg REAL, + height_cm REAL, + head_circumference_cm REAL, + notes TEXT, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + + // Medications table + await sql.unsafe(` + CREATE TABLE IF NOT EXISTS medications ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + child_id UUID NOT NULL REFERENCES children(id), + name TEXT NOT NULL, + dosage TEXT, + frequency TEXT, + start_date DATE NOT NULL, + end_date DATE, + active BOOLEAN NOT NULL DEFAULT true, + notes TEXT, + created_at TIMESTAMP DEFAULT NOW() NOT NULL + ) + `).catch(() => {}); + return NextResponse.json({ success: true, message: "All tables created" }); } catch (error) { console.error(error); diff --git a/src/db/schema/logs.ts b/src/db/schema/logs.ts new file mode 100644 index 0000000..a2905f8 --- /dev/null +++ b/src/db/schema/logs.ts @@ -0,0 +1,97 @@ +import { pgTable, pgEnum, uuid, timestamp, text, integer, boolean, date, real } from "drizzle-orm/pg-core"; +import { children as childrenTable } from "./family"; + +const children = childrenTable; + +// Feed types +export const feedType = pgEnum("feed_type", ["breast_milk", "formula", "solid", "water", "other"]); +export const feedMethod = pgEnum("feed_method", ["bottle", "breast_left", "breast_right", "breast_both", "cup", "spoon", "finger", "self"]); + +// Diaper types +export const diaperType = pgEnum("diaper_type", ["wet", "dirty", "both", "dry"]); + +// Sleep types +export const sleepType = pgEnum("sleep_type", ["nap", "night"]); + +// Logs: feeds +export const feeds = pgTable("feeds", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + type: feedType("type").notNull(), + method: feedMethod("method"), + amountMl: real("amount_ml"), + notes: text("notes"), + loggedAt: timestamp("logged_at").defaultNow().notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Logs: diapers +export const diapers = pgTable("diapers", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + type: diaperType("type").notNull(), + notes: text("notes"), + loggedAt: timestamp("logged_at").defaultNow().notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Logs: sleep +export const sleeps = pgTable("sleeps", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + type: sleepType("type").notNull(), + startedAt: timestamp("started_at").notNull(), + endedAt: timestamp("ended_at"), + durationMinutes: integer("duration_minutes"), + notes: text("notes"), + loggedAt: timestamp("logged_at").defaultNow().notNull(), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Logs: vaccinations +export const vaccinations = pgTable("vaccinations", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + vaccineName: text("vaccine_name").notNull(), + scheduledDate: date("scheduled_date").notNull(), + givenDate: date("given_date"), + status: text("status").notNull().default("pending"), // pending, given, skipped, delayed + provider: text("provider"), + lotNumber: text("lot_number"), + notes: text("notes"), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Logs: growth +export const growth = pgTable("growth", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + measuredAt: timestamp("measured_at").notNull(), + weightKg: real("weight_kg"), + heightCm: real("height_cm"), + headCircumferenceCm: real("head_circumference_cm"), + notes: text("notes"), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Logs: medications +export const medications = pgTable("medications", { + id: uuid("id").primaryKey().defaultRandom(), + childId: uuid("child_id").references(() => children.id).notNull(), + name: text("name").notNull(), + dosage: text("dosage"), + frequency: text("frequency"), + startDate: date("start_date").notNull(), + endDate: date("end_date"), + active: boolean("active").notNull().default(true), + notes: text("notes"), + createdAt: timestamp("created_at").defaultNow().notNull(), +}); + +// Type exports +export type Feed = typeof feeds.$inferSelect; +export type Diaper = typeof diapers.$inferSelect; +export type Sleep = typeof sleeps.$inferSelect; +export type Vaccination = typeof vaccinations.$inferSelect; +export type Growth = typeof growth.$inferSelect; +export type Medication = typeof medications.$inferSelect; \ No newline at end of file