// ============================================================ // VACCINE SCHEDULE — full AAP/ACIP table, sourced live from // GET /api/schedule-data. // ============================================================ import { useQuery } from '@tanstack/react-query'; import { api } from '@/lib/api'; interface VisitAge { id: string; label: string; era: string } interface VaccineDose { vaccine: string; dose?: number | string; notes?: string } interface ScheduleData { visitAges: VisitAge[]; periodicity: Record; vaccineFullNames: Record; } export default function VaxSchedule() { const { data, isLoading, error } = useQuery({ queryKey: ['schedule-data'], queryFn: () => api.get('/api/schedule-data'), }); if (isLoading) return
Loading schedule…
; if (error) return
{(error as Error).message}
; if (!data) return null; const visitsWithVax = data.visitAges.filter((v) => data.periodicity[v.id]?.vaccines?.length); const vaxKeys: string[] = []; const seen = new Set(); visitsWithVax.forEach((v) => { data.periodicity[v.id].vaccines!.forEach((dose) => { if (!seen.has(dose.vaccine)) { seen.add(dose.vaccine); vaxKeys.push(dose.vaccine); } }); }); return (

Vaccine Schedule

AAP/ACIP 2025 complete immunization schedule (0–18 years).

{visitsWithVax.map((v) => ( ))} {vaxKeys.map((key) => ( {visitsWithVax.map((v) => { const vaxList = data.periodicity[v.id].vaccines || []; const match = vaxList.find((d) => d.vaccine === key); if (!match) return ); })} ))}
Vaccine {v.label}
{data.vaccineFullNames[key] || key} ; const label = typeof match.dose === 'number' ? '#' + match.dose : (match.dose || '•'); return ( {label}

Hover any filled cell for notes. Sources: AAP/Bright Futures (Feb 2025), CDC Child & Adolescent Immunization Schedule (2025).

); }