New foundations: - src/types/index.ts — shared domain types (Child, Log, GrowthRecord, Medicine, Dose, Allergy, Visit, Illness, Vaccination, AIChat, ChatSession, Goal) - src/lib/formatting.ts — calculateAge, formatAge, formatTimeAgo (eliminates 3 duplicate implementations spread across page.tsx and growth/page.tsx) - src/lib/api.ts — typed fetch helpers (api.get/post/patch/delete) with consistent error handling; replaces manual fetch boilerplate New shared components: - src/components/PageHeader.tsx — reusable back-link + title header - src/components/TabBar.tsx — horizontal pill tab bar - src/components/CalendarView.tsx — extracted from activity/page.tsx (was ~170 inline lines) - src/components/medical/ — medical page split into 5 focused tab components: VaccineTab, MedicineTab, AllergyTab, VisitTab, IllnessTab Pages updated: - medical/page.tsx: 1029 → 42 lines (thin shell wiring the 5 tab components) - activity/page.tsx: uses CalendarView + shared Log type + api.ts - growth/page.tsx: uses shared GrowthRecord/Goal types + formatAge; fixes `any` catch clauses; fixes undefined → null in Chart.js dataset values - page.tsx (home): uses shared Log/AIChat/ChatSession types + formatTimeAgo/ calculateAge from formatting.ts; removes inline type definitions - ai/page.tsx: uses shared AIChat/ChatSession types - FamilyProvider.tsx: uses shared Child type; fixes `c: any` mapping Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
102 lines
1.7 KiB
TypeScript
102 lines
1.7 KiB
TypeScript
// Shared domain types — import from here rather than defining inline in each page
|
|
|
|
export interface Child {
|
|
id: string;
|
|
name: string;
|
|
birthDate: string;
|
|
sex: string;
|
|
}
|
|
|
|
export type LogType = "feed" | "diaper" | "sleep";
|
|
|
|
export interface Log {
|
|
id: string;
|
|
type: LogType;
|
|
subType?: string;
|
|
amount?: number | null;
|
|
notes?: string | null;
|
|
loggedAt: string;
|
|
}
|
|
|
|
export interface GrowthRecord {
|
|
id: string;
|
|
child_id: string;
|
|
measured_at: string;
|
|
weight_kg: number | null;
|
|
height_cm: number | null;
|
|
head_circumference_cm: number | null;
|
|
notes: string | null;
|
|
}
|
|
|
|
export interface Goal {
|
|
weightKg?: number;
|
|
heightCm?: number;
|
|
targetDate?: string;
|
|
}
|
|
|
|
export interface Medicine {
|
|
id: string;
|
|
name: string;
|
|
dose: string;
|
|
notes: string;
|
|
reminderTime?: string;
|
|
}
|
|
|
|
export interface DoseCorrection {
|
|
id: string;
|
|
corrected_value: Record<string, string>;
|
|
reason: string | null;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface Dose {
|
|
id: string;
|
|
administered_at: string;
|
|
amount_given: string | null;
|
|
notes: string | null;
|
|
corrections?: DoseCorrection[];
|
|
}
|
|
|
|
export interface Allergy {
|
|
id: string;
|
|
name: string;
|
|
severity: string;
|
|
notes: string;
|
|
}
|
|
|
|
export interface Visit {
|
|
id: string;
|
|
doctorName: string;
|
|
reason: string;
|
|
date: string;
|
|
notes: string;
|
|
}
|
|
|
|
export interface Illness {
|
|
id: string;
|
|
name: string;
|
|
startDate: string;
|
|
endDate?: string;
|
|
notes: string;
|
|
}
|
|
|
|
export interface Vaccination {
|
|
vaccine_name: string;
|
|
given_date: string;
|
|
status: "given" | "pending";
|
|
}
|
|
|
|
export interface AIChat {
|
|
id: string;
|
|
role: "user" | "assistant";
|
|
content: string;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface ChatSession {
|
|
id: string;
|
|
title: string;
|
|
messages: AIChat[];
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|