diff --git a/src/app/medical/page.tsx b/src/app/medical/page.tsx new file mode 100644 index 0000000..954e2a8 --- /dev/null +++ b/src/app/medical/page.tsx @@ -0,0 +1,152 @@ +"use client"; + +import { useState, useEffect } from "react"; + +// IAP Vaccination Schedule (India) +const IAP_SCHEDULE = [ + { name: "BCG", weeks: 0 }, + { name: "OPV-0", weeks: 0 }, + { name: "HepB-1", weeks: 0 }, + { name: "OPV-1", weeks: 6 }, + { name: "Pentavalent-1", weeks: 6 }, + { name: "PCV-1", weeks: 6 }, + { name: "Rota-1", weeks: 6 }, + { name: "OPV-2", weeks: 10 }, + { name: "Pentavalent-2", weeks: 10 }, + { name: "PCV-2", weeks: 10 }, + { name: "Rota-2", weeks: 10 }, + { name: "OPV-3", weeks: 14 }, + { name: "Pentavalent-3", weeks: 14 }, + { name: "PCV-3", weeks: 14 }, + { name: "Rota-3", weeks: 14 }, + { name: "MR-1", weeks: 48 }, // 9 months + { name: "JE-1", weeks: 48 }, + { name: "Vitamin A-1", weeks: 48 }, + { name: "OPV-4", weeks: 48 }, + { name: "MR-2", weeks: 96 }, // 18 months + { name: "JE-2", weeks: 96 }, + { name: "DPT-Booster-1", weeks: 96 }, + { name: "Vitamin A-2", weeks: 96 }, + { name: "OPV-5", weeks: 96 }, + { name: "DPT-Booster-2", weeks: 208 }, // 4 years + { name: "TT/Td", weeks: 208 }, +]; + +function calculateDueDate(birthDate: string, weeks: number): string { + const birth = new Date(birthDate); + birth.setDate(birth.getDate() + weeks * 7); + return birth.toISOString().split("T")[0]; +} + +export default function MedicalPage() { + const [childId] = useState("5ad3b16a-1e0d-45ab-bc91-038397d75d0a"); + const [vaccinations, setVaccinations] = useState([]); + const [loading, setLoading] = useState(true); + const [tab, setTab] = useState<"vaccinations" | "growth">("vaccinations"); + + const birthDate = "2024-01-15"; + + useEffect(() => { + fetch(`/api/vaccinations?childId=${childId}`) + .then((res) => res.json()) + .then((data) => { + setVaccinations(data.vaccinations || []); + setLoading(false); + }) + .catch(() => setLoading(false)); + }, [childId]); + + const handleMarkGiven = async (vaccineName: string) => { + const dueDate = calculateDueDate(birthDate, IAP_SCHEDULE.find((v) => v.name === vaccineName)?.weeks || 0); + + await fetch("/api/vaccinations", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + childId, + vaccineName, + scheduledDate: dueDate, + givenDate: new Date().toISOString().split("T")[0], + status: "given", + }), + }); + + setVaccinations((prev) => [...prev, { vaccine_name: vaccineName, status: "given" }]); + }; + + const isGiven = (name: string) => vaccinations.some((v) => v.vaccine_name === name && v.status === "given"); + const isPending = (name: string) => !isGiven(name); + + return ( +
+
+
+

Medical 💊

+ ← Home +
+ +
+ + +
+ + {tab === "vaccinations" && ( +
+

IAP Schedule

+ {loading ? ( +

Loading...

+ ) : ( + IAP_SCHEDULE.filter((v) => isPending(v.name) || isGiven(v.name)) + .sort((a, b) => a.weeks - b.weeks) + .map((vaccine) => { + const given = isGiven(vaccine.name); + const dueDate = calculateDueDate(birthDate, vaccine.weeks); + + return ( +
+
+
{vaccine.name}
+
+ Due: {new Date(dueDate).toLocaleDateString()} +
+
+ {given ? ( + ✓ Given + ) : ( + + )} +
+ ); + }) + )} +
+ )} + + {tab === "growth" && ( +
+

Growth tracking coming soon

+

Track weight, height, head circumference

+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/src/app/page.tsx b/src/app/page.tsx index 1254d96..aafc4b2 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,7 @@ "use client"; import { useState, useEffect } from "react"; +import Link from "next/link"; const OFFLINE_QUEUE_KEY = "tia_offline_queue"; @@ -246,8 +247,10 @@ export default function HomePage() {
Diaper