fix: home page vaccine reminder showing "undefined due today"

Two stacked causes:

1. ROOT CAUSE (home page field mismatch): the DB-backed notifications rewrite
   (678cf65) changed the API response shape, but the home page banner still read
   the OLD fields. It checked `notif.status === "overdue"` (no longer returned —
   now it's `title`) so it always fell to the else branch `${notif.vaccineName}
   due today`, and `vaccineName` no longer exists at top level (now in
   `metadata.vaccineName`) → rendered "undefined due today".
   Fix: render the complete server-built `message` ("BCG is N days overdue" /
   "BCG is due today"). Also filter to vaccine_* notifications so the banner can't
   show a log/memory/garment nudge under a "Vaccine Reminder" header.

2. Stale message data: an earlier generator had stored "undefined …" in the
   message itself, frozen by ON CONFLICT DO NOTHING. Delete legacy "undefined%"
   rows and switch vaccine upsert to DO UPDATE so messages (and overdue
   day-counts) stay correct instead of freezing the first version. is_read / id /
   created_at preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Manohar Gupta 2026-05-30 22:52:05 +05:30
parent ab937c4e9d
commit c1e02249d6
2 changed files with 12 additions and 4 deletions

View file

@ -401,9 +401,7 @@ export default function HomePage() {
<div>
<div className="font-semibold text-red-700">💊 Vaccine Reminder</div>
<div className="text-sm text-red-600">
{vaccineReminders[0].status === "overdue"
? `${vaccineReminders[0].message}`
: `${vaccineReminders[0].vaccineName} due today`}
{vaccineReminders[0].message}
</div>
</div>
<span className="text-red-400"></span>

View file

@ -83,6 +83,12 @@ export async function GET(request: NextRequest) {
const child = children[0];
const birthDate = new Date(child.birth_date as string);
// Self-heal legacy data: an earlier generator stored "undefined" in the
// message ("undefined is N days overdue"). Those rows were frozen by
// ON CONFLICT DO NOTHING. Delete them so the upsert below regenerates them
// with the correct vaccine name.
await sql`DELETE FROM notifications WHERE family_id = ${familyId} AND message LIKE 'undefined%'`;
// ── 1. Vaccine notifications ──────────────────────────────────────────────
const given = await sql`
SELECT vaccine_name FROM vaccinations
@ -118,7 +124,11 @@ export async function GET(request: NextRequest) {
${dueDateStr}::date,
${JSON.stringify({ vaccineName: v.name, dueDate: dueDateStr })}::jsonb
)
ON CONFLICT (family_id, child_id, type, scheduled_for) DO NOTHING
ON CONFLICT (family_id, child_id, type, scheduled_for) DO UPDATE SET
title = EXCLUDED.title,
message = EXCLUDED.message,
action_url = EXCLUDED.action_url,
metadata = EXCLUDED.metadata
`;
}