import type { TFunction } from "i18next"; import type { Patient } from "@/lib/patients"; // Build and print a clean, one-page clinical summary for a patient. We render an // isolated HTML document in a new window and trigger the browser's print dialog // (where the user picks "Save as PDF") — no PDF library needed, and the output // follows the user's locale via the passed `t`. function esc(value: unknown): string { return String(value ?? "") .replace(/&/g, "&") .replace(//g, ">"); } function rows(items: { label: string; value: string }[]): string { return items .filter((r) => r.value) .map( (r) => `${esc(r.label)}${esc(r.value)}`, ) .join(""); } export function printPatientSummary(patient: Patient, t: TFunction): void { const sexLabel = t(`patientCard.sex.${patient.sex}`); const generated = new Date().toLocaleString(); const section = (title: string, body: string, empty: string): string => `

${esc(title)}

${body || `

${esc(empty)}

`}
`; const list = (items: string[]): string => items.length ? `` : ""; const html = ` ${esc(patient.name)} — ${esc(t("patientCard.pdf.title"))}

${esc(patient.name)}

${esc(`${patient.age} · ${sexLabel} · ${t("patientCard.summary.mrn")} ${patient.fileNumber}`)}
${esc(t("patientCard.pdf.generated", { date: generated }))}
${section( t("patientCard.overview"), `${rows([ { label: t("patientCard.summary.primaryCare"), value: patient.pcp }, { label: t("patientCard.summary.lastSeen"), value: patient.encounters[0]?.date ?? "" }, { label: t("patientCard.summary.status"), value: t(`patients.status.${patient.status}`) }, ])}
`, "", )} ${section( t("patientCard.allergies.title"), list( patient.allergies.map((a) => [a.substance, a.reaction, t(`patientCard.severity.${a.severity}`)] .filter(Boolean) .join(" — "), ), ), t("patientCard.allergies.none"), )} ${section( t("patientCard.problems.title"), list( patient.problems.map((p) => p.since ? `${p.label} (${p.since})` : p.label, ), ), t("patientCard.problems.empty"), )} ${section( t("patientCard.medications.title"), list( patient.medications.map((m) => [m.name, m.dose, m.frequency].filter(Boolean).join(" · "), ), ), t("patientCard.medications.empty"), )} ${section( t("patientCard.vitals.title"), `${rows([ { label: t("patientCard.vitals.bp"), value: patient.vitals.bp }, { label: t("patientCard.vitals.hr"), value: patient.vitals.hr }, { label: t("patientCard.vitals.temp"), value: patient.vitals.temp }, { label: t("patientCard.vitals.spo2"), value: patient.vitals.spo2 }, ])}
`, "", )} ${section( t("patientCard.labs.title"), list( patient.labs.map((l) => `${l.name}: ${l.value} (${t(`patientCard.labFlag.${l.flag}`)})`, ), ), t("patientCard.labs.empty"), )} ${section( t("patientCard.visits.title"), patient.encounters .map( (e) => `
${esc(e.type)} ${esc(e.date)} ${esc(e.provider)}
${esc(e.summary)}
`, ) .join(""), t("patientCard.visits.empty"), )} `; const win = window.open("", "_blank", "width=820,height=1000"); if (!win) return; win.document.open(); win.document.write(html); win.document.close(); win.focus(); // Let layout settle before invoking print. win.setTimeout(() => win.print(), 250); }