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