'use client'; import QRCode from 'react-qr-code'; import { useTranslations } from 'next-intl'; import { CaseSheetFdiChart } from '@/components/ui/lab/CaseSheetFdiChart'; import { buildCaseConnectedTeeth, buildCaseProsthesisRows, formatCaseDateTime, formatPatientName, } from '@/components/lab/caseDetailUtils'; import { formatToothList } from '@/components/treatment/prosthesisTypeDisplay'; import { prosthesisJobPathLabel } from '@/components/treatment/prosthesisJobPath'; import type { LabCaseDetail } from '@/types/cases'; import type { ProsthesisCatalogEntry } from '@/types/treatment-catalog'; import type { FdiToothId } from '@/types/treatment'; import { BrandLockup } from '@/components/ui/shared/BrandLockup'; export type CaseSheetLabels = { title: string; orderNumber: string; orderDate: string; dateDue: string; sender: string; recipient: string; patient: string; patientId: string; prosthesis: string; toothChart: string; connected: string; teeth: string; archUpper: string; archLower: string; comments: string; noComments: string; }; type CaseSheetPrintLayoutProps = { labCase: LabCaseDetail; locale: string; labels: CaseSheetLabels; prosthesisCatalog: readonly ProsthesisCatalogEntry[]; }; const muted = { color: '#64748b', fontSize: 10, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' as const }; const body = { color: '#0f172a', fontSize: 12 }; const rule = { borderTop: '1px solid #cbd5e1', marginTop: 18, paddingTop: 12 }; /** * Off-screen A4 layout for PDF capture. * Uses only hex/rgb inline styles — html2canvas cannot parse Tailwind v4 `lab()` / `oklch()`. */ export function CaseSheetPrintLayout({ labCase, locale, labels, prosthesisCatalog, }: CaseSheetPrintLayoutProps) { const tProsthesis = useTranslations('prosthesis'); const prosthesisRows = buildCaseProsthesisRows(labCase); const connectedTeeth = buildCaseConnectedTeeth(labCase); const selected = new Set(); if (labCase.detail) { for (const tooth of labCase.detail.teeth) selected.add(tooth as FdiToothId); } const labName = labCase.sends[0]?.organizationName ?? (labCase.sends.map((s) => s.organizationName).filter(Boolean).join(', ') || '—'); const fallbackOrder = labCase.id.replace(/-/g, '').slice(0, 8).toUpperCase(); const orderNumber = labCase.externalCode?.trim() || fallbackOrder; return (

{labels.title}

{labCase.shareUrl ? (
) : null}

{labels.prosthesis}

    {prosthesisRows.length === 0 ? (
  • ) : ( prosthesisRows.map((row) => { const label = prosthesisJobPathLabel( row.prosthesisTypeCode, prosthesisCatalog, (key) => tProsthesis(key as never), ); return (
  • {label} {row.connected ? ( {labels.connected} ) : null}

    {labels.teeth}: {formatToothList(row.teeth, { UA: labels.archUpper, LA: labels.archLower })}

  • ); }) )}
{selected.size > 0 ? ( <>

{labels.toothChart}

) : null}

{labels.comments}

{labCase.detail?.comment?.trim() || labels.noComments}

); } function MetaBlock({ label, value }: { label: string; value: string }) { return (

{label}

{value}

); } function PartyBlock({ label, title, subtitle, }: { label: string; title: string; subtitle?: string; }) { return (

{label}

{title}

{subtitle ? (

{subtitle}

) : null}
); }