Skip to content

Commit 8bd75bb

Browse files
Merge pull request #62 from hack4impact/feature/60-child-registration-tables
feat(db): add children and emergency_contacts tables with related fields
2 parents f2a61d7 + ed808ea commit 8bd75bb

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

docs/schema-overview.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,60 @@ erDiagram
6262
timestamp updated_at
6363
}
6464
65+
children {
66+
uuid id PK
67+
uuid parent_id FK
68+
gender gender
69+
text first_name
70+
text last_name
71+
date dob
72+
text allergies
73+
text medical_conditions
74+
text medications
75+
timestamp created_at
76+
timestamp updated_at
77+
}
78+
79+
emergency_contacts {
80+
uuid id PK
81+
uuid child_id FK
82+
text full_name
83+
text email_address
84+
text phone_number
85+
text relationship
86+
timestamp created_at
87+
timestamp updated_at
88+
}
89+
90+
extra_questions {
91+
uuid id PK
92+
uuid service_id FK
93+
extra_question_type type
94+
text prompt
95+
jsonb options
96+
timestamp created_at
97+
timestamp updated_at
98+
}
99+
100+
extra_question_answers {
101+
uuid id PK
102+
uuid extra_question_id FK
103+
uuid child_id FK
104+
text answer "text[]"
105+
timestamp created_at
106+
timestamp updated_at
107+
}
108+
65109
profiles ||--o{ service_bookings : "books"
66110
services ||--o{ service_bookings : "booked via"
67111
profiles ||--o{ coaching_sessions : "coaches"
68112
profiles ||--o{ coaching_sessions : "attends"
69113
services ||--o{ coaching_sessions : "fulfilled by"
114+
profiles ||--o{ children : "parent of"
115+
children ||--o{ emergency_contacts : "has"
116+
services ||--o{ extra_questions : "defines"
117+
extra_questions ||--o{ extra_question_answers : "answered via"
118+
children ||--o{ extra_question_answers : "submits"
70119
```
71120

72121
## Enums
@@ -78,3 +127,5 @@ erDiagram
78127
| `booking_status` | `pending`, `confirmed`, `cancelled` |
79128
| `webinar_tier` | `free`, `premium` |
80129
| `session_status` | `pending`, `confirmed`, `cancelled`, `completed` |
130+
| `gender` | `male`, `female`, `prefer_not_to_say` |
131+
| `extra_question_type` | `text`, `multiple_choices`, `checkboxes`, `user_agreement` |

lib/db/schema.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ import {
1212

1313
export type ProgramSlot = { dayOfWeek: number; time: string };
1414

15+
export type ExtraQuestionOption = {
16+
id: string;
17+
title: string;
18+
description?: string;
19+
};
20+
1521
export const roleEnum = pgEnum("role", ["user", "admin", "coach"]);
1622
export const serviceTypeEnum = pgEnum("service_type", [
1723
"private_lessons",
@@ -35,6 +41,13 @@ export const serviceStatusEnum = pgEnum("service_status", [
3541
"deleted",
3642
"disabled",
3743
]);
44+
export const genderEnum = pgEnum("gender", ["male", "female", "prefer_not_to_say"]);
45+
export const extraQuestionTypeEnum = pgEnum("extra_question_type", [
46+
"text",
47+
"multiple_choices",
48+
"checkboxes",
49+
"user_agreement",
50+
]);
3851

3952
export const profiles = pgTable("profiles", {
4053
id: uuid("id").primaryKey(),
@@ -136,3 +149,57 @@ export const purchases = pgTable("purchases", {
136149
createdAt: timestamp("created_at").defaultNow().notNull(),
137150
updatedAt: timestamp("updated_at").defaultNow().notNull(),
138151
});
152+
153+
export const children = pgTable("children", {
154+
id: uuid("id").primaryKey().defaultRandom(),
155+
parentId: uuid("parent_id")
156+
.references(() => profiles.id, { onDelete: "cascade" })
157+
.notNull(),
158+
gender: genderEnum("gender").notNull(),
159+
firstName: text("first_name").notNull(),
160+
lastName: text("last_name").notNull(),
161+
dob: date("dob", { mode: "string" }).notNull(),
162+
allergies: text("allergies"),
163+
medicalConditions: text("medical_conditions"),
164+
medications: text("medications"),
165+
createdAt: timestamp("created_at").defaultNow().notNull(),
166+
updatedAt: timestamp("updated_at").defaultNow().notNull(),
167+
});
168+
169+
export const emergencyContacts = pgTable("emergency_contacts", {
170+
id: uuid("id").primaryKey().defaultRandom(),
171+
childId: uuid("child_id")
172+
.references(() => children.id, { onDelete: "cascade" })
173+
.notNull(),
174+
fullName: text("full_name").notNull(),
175+
emailAddress: text("email_address").notNull(),
176+
phoneNumber: text("phone_number").notNull(),
177+
relationship: text("relationship").notNull(),
178+
createdAt: timestamp("created_at").defaultNow().notNull(),
179+
updatedAt: timestamp("updated_at").defaultNow().notNull(),
180+
});
181+
182+
export const extraQuestions = pgTable("extra_questions", {
183+
id: uuid("id").primaryKey().defaultRandom(),
184+
serviceId: uuid("service_id")
185+
.references(() => services.id, { onDelete: "cascade" })
186+
.notNull(),
187+
type: extraQuestionTypeEnum("type").notNull(),
188+
prompt: text("prompt").notNull(),
189+
options: jsonb("options").$type<ExtraQuestionOption[]>(),
190+
createdAt: timestamp("created_at").defaultNow().notNull(),
191+
updatedAt: timestamp("updated_at").defaultNow().notNull(),
192+
});
193+
194+
export const extraQuestionAnswers = pgTable("extra_question_answers", {
195+
id: uuid("id").primaryKey().defaultRandom(),
196+
extraQuestionId: uuid("extra_question_id")
197+
.references(() => extraQuestions.id, { onDelete: "cascade" })
198+
.notNull(),
199+
childId: uuid("child_id")
200+
.references(() => children.id, { onDelete: "cascade" })
201+
.notNull(),
202+
answer: text("answer").array().notNull(),
203+
createdAt: timestamp("created_at").defaultNow().notNull(),
204+
updatedAt: timestamp("updated_at").defaultNow().notNull(),
205+
});

0 commit comments

Comments
 (0)