Add notifications API for vaccine reminders
- API endpoint /api/notifications returns due/overdue vaccines - Checks child's birthDate to calculate due dates - Returns notifications with type, status, days overdue Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
3e54efaf66
commit
b93f1f5dcf
1 changed files with 97 additions and 0 deletions
97
src/app/api/notifications/route.ts
Normal file
97
src/app/api/notifications/route.ts
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import { NextResponse } from "next/server";
|
||||
import { sql } from "@/db";
|
||||
|
||||
// IAP Vaccination Schedule (weeks from birth)
|
||||
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 },
|
||||
{ name: "JE-1", weeks: 48 },
|
||||
{ name: "Vitamin A-1", weeks: 48 },
|
||||
{ name: "OPV-4", weeks: 48 },
|
||||
{ name: "MR-2", weeks: 96 },
|
||||
{ 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 },
|
||||
{ name: "Tetanus and adult diphtheria (Td)", weeks: 208 },
|
||||
];
|
||||
|
||||
export async function GET(request: Request) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const childId = searchParams.get("childId");
|
||||
|
||||
if (!childId) {
|
||||
return NextResponse.json({ error: "childId required" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Get child's birth date
|
||||
const children = await sql`
|
||||
SELECT id, name, birth_date FROM children WHERE id = ${childId}
|
||||
`;
|
||||
|
||||
if (!children || children.length === 0) {
|
||||
return NextResponse.json({ notifications: [] });
|
||||
}
|
||||
|
||||
const child = children[0];
|
||||
const birthDate = new Date(child.birth_date);
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
// Get already given vaccines
|
||||
const given = await sql`
|
||||
SELECT vaccine_name, given_date FROM vaccinations
|
||||
WHERE child_id = ${childId} AND status = 'given'
|
||||
`;
|
||||
const givenMap = new Set(given.map((v: any) => v.vaccine_name));
|
||||
|
||||
// Calculate upcoming vaccine notifications
|
||||
const notifications = [];
|
||||
for (const vaccine of IAP_SCHEDULE) {
|
||||
if (givenMap.has(vaccine.name)) continue;
|
||||
|
||||
// Calculate due date
|
||||
const dueDate = new Date(birthDate);
|
||||
dueDate.setDate(dueDate.getDate() + vaccine.weeks * 7);
|
||||
dueDate.setHours(0, 0, 0, 0);
|
||||
|
||||
const diffDays = Math.floor((dueDate.getTime() - today.getTime()) / (1000 * 60 * 60 * 24));
|
||||
|
||||
// Notify if due today or overdue
|
||||
if (diffDays <= 0) {
|
||||
notifications.push({
|
||||
id: `vaccine-${vaccine.name}`,
|
||||
type: "vaccine",
|
||||
title: diffDays === 0 ? "Vaccine Due Today" : "Vaccine Overdue",
|
||||
message: `${vaccine.name} is ${diffDays === 0 ? "due today" : `${Math.abs(diffDays)} days overdue`}`,
|
||||
vaccineName: vaccine.name,
|
||||
dueDate: dueDate.toISOString().split("T")[0],
|
||||
status: diffDays === 0 ? "due_today" : "overdue",
|
||||
childId,
|
||||
childName: child.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ notifications });
|
||||
} catch (error) {
|
||||
console.error("Notifications error:", error);
|
||||
return NextResponse.json({ error: String(error) }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue