@primocaredentgroup/dental-digital-intake-ui 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/DigitalIntakeDashboard.tsx","../src/components/StatusBadge.tsx","../src/lib/mockHostContext.ts","../src/lib/validationUi.ts","../src/components/DigitalAcquisitionDetail.tsx","../src/lib/meshFormats.ts","../src/components/FileList.tsx","../src/components/UploadPanel.tsx","../src/components/ReviewPanel.tsx","../src/components/ManifestViewer.tsx","../src/components/CadProjectMetadataPanel.tsx","../src/components/CaseSummaryCard.tsx","../src/components/EventTimeline.tsx","../src/components/MeshViewer.tsx","../src/lib/meshLoaders.ts","../src/dentalGeom/DentalGeomIntakeViewport.ts","../src/dentalGeom/constants.ts","../src/dentalGeom/mockSegmentation.ts","../src/components/MeshFileSelector.tsx"],"sourcesContent":["import { useState } from \"react\";\nimport type { AcquisitionListRow } from \"@primocaredentgroup/dental-digital-intake-shared\";\nimport { StatusBadge } from \"./StatusBadge\";\nimport { hostAppLabel, originLabel, vendorLabel } from \"../lib/mockHostContext\";\nimport {\n validationProfileLabel,\n} from \"../lib/validationUi\";\n\nexport type DashboardFilters = {\n status: string;\n origin: string;\n vendor: string;\n hostApp: string;\n validationProfile: string;\n};\n\nexport const defaultDashboardFilters = (): DashboardFilters => ({\n status: \"\",\n origin: \"\",\n vendor: \"\",\n hostApp: \"\",\n validationProfile: \"\",\n});\n\nexport function DigitalIntakeDashboard({\n acquisitions,\n filters,\n onFiltersChange,\n onOpen,\n onCreateOpen,\n onSeedDemo,\n}: {\n acquisitions: AcquisitionListRow[] | undefined;\n filters: DashboardFilters;\n onFiltersChange: (patch: Partial<DashboardFilters>) => void;\n onOpen: (id: string) => void;\n onCreateOpen?: () => void;\n onSeedDemo?: () => Promise<void>;\n}) {\n const [seedBusy, setSeedBusy] = useState(false);\n\n const set = (patch: Partial<DashboardFilters>) =>\n onFiltersChange({ ...filters, ...patch });\n\n const kpis = {\n total: acquisitions?.length ?? 0,\n review:\n acquisitions?.filter((a) => a.status === \"needs_review\").length ?? 0,\n readyLab:\n acquisitions?.filter(\n (a) =>\n a.status === \"ready_for_next_step\" &&\n a.validationResult?.readinessLabel === \"ready_for_lab\",\n ).length ?? 0,\n readyCad:\n acquisitions?.filter(\n (a) =>\n a.status === \"ready_for_next_step\" &&\n a.validationResult?.readinessLabel === \"ready_for_cad\",\n ).length ?? 0,\n validationFailed:\n acquisitions?.filter(\n (a) =>\n a.validationResult != null && a.validationResult.isValid === false,\n ).length ?? 0,\n failed:\n acquisitions?.filter((a) => a.status === \"failed\").length ?? 0,\n };\n\n return (\n <div>\n <div className=\"kpi-grid\">\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.total}</div>\n <div className=\"kpi-label\">Acquisizioni in lista</div>\n </div>\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.review}</div>\n <div className=\"kpi-label\">Needs review</div>\n </div>\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.readyLab}</div>\n <div className=\"kpi-label\">Ready for Lab</div>\n </div>\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.readyCad}</div>\n <div className=\"kpi-label\">Ready for CAD</div>\n </div>\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.validationFailed}</div>\n <div className=\"kpi-label\">Validazione fallita</div>\n </div>\n <div className=\"kpi\">\n <div className=\"kpi-value\">{kpis.failed}</div>\n <div className=\"kpi-label\">Failed</div>\n </div>\n </div>\n\n <div className=\"panel\" style={{ marginBottom: \"1.25rem\" }}>\n <h3 style={{ marginTop: 0 }}>Filtri</h3>\n <div className=\"field-grid\">\n <div className=\"field\">\n <label>Stato</label>\n <select\n value={filters.status}\n onChange={(e) => set({ status: e.target.value })}\n >\n <option value=\"\">Tutti</option>\n <option value=\"draft\">draft</option>\n <option value=\"waiting_files\">waiting_files</option>\n <option value=\"uploaded\">uploaded</option>\n <option value=\"parsing\">parsing</option>\n <option value=\"needs_review\">needs_review</option>\n <option value=\"classified\">classified</option>\n <option value=\"linked\">linked</option>\n <option value=\"validated\">validated</option>\n <option value=\"ready_for_next_step\">ready_for_next_step</option>\n <option value=\"archived\">archived</option>\n <option value=\"failed\">failed</option>\n </select>\n </div>\n <div className=\"field\">\n <label>Origine</label>\n <select\n value={filters.origin}\n onChange={(e) => set({ origin: e.target.value })}\n >\n <option value=\"\">Tutte</option>\n <option value=\"clinic_intraoral\">clinic_intraoral</option>\n <option value=\"lab_bench_scan\">lab_bench_scan</option>\n <option value=\"unknown\">unknown</option>\n </select>\n </div>\n <div className=\"field\">\n <label>Vendor</label>\n <select\n value={filters.vendor}\n onChange={(e) => set({ vendor: e.target.value })}\n >\n <option value=\"\">Tutti</option>\n <option value=\"3shape\">3shape</option>\n <option value=\"itero\">itero</option>\n <option value=\"carestream\">carestream</option>\n <option value=\"sirona\">sirona</option>\n <option value=\"exocad\">exocad</option>\n <option value=\"unknown\">unknown</option>\n </select>\n </div>\n <div className=\"field\">\n <label>Host app</label>\n <select\n value={filters.hostApp}\n onChange={(e) => set({ hostApp: e.target.value })}\n >\n <option value=\"\">Tutte</option>\n <option value=\"primoupcore\">primoupcore</option>\n <option value=\"primolabcore\">primolabcore</option>\n <option value=\"standalone\">standalone</option>\n </select>\n </div>\n <div className=\"field\">\n <label>Profilo validazione</label>\n <select\n value={filters.validationProfile}\n onChange={(e) => set({ validationProfile: e.target.value })}\n >\n <option value=\"\">Tutti</option>\n <option value=\"clinic_intraoral_default\">\n {validationProfileLabel.clinic_intraoral_default}\n </option>\n <option value=\"lab_bench_scan_default\">\n {validationProfileLabel.lab_bench_scan_default}\n </option>\n <option value=\"generic_default\">\n {validationProfileLabel.generic_default}\n </option>\n </select>\n </div>\n </div>\n </div>\n\n <div className=\"btn-row\" style={{ marginBottom: \"1rem\" }}>\n {onCreateOpen ? (\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n onClick={() => onCreateOpen()}\n >\n Nuova acquisizione\n </button>\n ) : null}\n {onSeedDemo ? (\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={seedBusy}\n onClick={() => {\n setSeedBusy(true);\n void onSeedDemo()\n .catch(() => {})\n .finally(() => setSeedBusy(false));\n }}\n >\n Carica dati demo\n </button>\n ) : null}\n </div>\n\n {!acquisitions ? (\n <p className=\"muted\">Caricamento…</p>\n ) : (\n <div className=\"acq-grid\">\n {acquisitions.map((a) => (\n <button\n key={a._id}\n type=\"button\"\n className=\"acq-card\"\n onClick={() => onOpen(a._id)}\n >\n <div className=\"btn-row\" style={{ marginBottom: \"0.5rem\" }}>\n <StatusBadge status={a.status} />\n </div>\n <div className=\"acq-card-title\">{a.title}</div>\n <p className=\"acq-card-sub\">\n {originLabel(a.origin)} · {hostAppLabel(a.hostApp)}\n </p>\n <p className=\"acq-card-sub\">\n Vendor: {vendorLabel(a.sourceVendor)} (\n {a.vendorConfidence.toFixed(2)})\n </p>\n <p className=\"acq-card-sub\">\n Profilo validazione:{\" \"}\n <code style={{ fontSize: \"0.8rem\" }}>\n {a.validationProfile ?? \"—\"}\n </code>\n </p>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","import type { ReactNode } from \"react\";\n\nconst map: Record<string, string> = {\n draft: \"#94a3b8\",\n waiting_files: \"#38bdf8\",\n uploaded: \"#818cf8\",\n parsing: \"#fbbf24\",\n needs_review: \"#fb923c\",\n classified: \"#34d399\",\n linked: \"#22d3ee\",\n validated: \"#4ade80\",\n ready_for_next_step: \"#a78bfa\",\n archived: \"#64748b\",\n failed: \"#f87171\",\n};\n\nexport function StatusBadge({ status }: { status: string }) {\n const c = map[status] ?? \"#94a3b8\";\n return (\n <span\n className=\"badge\"\n style={{\n background: `${c}22`,\n color: \"#f8fafc\",\n border: `1px solid ${c}55`,\n }}\n >\n <span\n style={{\n width: 7,\n height: 7,\n borderRadius: \"50%\",\n background: c,\n display: \"inline-block\",\n }}\n />\n {status.replace(/_/g, \" \")}\n </span>\n );\n}\n\nexport function SmallBadge({\n children,\n variant,\n}: {\n children: ReactNode;\n variant: \"format\" | \"role\";\n}) {\n const cls = variant === \"format\" ? \"badge-format\" : \"badge-role\";\n return <span className={`badge ${cls}`}>{children}</span>;\n}\n","export const hostAppLabel = (h: string) =>\n ({\n primoupcore: \"PrimoUP Core\",\n primolabcore: \"PrimoLab Core\",\n standalone: \"Standalone\",\n })[h] ?? h;\n\nexport const originLabel = (o: string) =>\n ({\n clinic_intraoral: \"Clinica · intraorale\",\n lab_bench_scan: \"Laboratorio · da banco\",\n unknown: \"Origine non determinata\",\n })[o] ?? o;\n\nexport const vendorLabel = (v: string) =>\n ({\n \"3shape\": \"3Shape\",\n itero: \"iTero\",\n carestream: \"Carestream\",\n sirona: \"Sirona / Elios\",\n exocad: \"Exocad\",\n unknown: \"Vendor sconosciuto\",\n })[v] ?? v;\n","/** Solo UI example: etichette leggibili (il profilo effettivo è solo backend). */\n\nexport type ValidationProfileIdUi =\n | \"clinic_intraoral_default\"\n | \"lab_bench_scan_default\"\n | \"generic_default\";\n\nexport type OriginUi = \"clinic_intraoral\" | \"lab_bench_scan\" | \"unknown\";\n\nexport function defaultProfileForOriginUi(origin: OriginUi): ValidationProfileIdUi {\n if (origin === \"clinic_intraoral\") return \"clinic_intraoral_default\";\n if (origin === \"lab_bench_scan\") return \"lab_bench_scan_default\";\n return \"generic_default\";\n}\n\nexport const validationProfileLabel: Record<ValidationProfileIdUi, string> = {\n clinic_intraoral_default: \"Clinica intraorale (default)\",\n lab_bench_scan_default: \"Laboratorio / scansione da banco (default)\",\n generic_default: \"Generico (default)\",\n};\n\nexport const readinessLabelUi: Record<\n \"ready_for_lab\" | \"ready_for_cad\" | \"ready_for_next_step\",\n string\n> = {\n ready_for_lab: \"Ready for Lab\",\n ready_for_cad: \"Ready for CAD\",\n ready_for_next_step: \"Ready for Next Step\",\n};\n","import { type ReactNode, useMemo, useState } from \"react\";\nimport type {\n NormalizedManifest,\n ExternalReferencesMap,\n} from \"@primocaredentgroup/dental-digital-intake-shared\";\nimport type { PipelineBridge } from \"../bridges/pipelineBridge.js\";\nimport type { UploadBridge } from \"../bridges/uploadBridge.js\";\nimport type { ReviewBridge } from \"../bridges/reviewBridge.js\";\nimport { StatusBadge } from \"./StatusBadge\";\nimport { FileList, type ScanFile } from \"./FileList\";\nimport { UploadPanel } from \"./UploadPanel\";\nimport { ReviewPanel } from \"./ReviewPanel\";\nimport { ManifestViewer } from \"./ManifestViewer\";\nimport { CadProjectMetadataPanel } from \"./CadProjectMetadataPanel\";\nimport { CaseSummaryCard } from \"./CaseSummaryCard\";\nimport { EventTimeline, type AcquisitionEventRow } from \"./EventTimeline\";\nimport { MeshViewer, type MeshSegmentationBridge } from \"./MeshViewer.js\";\nimport { MeshFileSelector } from \"./MeshFileSelector\";\nimport { isMeshViewerFormat } from \"../lib/meshFormats\";\nimport { hostAppLabel, originLabel, vendorLabel } from \"../lib/mockHostContext\";\nimport {\n readinessLabelUi,\n validationProfileLabel,\n type ValidationProfileIdUi,\n} from \"../lib/validationUi\";\n\ntype ReadinessKey = keyof typeof readinessLabelUi;\n\nfunction readinessText(k: ReadinessKey | undefined): string {\n if (!k) return \"—\";\n return readinessLabelUi[k];\n}\n\n/** Snapshot documento acquisizione (campi usati dalla UI). */\nexport type AcquisitionDocumentModel = {\n title: string;\n status: string;\n origin: string;\n hostApp: string;\n reviewStatus: string;\n sourceVendor: string;\n vendorConfidence: number;\n warnings?: string[];\n /** Solo se acquisizione originata da adapter/provider ingestion. */\n sourceAdapterType?: string;\n sourceProviderId?: string;\n externalCaseId?: string;\n externalPatientId?: string;\n /** Borsa opaca persistita dai vendor / bridge host (JSON Convex-safe). */\n externalReferences?: ExternalReferencesMap | null;\n linkedEntity: {\n patientId?: string;\n prescriptionId?: string;\n labWorkOrderId?: string;\n customerId?: string;\n externalCaseId?: string;\n };\n extractionStatus?: string;\n extractionError?: string;\n originalPackageName?: string;\n originalPackageSizeBytes?: number;\n originalPackageStorageId?: string;\n validationProfile?: ValidationProfileIdUi;\n validationResult?: {\n isValid: boolean;\n blockingIssues: string[];\n warnings: string[];\n checkedAt: number;\n profileUsed: ValidationProfileIdUi;\n readinessLabel: keyof typeof readinessLabelUi;\n };\n};\n\nexport type DigitalAcquisitionDetailProps = {\n acquisitionId: string;\n onBack: () => void;\n /** Dati server; `undefined` durante il caricamento iniziale */\n doc: AcquisitionDocumentModel | undefined;\n files: ScanFile[] | undefined;\n events: AcquisitionEventRow[] | undefined;\n manifest: NormalizedManifest | null | undefined;\n packageDownloadUrl: string | null | undefined;\n /** URL mesh selezionata per il viewer (undefined = loading) */\n meshDownloadUrl: string | null | undefined;\n pipeline: PipelineBridge;\n upload: UploadBridge;\n review: ReviewBridge;\n /** Host rende il link “Scarica” per ogni riga file (es. Convex useQuery per URL) */\n renderFileListActions?: (file: ScanFile) => ReactNode;\n /** Controllato dall’host per collegare `getScanFileDownloadUrl` */\n previewMeshId: string | null;\n onPreviewMeshIdChange: (id: string | null) => void;\n /** Opzionale: servizio segmentazione denti (es. worker Python MeshSegNet). */\n meshSegmentationBridge?: MeshSegmentationBridge | null;\n};\n\nexport function DigitalAcquisitionDetail({\n acquisitionId,\n onBack,\n doc,\n files,\n events,\n manifest,\n packageDownloadUrl,\n meshDownloadUrl,\n meshSegmentationBridge,\n pipeline,\n upload,\n review,\n renderFileListActions,\n previewMeshId,\n onPreviewMeshIdChange,\n}: DigitalAcquisitionDetailProps) {\n const [patientId, setPatientId] = useState(\"\");\n const [prescriptionId, setPrescriptionId] = useState(\"\");\n const [labWorkOrderId, setLabWorkOrderId] = useState(\"\");\n const [customerId, setCustomerId] = useState(\"\");\n const [externalCaseId, setExternalCaseId] = useState(\"\");\n const [err, setErr] = useState<string | null>(null);\n const [busy, setBusy] = useState(false);\n\n const viewableMeshCount = useMemo(\n () => (files ?? []).filter((f) => isMeshViewerFormat(f.format)).length,\n [files],\n );\n\n const proprietary3dFiles = useMemo(\n () =>\n (files ?? []).filter((f) => {\n const fmt = f.format.toLowerCase();\n const ext = f.extension.toLowerCase();\n return [\"dcm\", \"3ml\"].includes(fmt) || [\"dcm\", \"3ml\"].includes(ext);\n }),\n [files],\n );\n\n const selectedMeshFile = useMemo(() => {\n if (!previewMeshId || !files?.length) return null;\n const f = files.find((x: ScanFile) => x._id === previewMeshId);\n if (!f) return null;\n return {\n _id: f._id,\n originalName: f.originalName,\n format: f.format,\n sizeBytes: f.sizeBytes,\n role: f.role,\n storageId: f.storageId,\n };\n }, [previewMeshId, files]);\n\n const run = async (fn: () => Promise<void>) => {\n setErr(null);\n setBusy(true);\n try {\n await fn();\n } catch (e) {\n setErr(e instanceof Error ? e.message : \"Errore\");\n } finally {\n setBusy(false);\n }\n };\n\n if (!doc) {\n return (\n <div className=\"panel\">\n <p className=\"muted\">Caricamento dettaglio…</p>\n </div>\n );\n }\n\n const extraction = doc.extractionStatus;\n const extractionError = doc.extractionError;\n const validationProfile = doc.validationProfile;\n const validationResult = doc.validationResult;\n const originalPackageName = doc.originalPackageName;\n const originalPackageSizeBytes = doc.originalPackageSizeBytes;\n const hasOriginalPackage = Boolean(doc.originalPackageStorageId);\n\n const terminal =\n doc.status === \"archived\" || doc.status === \"failed\";\n const canMutate = !terminal;\n\n const canBeginUpload = canMutate && doc.status === \"draft\";\n const canMarkUploaded = canMutate && doc.status === \"waiting_files\";\n const extractionBlocksParse =\n extraction === \"extracting\" || extraction === \"failed\";\n const canParse =\n canMutate &&\n doc.status === \"uploaded\" &&\n !extractionBlocksParse;\n const canValidate = canMutate && Boolean(manifest?.readiness.canValidate);\n const canMarkReady = canMutate && Boolean(manifest?.validation.canMarkReady);\n const canArchive = canMutate && doc.status === \"ready_for_next_step\";\n const canFail =\n canMutate && doc.status !== \"failed\" && doc.status !== \"archived\";\n\n const markReadyLabel =\n validationResult?.readinessLabel === \"ready_for_lab\"\n ? \"5 · Ready for Lab\"\n : validationResult?.readinessLabel === \"ready_for_cad\"\n ? \"5 · Ready for CAD\"\n : \"5 · Ready for Next Step\";\n\n return (\n <div>\n <div className=\"btn-row\" style={{ marginBottom: \"1rem\" }}>\n <button type=\"button\" className=\"btn btn-ghost\" onClick={onBack}>\n ← Dashboard\n </button>\n </div>\n\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <div className=\"btn-row\" style={{ marginBottom: \"0.75rem\" }}>\n <StatusBadge status={doc.status} />\n </div>\n <h2 style={{ margin: \"0 0 0.5rem\" }}>{doc.title}</h2>\n <p className=\"muted\" style={{ margin: 0 }}>\n {originLabel(doc.origin)} · {hostAppLabel(doc.hostApp)} · Review:{\" \"}\n {doc.reviewStatus} · Vendor {vendorLabel(doc.sourceVendor)} (\n {doc.vendorConfidence.toFixed(2)})\n </p>\n {doc.warnings?.length ? (\n <div className=\"warning-box\">\n <strong>Warning</strong>\n <div style={{ marginTop: \"0.35rem\" }}>\n {doc.warnings.join(\" · \")}\n </div>\n </div>\n ) : null}\n {(doc.sourceAdapterType ??\n doc.sourceProviderId ??\n doc.externalCaseId ??\n doc.externalPatientId ??\n (doc.externalReferences &&\n typeof doc.externalReferences === \"object\" &&\n Object.keys(doc.externalReferences).length > 0)) ? (\n <div\n style={{\n marginTop: \"0.75rem\",\n padding: \"0.65rem 0.85rem\",\n borderRadius: 12,\n background: \"rgba(59, 130, 246, 0.06)\",\n border: \"1px solid rgba(59, 130, 246, 0.2)\",\n fontSize: \"0.82rem\",\n }}\n >\n <strong style={{ color: \"#93c5fd\" }}>Riferimenti esterni / integrazioni</strong>\n <div className=\"muted\" style={{ marginTop: \"0.35rem\" }}>\n {doc.sourceAdapterType ? (\n <>\n Adapter:{\" \"}\n <code>{doc.sourceAdapterType}</code>\n <br />\n </>\n ) : null}\n {doc.sourceProviderId ? (\n <>\n Provider id:{\" \"}\n <code style={{ wordBreak: \"break-all\" }}>{doc.sourceProviderId}</code>\n <br />\n </>\n ) : null}\n {doc.externalCaseId ? (\n <>\n External case id:{\" \"}\n <code>{doc.externalCaseId}</code>\n <br />\n </>\n ) : null}\n {doc.externalPatientId ? (\n <>\n External patient id: <code>{doc.externalPatientId}</code>\n <br />\n </>\n ) : null}\n {doc.linkedEntity.externalCaseId && !doc.externalCaseId ? (\n <>\n Linked external case id:{\" \"}\n <code>{doc.linkedEntity.externalCaseId}</code>\n <br />\n </>\n ) : null}\n </div>\n {doc.externalReferences &&\n typeof doc.externalReferences === \"object\" &&\n Object.keys(doc.externalReferences).length > 0 ? (\n <div style={{ marginTop: \"0.5rem\" }}>\n <div className=\"muted\" style={{ marginBottom: \"0.25rem\" }}>\n <code style={{ fontSize: \"0.78rem\" }}>externalReferences</code>\n </div>\n <pre\n className=\"muted\"\n style={{\n margin: 0,\n maxHeight: 220,\n overflow: \"auto\",\n fontSize: \"0.75rem\",\n lineHeight: 1.35,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n }}\n >\n {JSON.stringify(doc.externalReferences, null, 2)}\n </pre>\n </div>\n ) : null}\n </div>\n ) : null}\n {terminal ? (\n <p className=\"muted\" style={{ marginTop: \"0.75rem\", marginBottom: 0 }}>\n Stato terminale: modifiche e upload disabilitati. Solo consultazione\n manifest e timeline.\n </p>\n ) : null}\n </div>\n\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Validazione (engine lato server)</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n Profilo:{\" \"}\n <strong>\n {validationProfile\n ? validationProfileLabel[validationProfile]\n : \"—\"}\n </strong>{\" \"}\n <code style={{ fontSize: \"0.8rem\" }}>({validationProfile ?? \"n/d\"})</code>\n </p>\n <p className=\"muted\">\n Readiness se validazione OK:{\" \"}\n <strong>\n {manifest?.validation.readinessLabel\n ? readinessText(manifest.validation.readinessLabel as ReadinessKey)\n : \"—\"}\n </strong>\n </p>\n {validationResult ? (\n <>\n <p className=\"muted\" style={{ marginBottom: \"0.35rem\" }}>\n Ultimo esito:{\" \"}\n <strong>\n {validationResult.isValid ? \"valido\" : \"non valido\"}\n </strong>{\" \"}\n · {new Date(validationResult.checkedAt).toLocaleString()}\n </p>\n {validationResult.blockingIssues.length ? (\n <div className=\"err-banner\">\n <strong>Blocking (ultimo run)</strong>\n <ul style={{ margin: \"0.35rem 0 0\", paddingLeft: \"1.1rem\" }}>\n {validationResult.blockingIssues.map((x: string) => (\n <li key={x}>{x}</li>\n ))}\n </ul>\n </div>\n ) : null}\n {validationResult.warnings.length ? (\n <div className=\"warning-box\" style={{ marginTop: \"0.5rem\" }}>\n <strong>Warning validazione</strong>\n <ul style={{ margin: \"0.35rem 0 0\", paddingLeft: \"1.1rem\" }}>\n {validationResult.warnings.map((x: string) => (\n <li key={x}>{x}</li>\n ))}\n </ul>\n </div>\n ) : null}\n </>\n ) : (\n <p className=\"muted\">Nessuna validazione formale registrata.</p>\n )}\n {manifest &&\n (manifest.validation.blockingIssues.length > 0 ||\n manifest.validation.warnings.length > 0) ? (\n <div style={{ marginTop: \"0.65rem\" }}>\n <strong className=\"muted\">Snapshot engine (manifest)</strong>\n {manifest.validation.blockingIssues.length ? (\n <ul\n className=\"muted\"\n style={{ margin: \"0.35rem 0 0\", paddingLeft: \"1.1rem\" }}\n >\n {manifest.validation.blockingIssues.map((x: string) => (\n <li key={x}>{x}</li>\n ))}\n </ul>\n ) : null}\n {manifest.validation.warnings.length ? (\n <ul\n className=\"muted\"\n style={{ margin: \"0.35rem 0 0\", paddingLeft: \"1.1rem\" }}\n >\n {manifest.validation.warnings.map((x: string) => (\n <li key={x}>{x}</li>\n ))}\n </ul>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {hasOriginalPackage ? (\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Pacchetto caricato</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n <strong>{originalPackageName ?? \"—\"}</strong>\n {originalPackageSizeBytes != null\n ? ` · ${(originalPackageSizeBytes / 1024).toFixed(1)} KB`\n : null}\n </p>\n <p className=\"muted\" style={{ margin: \"0.35rem 0\" }}>\n Estrazione: <code>{extraction ?? \"n/d\"}</code>\n {extraction === \"extracting\"\n ? \" — attendi il completamento sull’action Convex.\"\n : null}\n </p>\n {extractionError ? (\n <div className=\"err-banner\" style={{ marginTop: \"0.5rem\" }}>\n {extractionError}\n </div>\n ) : null}\n {packageDownloadUrl ? (\n <a\n href={packageDownloadUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"btn btn-ghost\"\n style={{ display: \"inline-block\", marginTop: \"0.5rem\" }}\n >\n Scarica pacchetto originale\n </a>\n ) : packageDownloadUrl === undefined && hasOriginalPackage ? (\n <p className=\"muted\" style={{ marginBottom: 0 }}>\n Recupero URL download…\n </p>\n ) : null}\n </div>\n ) : null}\n\n {manifest?.cadProject ? (\n <CaseSummaryCard\n cadProject={manifest.cadProject}\n fallbackTitle={doc.title}\n />\n ) : null}\n\n {manifest?.cadProject ? (\n <CadProjectMetadataPanel\n cadProject={manifest.cadProject}\n manifestFiles={manifest.files}\n />\n ) : null}\n\n {err ? <div className=\"err-banner\">{err}</div> : null}\n\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Azioni pipeline (enforce server-side)</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n Stato attuale: <strong>{doc.status}</strong>. I pulsanti disabilitati\n non sono ammessi dal backend in questa fase.\n </p>\n <div className=\"tool-grid\">\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy || !canBeginUpload}\n title={\n canBeginUpload\n ? \"Avvia sessione upload\"\n : \"Solo da draft e se non terminale\"\n }\n onClick={() =>\n void run(() => pipeline.beginUpload())\n }\n >\n 1 · Inizia upload\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy || !canMarkUploaded}\n title={\n canMarkUploaded\n ? \"Segna upload completato\"\n : \"Serve waiting_files e almeno un file\"\n }\n onClick={() =>\n void run(() => pipeline.markUploaded())\n }\n >\n 2 · Upload completato\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy || !canParse}\n title={\n canParse\n ? \"Lancia parsing server\"\n : extraction === \"extracting\"\n ? \"Estrazione ZIP in corso\"\n : extraction === \"failed\"\n ? \"Estrazione fallita\"\n : \"Serve stato uploaded\"\n }\n onClick={() => void run(() => pipeline.parse())}\n >\n 3 · Parsing\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy || !canValidate}\n title={\n canValidate\n ? \"Validazione server-only\"\n : manifest?.readiness.missingRequirements?.length\n ? manifest.readiness.missingRequirements.join(\" · \")\n : \"Stato non ammesso per validazione\"\n }\n onClick={() =>\n void run(() => pipeline.validate())\n }\n >\n 4 · Valida acquisizione\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy || !canMarkReady}\n title={\n canMarkReady\n ? manifest?.validation.nextStepSemanticLabel\n ? readinessText(\n manifest.validation.nextStepSemanticLabel as ReadinessKey,\n )\n : \"Ready\"\n : \"Serve validated + validationResult valido dal server\"\n }\n onClick={() =>\n void run(() => pipeline.markReady())\n }\n >\n {markReadyLabel}\n </button>\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={busy || !canArchive}\n title={\n canArchive ? \"Archivia\" : \"Serve ready_for_next_step\"\n }\n onClick={() =>\n void run(() => pipeline.archive())\n }\n >\n Archivia\n </button>\n <button\n type=\"button\"\n className=\"btn btn-danger\"\n disabled={busy || !canFail}\n title={\n canFail ? \"Imposta stato failed\" : \"Non disponibile (terminale)\"\n }\n onClick={() =>\n void run(() =>\n pipeline.fail(\"Segnalazione errore da UI example\"),\n )\n }\n >\n Segna failed\n </button>\n </div>\n </div>\n\n <div className=\"detail-layout\">\n <div>\n {(doc.status === \"draft\" || doc.status === \"waiting_files\") &&\n canMutate && (\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <UploadPanel upload={upload} />\n </div>\n )}\n\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>File</h3>\n {!files?.length ? (\n <p className=\"muted\">\n Nessun file associato. Usa l&apos;upload reale quando la pipeline\n lo consente, oppure i mock dalla dashboard se l&apos;MVP lo\n prevede.\n </p>\n ) : (\n <FileList\n files={files}\n renderFileActions={renderFileListActions}\n onVisualizeMesh={(f) => onPreviewMeshIdChange(f._id)}\n />\n )}\n </div>\n\n {doc.status === \"needs_review\" && canMutate && (\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <ReviewPanel\n key={\n files\n ?.map(\n (f: { _id: string; role: string }) => `${f._id}:${f.role}`,\n )\n .join(\"|\") ?? \"none\"\n }\n acquisitionId={acquisitionId}\n review={review}\n files={files?.map((f: ScanFile) => ({\n _id: f._id,\n originalName: f.originalName,\n role: f.role,\n format: f.format,\n storageId: f.storageId,\n }))}\n onPreviewMesh={(id) => onPreviewMeshIdChange(id)}\n />\n </div>\n )}\n\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Collegamento entità</h3>\n <p className=\"muted\">\n Requisiti MVP: clinica richiede patientId + prescriptionId; lab\n richiede labWorkOrderId. Il server decide se passare a linked.\n </p>\n <div className=\"field-grid\">\n <div className=\"field\">\n <label>patientId</label>\n <input\n value={patientId}\n onChange={(e) => setPatientId(e.target.value)}\n placeholder={doc.linkedEntity.patientId ?? \"\"}\n />\n </div>\n <div className=\"field\">\n <label>prescriptionId</label>\n <input\n value={prescriptionId}\n onChange={(e) => setPrescriptionId(e.target.value)}\n placeholder={doc.linkedEntity.prescriptionId ?? \"\"}\n />\n </div>\n <div className=\"field\">\n <label>labWorkOrderId</label>\n <input\n value={labWorkOrderId}\n onChange={(e) => setLabWorkOrderId(e.target.value)}\n placeholder={doc.linkedEntity.labWorkOrderId ?? \"\"}\n />\n </div>\n <div className=\"field\">\n <label>customerId</label>\n <input\n value={customerId}\n onChange={(e) => setCustomerId(e.target.value)}\n placeholder={doc.linkedEntity.customerId ?? \"\"}\n />\n </div>\n <div className=\"field\">\n <label>externalCaseId</label>\n <input\n value={externalCaseId}\n onChange={(e) => setExternalCaseId(e.target.value)}\n placeholder={doc.linkedEntity.externalCaseId ?? \"\"}\n />\n </div>\n </div>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n style={{ marginTop: \"0.75rem\" }}\n disabled={busy || !canMutate}\n onClick={() =>\n void run(() =>\n pipeline.updateLinkedEntity({\n patientId: patientId || undefined,\n prescriptionId: prescriptionId || undefined,\n labWorkOrderId: labWorkOrderId || undefined,\n customerId: customerId || undefined,\n externalCaseId: externalCaseId || undefined,\n }),\n )\n }\n >\n Aggiorna collegamenti\n </button>\n </div>\n\n <div className=\"panel\">\n <h3 style={{ marginTop: 0 }}>Manifest normalizzato (solo backend)</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n Generato dalle query Convex del componente, non costruito in UI.\n </p>\n <ManifestViewer manifest={manifest} />\n </div>\n </div>\n\n <div>\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Anteprima 3D</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n Viewer Three.js orthodontic-style (ispirato a{\" \"}\n <a\n href=\"https://github.com/Ellipsis1/DentalGeom\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n DentalGeom\n </a>\n ); i dati restano su storage Convex via URL firmato.\n </p>\n {viewableMeshCount === 0 ? (\n <div className=\"warning-box\" style={{ marginBottom: \"0.75rem\" }}>\n <strong>Nessuna mesh visualizzabile (STL / PLY / OBJ)</strong>\n <div style={{ marginTop: \"0.35rem\" }}>\n {proprietary3dFiles.length > 0 ? (\n <>\n Questo pacchetto contiene {proprietary3dFiles.length} file\n 3D in <strong>formati proprietari 3Shape</strong> (\n <code>.dcm</code> — non DICOM standard — e{\" \"}\n <code>.3ml</code>, spesso cifrati) che il viewer browser non\n può aprire. Per la preview 3D serve un export{\" \"}\n <strong>STL/PLY/OBJ</strong> dal software CAD.\n </>\n ) : (\n <>\n Carica o estrai file <strong>STL, PLY o OBJ</strong> per\n abilitare l&apos;anteprima 3D.\n </>\n )}\n </div>\n </div>\n ) : null}\n <MeshFileSelector\n files={files ?? undefined}\n selectedId={previewMeshId}\n onSelect={(f) => onPreviewMeshIdChange(f._id)}\n />\n <MeshViewer\n meshDownloadUrl={meshDownloadUrl}\n selectedFile={selectedMeshFile}\n segmentationBridge={meshSegmentationBridge}\n />\n </div>\n <div className=\"panel\">\n <h3 style={{ marginTop: 0 }}>Timeline eventi</h3>\n <EventTimeline events={events ?? undefined} />\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/** Format mesh supportati dal viewer 3D (solo example UI). */\nexport const MESH_VIEWER_FORMATS = [\"stl\", \"ply\", \"obj\"] as const;\nexport type MeshViewerFormat = (typeof MESH_VIEWER_FORMATS)[number];\n\nexport function isMeshViewerFormat(format: string): boolean {\n const f = format.toLowerCase();\n return (MESH_VIEWER_FORMATS as readonly string[]).includes(f);\n}\n\n/** Limite consigliato: avviso lato client prima di scaricare (allineato al backend ZIP per file). */\nexport const MESH_VIEWER_LARGE_BYTES = 250 * 1024 * 1024;\n","import type { ReactNode } from \"react\";\nimport { SmallBadge } from \"./StatusBadge\";\n\nimport { isMeshViewerFormat } from \"../lib/meshFormats\";\n\nexport type ScanFile = {\n _id: string;\n originalName: string;\n originalPath: string;\n extension: string;\n format: string;\n role: string;\n sizeBytes: number;\n classificationSource: string;\n warnings: string[];\n storageId?: string;\n extractedFromZip?: boolean;\n extractedPath?: string;\n};\n\nexport function FileList({\n files,\n onVisualizeMesh,\n renderFileActions,\n}: {\n files: ScanFile[] | undefined;\n onVisualizeMesh?: (file: ScanFile) => void;\n /** Host (es. Convex) fornisce link download / azioni per riga senza accoppiare questo package al client generato. */\n renderFileActions?: (file: ScanFile) => ReactNode;\n}) {\n if (!files?.length) return <p className=\"muted\">Nessun file caricato.</p>;\n return (\n <div>\n {files.map((f) => (\n <div key={f._id} className=\"file-row\">\n <div className=\"file-row-main\" style={{ flex: \"1 1 200px\" }}>\n <div style={{ fontWeight: 600, wordBreak: \"break-word\" }}>\n {f.originalName}\n </div>\n <div className=\"muted file-row-path\" style={{ fontSize: \"0.8rem\" }}>\n {f.originalPath}\n {f.extractedFromZip && f.extractedPath ? (\n <span>\n {\" \"}\n · da ZIP: <code>{f.extractedPath}</code>\n </span>\n ) : null}\n </div>\n {f.warnings?.length ? (\n <div className=\"warning-box\" style={{ marginTop: \"0.35rem\" }}>\n {f.warnings.join(\" · \")}\n </div>\n ) : null}\n </div>\n <SmallBadge variant=\"format\">{f.format}</SmallBadge>\n <SmallBadge variant=\"role\">{f.role}</SmallBadge>\n <span className=\"muted\" style={{ fontSize: \"0.8rem\" }}>\n {(f.sizeBytes / 1024).toFixed(1)} KB\n </span>\n <span className=\"muted\" style={{ fontSize: \"0.75rem\" }}>\n {f.classificationSource}\n </span>\n {renderFileActions ? renderFileActions(f) : null}\n {onVisualizeMesh &&\n isMeshViewerFormat(f.format) &&\n f.storageId ? (\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n style={{ fontSize: \"0.75rem\", padding: \"0.25rem 0.5rem\" }}\n onClick={() => onVisualizeMesh(f)}\n >\n Visualizza\n </button>\n ) : null}\n </div>\n ))}\n </div>\n );\n}\n","import { useState } from \"react\";\nimport { extractZipSafely, collectCadMetadataFromZipEntries } from \"@primocaredentgroup/dental-digital-intake-shared\";\nimport type { UploadBridge } from \"../bridges/uploadBridge.js\";\n\nfunction guessContentType(extension: string): string | undefined {\n const e = extension.toLowerCase();\n if (e === \"stl\") return \"model/stl\";\n if (e === \"ply\") return \"application/octet-stream\";\n if (e === \"obj\") return \"text/plain\";\n if (e === \"jpg\" || e === \"jpeg\") return \"image/jpeg\";\n if (e === \"png\") return \"image/png\";\n if (e === \"pdf\") return \"application/pdf\";\n if (e === \"json\") return \"application/json\";\n if (e === \"xml\") return \"application/xml\";\n if (e === \"txt\") return \"text/plain\";\n if (e === \"dcm\") return \"application/dicom\";\n return undefined;\n}\n\nexport function UploadPanel({\n upload,\n}: {\n upload: UploadBridge;\n}) {\n const [busy, setBusy] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n const [status, setStatus] = useState<string | null>(null);\n const [dragOver, setDragOver] = useState(false);\n\n const uploadZipViaBrowser = async (file: File) => {\n setErr(null);\n setBusy(true);\n setStatus(`Lettura ed estrazione ZIP in locale (${file.name})…`);\n try {\n const buf = new Uint8Array(await file.arrayBuffer());\n const extracted = extractZipSafely(buf);\n if (!extracted.ok) {\n setErr(extracted.fatal);\n setStatus(null);\n return;\n }\n const entries = extracted.entries;\n setStatus(\n `${entries.length} file da caricare (estrazione browser). Upload in corso…`,\n );\n const urls = await upload.generateBulkPackageUploadUrls(entries.length);\n if (urls.length !== entries.length) {\n throw new Error(\"Numero di URL di upload incoerente con i file estratti.\");\n }\n\n const filesPayload: Array<{\n storageId: string;\n originalName: string;\n extractedPath: string;\n extension: string;\n sizeBytes: number;\n contentType?: string;\n }> = [];\n\n for (let i = 0; i < entries.length; i++) {\n const eEntry = entries[i]!;\n setStatus(`Upload ${i + 1}/${entries.length}: ${eEntry.safePath}…`);\n const ct = guessContentType(eEntry.extension);\n const init: RequestInit = {\n method: \"POST\",\n body: new Blob([eEntry.data as BlobPart]),\n };\n if (ct) {\n init.headers = { \"Content-Type\": ct };\n }\n const uploadRes = await fetch(urls[i]!, init);\n if (!uploadRes.ok) {\n throw new Error(\n `Upload fallito per ${eEntry.safePath} (HTTP ${uploadRes.status}).`,\n );\n }\n const body = (await uploadRes.json()) as { storageId?: string };\n if (!body.storageId) {\n throw new Error(`Risposta storage senza storageId per ${eEntry.safePath}.`);\n }\n const baseName = eEntry.safePath.split(\"/\").pop() ?? eEntry.safePath;\n filesPayload.push({\n storageId: body.storageId,\n originalName: baseName,\n extractedPath: eEntry.safePath,\n extension: eEntry.extension,\n sizeBytes: eEntry.data.byteLength,\n contentType: ct,\n });\n }\n\n setStatus(\"Registrazione file sul server…\");\n const cadProjectMetadata = collectCadMetadataFromZipEntries(\n entries.map((e) => ({ safePath: e.safePath, data: e.data })),\n );\n await upload.registerClientExtractedZipFiles({\n originalZipFileName: file.name,\n zipWarnings: extracted.warnings,\n ...(cadProjectMetadata ? { cadProjectMetadata } : {}),\n files: filesPayload,\n });\n setStatus(\n \"ZIP processato nel browser e registrato: parsing avviato sul server.\",\n );\n } catch (e) {\n setErr(e instanceof Error ? e.message : \"Errore durante l'elaborazione ZIP.\");\n setStatus(null);\n } finally {\n setBusy(false);\n }\n };\n\n const uploadSingleOrServerSmallZip = async (file: File) => {\n setErr(null);\n setBusy(true);\n setStatus(`Caricamento su storage… (${file.name})`);\n try {\n const postUrl = await upload.generatePackageUploadUrl();\n const headers: Record<string, string> = file.type\n ? { \"Content-Type\": file.type }\n : {};\n const uploadRes = await fetch(postUrl, {\n method: \"POST\",\n headers,\n body: file,\n });\n if (!uploadRes.ok) {\n throw new Error(\n `Upload verso storage fallito (HTTP ${uploadRes.status}).`,\n );\n }\n const body = (await uploadRes.json()) as { storageId?: string };\n if (!body.storageId) {\n throw new Error(\"Risposta storage senza storageId.\");\n }\n setStatus(\"Registrazione pacchetto lato server…\");\n const result = await upload.registerUploadedPackage({\n storageId: body.storageId,\n originalFileName: file.name,\n declaredContentType: file.type || undefined,\n });\n if (result.kind === \"zip\") {\n setStatus(\n \"ZIP piccolo: estrazione sul backend in corso (aggiornamento automatico).\",\n );\n } else if (result.kind === \"zip_too_large\") {\n setErr(\n \"Questo ZIP supera il limite dell’estrazione server: usa sempre la modalità browser (trascina di nuovo il file).\",\n );\n setStatus(null);\n } else {\n setStatus(\"File singolo registrato: parsing avviato sul server.\");\n }\n } catch (e) {\n setErr(e instanceof Error ? e.message : \"Errore durante l'upload.\");\n setStatus(null);\n } finally {\n setBusy(false);\n }\n };\n\n const uploadFile = async (file: File) => {\n const lower = file.name.toLowerCase();\n const isZip =\n lower.endsWith(\".zip\") ||\n (file.type !== \"\" && file.type.toLowerCase().includes(\"zip\"));\n\n if (isZip) {\n await uploadZipViaBrowser(file);\n return;\n }\n await uploadSingleOrServerSmallZip(file);\n };\n\n const onInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n e.target.value = \"\";\n if (file) void uploadFile(file);\n };\n\n const onDrop = (e: React.DragEvent) => {\n e.preventDefault();\n setDragOver(false);\n const file = e.dataTransfer.files?.[0];\n if (file) void uploadFile(file);\n };\n\n return (\n <div>\n <h3 style={{ marginTop: 0 }}>Upload reale (Convex storage)</h3>\n <p className=\"muted\" style={{ marginTop: 0 }}>\n I file <strong>.zip</strong> sono estratti nel <strong>browser</strong> (RAM del\n tuo PC), poi ogni file operativo viene caricato su Convex: così non si applica il\n limite ~64 MB delle action sullo ZIP completo. File singoli (.stl, .ply, …)\n continuano a passare dall’upload classico.\n </p>\n {err ? <div className=\"err-banner\">{err}</div> : null}\n {status ? (\n <div className=\"panel\" style={{ marginBottom: \"0.75rem\", padding: \"0.65rem 1rem\" }}>\n {status}\n </div>\n ) : null}\n <div\n className={`upload-dropzone ${dragOver ? \"upload-dropzone-active\" : \"\"}`}\n onDragOver={(e) => {\n e.preventDefault();\n setDragOver(true);\n }}\n onDragLeave={() => setDragOver(false)}\n onDrop={onDrop}\n >\n <p style={{ margin: \"0 0 0.5rem\" }}>\n Trascina qui un file oppure scegli dal disco.\n </p>\n <input\n type=\"file\"\n disabled={busy}\n accept=\".zip,.stl,.ply,.obj,.dcm,.xml,.json,.png,.jpg,.jpeg,.pdf,.txt,application/zip\"\n onChange={onInputChange}\n />\n </div>\n <p className=\"muted\" style={{ fontSize: \"0.85rem\", marginBottom: 0 }}>\n ZIP → tipo rilevato dal nome / content-type; estrazione locale + più POST verso\n l’host. I file singoli usano l’upload classico lato server.\n </p>\n </div>\n );\n}\n","import { useState } from \"react\";\n\nimport { isMeshViewerFormat } from \"../lib/meshFormats\";\nimport type { ReviewBridge } from \"../bridges/reviewBridge.js\";\n\nconst roles = [\n \"upper_arch\",\n \"lower_arch\",\n \"bite\",\n \"scanbody\",\n \"abutment\",\n \"model\",\n \"impression\",\n \"dicom_volume\",\n \"project_file\",\n \"preview\",\n \"document\",\n \"unknown\",\n] as const;\n\ntype FileRow = {\n _id: string;\n originalName: string;\n role: string;\n format: string;\n storageId?: string;\n};\n\nexport function ReviewPanel({\n acquisitionId,\n files,\n review,\n onPreviewMesh,\n}: {\n acquisitionId: string;\n files: FileRow[] | undefined;\n review: ReviewBridge;\n onPreviewMesh?: (fileId: string) => void;\n}) {\n const [map, setMap] = useState<Record<string, string>>({});\n const [busy, setBusy] = useState(false);\n const [err, setErr] = useState<string | null>(null);\n\n const onRole = (id: string, role: string) => {\n setMap((m) => ({ ...m, [id]: role }));\n };\n\n const submit = async (rejected?: boolean) => {\n if (!files?.length) return;\n setErr(null);\n setBusy(true);\n try {\n await review.saveReview({\n acquisitionId,\n updates: files.map((f) => ({\n fileId: f._id,\n role: map[f._id] ?? f.role,\n })) as {\n fileId: string;\n role: (typeof roles)[number];\n }[],\n markRejected: rejected,\n });\n } catch (e) {\n setErr(e instanceof Error ? e.message : \"Errore review\");\n } finally {\n setBusy(false);\n }\n };\n\n if (!files?.length) return null;\n\n return (\n <div>\n <h3 style={{ marginTop: 0 }}>Review manuale</h3>\n <p className=\"muted\">\n Correggi il ruolo dei file: le modifiche sono applicate solo tramite\n mutation server-side.\n </p>\n {err ? <div className=\"err-banner\">{err}</div> : null}\n <div className=\"btn-row\" style={{ marginBottom: \"0.75rem\" }}>\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={busy}\n onClick={() =>\n void review.beginManualReview({ acquisitionId })\n }\n >\n Segna &quot;in review&quot;\n </button>\n </div>\n {files.map((f) => (\n <div key={f._id} className=\"field\" style={{ marginBottom: \"0.65rem\" }}>\n <div\n className=\"btn-row\"\n style={{\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: \"0.35rem\",\n }}\n >\n <label style={{ margin: 0 }}>{f.originalName}</label>\n {onPreviewMesh &&\n isMeshViewerFormat(f.format) &&\n f.storageId ? (\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n style={{ fontSize: \"0.75rem\", padding: \"0.25rem 0.55rem\" }}\n onClick={() => onPreviewMesh(f._id)}\n >\n Visualizza 3D\n </button>\n ) : null}\n </div>\n <select\n value={map[f._id] ?? f.role}\n onChange={(e) => onRole(f._id, e.target.value)}\n >\n {roles.map((r) => (\n <option key={r} value={r}>\n {r}\n </option>\n ))}\n </select>\n </div>\n ))}\n <div className=\"btn-row\" style={{ marginTop: \"1rem\" }}>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={busy}\n onClick={() => void submit(false)}\n >\n Salva review e classifica\n </button>\n <button\n type=\"button\"\n className=\"btn btn-danger\"\n disabled={busy}\n onClick={() => void submit(true)}\n >\n Respinti (solo review status)\n </button>\n </div>\n </div>\n );\n}\n","export function ManifestViewer({ manifest }: { manifest: unknown }) {\n if (manifest == null) {\n return <p className=\"muted\">Manifest non ancora disponibile.</p>;\n }\n return (\n <pre className=\"manifest-pre\">\n {JSON.stringify(manifest, null, 2)}\n </pre>\n );\n}\n","import type {\n CadProjectMetadata,\n CadSourceFileMetadata,\n ExocadConfidence,\n ExocadImplantComponent,\n ExocadSummary,\n ThreeShapeConfidence,\n ThreeShapeImplantComponent,\n ThreeShapeSummary,\n} from \"@primocaredentgroup/dental-digital-intake-shared\";\n\ntype ManifestFileRef = {\n originalName: string;\n};\n\nconst CONFIDENCE_LABEL: Record<ExocadConfidence, string> = {\n high: \"Alta\",\n medium: \"Media\",\n low: \"Bassa\",\n inferred: \"Dedotta\",\n};\n\nfunction ConfidenceBadge({\n confidence,\n}: {\n confidence: ExocadConfidence | ThreeShapeConfidence;\n}) {\n return (\n <span className={`confidence-badge confidence-${confidence}`}>\n {CONFIDENCE_LABEL[confidence]}\n </span>\n );\n}\n\nconst TS_COMPONENT_LABEL: Record<ThreeShapeImplantComponent[\"type\"], string> = {\n analog: \"Analogo\",\n analog_socket: \"Socket analogo\",\n scanbody: \"Scan body\",\n \"link/tibase_candidate\": \"Link / Ti-Base (candidato)\",\n screw_or_transmucosal_component_candidate: \"Vite / transmucoso (candidato)\",\n manufacturer_component_candidate: \"Componente produttore (candidato)\",\n unknown: \"Non classificato\",\n};\n\nfunction ImplantComponentCard({ comp }: { comp: ExocadImplantComponent }) {\n const geom = comp.parsedGeometry;\n return (\n <div className=\"implant-card\">\n <div className=\"implant-card-head\">\n <strong>{comp.manufacturer ?? \"Produttore n/d\"}</strong>\n <ConfidenceBadge confidence={comp.confidence} />\n </div>\n <dl className=\"implant-card-grid\">\n {comp.tooth ? (\n <>\n <dt>Dente</dt>\n <dd>{comp.tooth}</dd>\n </>\n ) : null}\n {comp.platform ? (\n <>\n <dt>Piattaforma</dt>\n <dd>{comp.platform}</dd>\n </>\n ) : null}\n {comp.connection ? (\n <>\n <dt>Connessione</dt>\n <dd>{comp.connection}</dd>\n </>\n ) : null}\n {comp.component ? (\n <>\n <dt>Componente</dt>\n <dd>{comp.component}</dd>\n </>\n ) : null}\n {comp.libraryName ? (\n <>\n <dt>Libreria Exocad</dt>\n <dd>{comp.libraryName}</dd>\n </>\n ) : null}\n {comp.geometryFile ? (\n <>\n <dt>File geometria</dt>\n <dd>\n <code>{comp.geometryFile}</code>\n </dd>\n </>\n ) : null}\n {comp.libraryPath ? (\n <>\n <dt>Path libreria</dt>\n <dd>\n <code className=\"implant-path\">{comp.libraryPath}</code>\n </dd>\n </>\n ) : null}\n </dl>\n {geom ? (\n <div className=\"implant-geom\">\n <span className=\"implant-geom-title\">\n Interpretazione codice (dedotta, da confermare)\n </span>\n <ul className=\"implant-geom-list\">\n {geom.baseType ? (\n <li>\n Tipo base: <strong>{geom.baseType.value}</strong>{\" \"}\n <ConfidenceBadge confidence={geom.baseType.confidence} />\n </li>\n ) : null}\n {geom.diameterOrPlatform ? (\n <li>\n Diametro/piattaforma:{\" \"}\n <strong>{geom.diameterOrPlatform.value}</strong>{\" \"}\n <ConfidenceBadge\n confidence={geom.diameterOrPlatform.confidence}\n />\n </li>\n ) : null}\n {geom.abutmentHeight ? (\n <li>\n Altezza abutment: <strong>{geom.abutmentHeight.value}</strong>{\" \"}\n <ConfidenceBadge confidence={geom.abutmentHeight.confidence} />\n </li>\n ) : null}\n </ul>\n </div>\n ) : null}\n <p className=\"implant-card-source muted\">\n Fonte: {comp.sourceFiles.join(\", \")}\n </p>\n </div>\n );\n}\n\nfunction ExocadComponentsSection({ exocad }: { exocad: ExocadSummary }) {\n const { implantComponents, case: caseInfo, restoration, model } = exocad;\n\n return (\n <div className=\"exocad-section\">\n <div className=\"exocad-case\">\n {caseInfo.patientName ? (\n <span>\n <strong>Paziente:</strong> {caseInfo.patientName}\n </span>\n ) : null}\n {caseInfo.practiceName ? (\n <span>\n <strong>Clinica:</strong> {caseInfo.practiceName}\n {caseInfo.practiceId ? ` (#${caseInfo.practiceId})` : \"\"}\n </span>\n ) : null}\n {restoration.span ? (\n <span>\n <strong>{restoration.isBridge ? \"Ponte\" : \"Span\"}:</strong>{\" \"}\n {restoration.span}\n </span>\n ) : null}\n {caseInfo.exocadVersion ? (\n <span className=\"muted\">{caseInfo.exocadVersion}</span>\n ) : null}\n </div>\n\n <div className=\"implant-box\">\n <div className=\"implant-box-head\">\n <strong>Componentistica rilevata</strong>\n <span\n className={`implant-flag ${exocad.isImplantCase ? \"is-implant\" : \"no-implant\"}`}\n >\n {exocad.isImplantCase ? \"Caso implantare\" : \"Nessun impianto rilevato\"}\n </span>\n </div>\n\n {implantComponents.length === 0 ? (\n <p className=\"muted\" style={{ margin: 0 }}>\n Nessuna componentistica implantare trovata nei file\n <code> .constructionInfo</code> / <code>.modelInfo</code>. Se il caso\n è su impianto, controlla che lo ZIP contenga questi file.\n </p>\n ) : (\n <div className=\"implant-card-list\">\n {implantComponents.map((comp, i) => (\n <ImplantComponentCard\n key={`${comp.geometryCode ?? comp.component ?? \"c\"}-${i}`}\n comp={comp}\n />\n ))}\n </div>\n )}\n\n {model.analogLibrary || model.modelWorkflow ? (\n <p className=\"muted implant-model\">\n {model.analogLibrary ? (\n <>\n Libreria analoghi: <strong>{model.analogLibrary}</strong>.{\" \"}\n </>\n ) : null}\n {model.modelWorkflow ? (\n <>\n Workflow modello: <strong>{model.modelWorkflow}</strong>.\n </>\n ) : null}\n </p>\n ) : null}\n\n {exocad.warnings.length > 0 ? (\n <ul className=\"implant-warnings\">\n {exocad.warnings.map((w) => (\n <li key={w}>{w}</li>\n ))}\n </ul>\n ) : null}\n </div>\n </div>\n );\n}\n\nfunction zipPathForSourceFile(\n sourceFile: string,\n files: ManifestFileRef[],\n): string | undefined {\n const base = sourceFile.replace(/\\\\/g, \"/\").split(\"/\").pop() ?? sourceFile;\n const match = files.find(\n (f) =>\n f.originalName === sourceFile ||\n f.originalName.endsWith(`/${base}`) ||\n f.originalName.split(\"/\").pop() === base,\n );\n return match?.originalName;\n}\n\nfunction CadSourceFileBlock({\n entry,\n zipPath,\n defaultOpen,\n}: {\n entry: CadSourceFileMetadata;\n zipPath?: string;\n defaultOpen?: boolean;\n}) {\n const hasDetails =\n entry.projectName ||\n entry.projectDirectory ||\n entry.toothNumbers.length > 0 ||\n entry.materials.length > 0 ||\n entry.shades.length > 0 ||\n entry.reconstructions.length > 0;\n\n return (\n <details className=\"cad-source-file\" open={defaultOpen}>\n <summary>\n <code>{entry.sourceFile}</code>\n {entry.source === \"exocad\" ? (\n <span className=\"cad-source-file-vendor\"> · Exocad</span>\n ) : null}\n </summary>\n {zipPath && zipPath !== entry.sourceFile ? (\n <p className=\"cad-source-file-path\">\n Nel pacchetto ZIP: <code>{zipPath}</code>\n </p>\n ) : null}\n {!hasDetails ? (\n <p className=\"muted\" style={{ margin: \"0.5rem 0 0\" }}>\n Nessun campo strutturato estratto da questo file (formato XML non\n riconosciuto o file vuoto).\n </p>\n ) : (\n <div className=\"cad-source-file-body\">\n {entry.projectName ? (\n <p>\n <strong>Progetto:</strong> {entry.projectName}\n </p>\n ) : null}\n {entry.projectDirectory ? (\n <p>\n <strong>Directory:</strong> {entry.projectDirectory}\n </p>\n ) : null}\n {entry.toothNumbers.length > 0 ? (\n <p>\n <strong>Denti (FDI):</strong> {entry.toothNumbers.join(\", \")}\n </p>\n ) : null}\n {entry.materials.length > 0 ? (\n <p>\n <strong>Materiali:</strong> {entry.materials.join(\", \")}\n </p>\n ) : null}\n {entry.shades.length > 0 ? (\n <p>\n <strong>Colori / shade:</strong> {entry.shades.join(\", \")}\n </p>\n ) : null}\n {entry.reconstructions.length > 0 ? (\n <div>\n <span className=\"cad-recon-label\">Elementi</span>\n <ul className=\"cad-recon-list\">\n {entry.reconstructions.map((r, i) => (\n <li key={`${entry.sourceFile}-${r.toothNumbers.join(\"-\")}-${i}`}>\n {r.toothNumbers.length\n ? `Denti ${r.toothNumbers.join(\", \")}`\n : \"Elemento\"}\n {r.reconstructionType ? ` · ${r.reconstructionType}` : null}\n {r.material ? ` · ${r.material}` : null}\n {r.shade ? ` · ${r.shade}` : null}\n {r.meshFileName ? ` · ${r.meshFileName}` : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n </div>\n )}\n {entry.parseWarnings.length > 0 ? (\n <ul className=\"cad-recon-list muted\" style={{ fontSize: \"0.88rem\" }}>\n {entry.parseWarnings.map((w) => (\n <li key={w}>{w}</li>\n ))}\n </ul>\n ) : null}\n </details>\n );\n}\n\nfunction ThreeShapeSection({ ts }: { ts: ThreeShapeSummary }) {\n const { case: caseInfo, restoration, implant } = ts;\n\n return (\n <div className=\"exocad-section\">\n <div className=\"exocad-case\">\n {caseInfo.patientName ? (\n <span>\n <strong>Paziente:</strong> {caseInfo.patientName}\n </span>\n ) : null}\n {caseInfo.orderId ? (\n <span>\n <strong>Ordine:</strong> {caseInfo.orderId}\n </span>\n ) : null}\n {caseInfo.customer ? (\n <span>\n <strong>Cliente:</strong> {caseInfo.customer}\n </span>\n ) : null}\n {restoration.teeth.length > 0 ? (\n <span>\n <strong>Denti (FDI):</strong> {restoration.teeth.join(\", \")}\n </span>\n ) : null}\n {restoration.type ? (\n <span>\n <strong>Lavorazione:</strong> {restoration.type}\n </span>\n ) : null}\n {restoration.materialName ? (\n <span>\n <strong>Materiale:</strong> {restoration.materialName}\n </span>\n ) : null}\n <span className=\"muted\">{caseInfo.software}</span>\n </div>\n\n <div className=\"implant-box\">\n <div className=\"implant-box-head\">\n <strong>Componentistica rilevata · 3Shape</strong>\n <span\n className={`implant-flag ${implant.isImplantCase ? \"is-implant\" : \"no-implant\"}`}\n >\n {implant.isImplantCase\n ? \"Caso implantare\"\n : \"Nessun impianto rilevato\"}\n </span>\n </div>\n\n {implant.isImplantCase ? (\n <dl className=\"implant-card-grid\" style={{ marginBottom: \"0.6rem\" }}>\n {implant.manufacturer ? (\n <>\n <dt>Produttore</dt>\n <dd>{implant.manufacturer}</dd>\n </>\n ) : null}\n {implant.connection ? (\n <>\n <dt>Connessione</dt>\n <dd>{implant.connection}</dd>\n </>\n ) : null}\n {implant.abutmentKitId ? (\n <>\n <dt>Abutment kit</dt>\n <dd>\n <code>{implant.abutmentKitId}</code>\n </dd>\n </>\n ) : null}\n {implant.connectionId ? (\n <>\n <dt>Connection ID</dt>\n <dd>\n <code>{implant.connectionId}</code>\n </dd>\n </>\n ) : null}\n {implant.implantSystemId ? (\n <>\n <dt>Implant system ID</dt>\n <dd>\n <code>{implant.implantSystemId}</code>\n </dd>\n </>\n ) : null}\n </dl>\n ) : null}\n\n {implant.components.length > 0 ? (\n <div className=\"ts-components\">\n <span className=\"implant-geom-title\">Componenti trovati</span>\n <ul className=\"ts-component-list\">\n {implant.components.map((c) => (\n <li key={c.sourcePath}>\n <code>{c.fileName}</code>\n <span className=\"ts-component-type\">\n {TS_COMPONENT_LABEL[c.type]}\n </span>\n <ConfidenceBadge confidence={c.confidence} />\n </li>\n ))}\n </ul>\n </div>\n ) : implant.isImplantCase ? (\n <p className=\"muted\" style={{ margin: 0 }}>\n Caso implantare ma nessun componente trovato in\n <code> External models/</code>.\n </p>\n ) : null}\n\n {ts.warnings.length > 0 ? (\n <ul className=\"implant-warnings\">\n {ts.warnings.map((w) => (\n <li key={w}>{w}</li>\n ))}\n </ul>\n ) : null}\n </div>\n </div>\n );\n}\n\nexport function CadProjectMetadataPanel({\n cadProject,\n manifestFiles = [],\n}: {\n cadProject: CadProjectMetadata;\n manifestFiles?: ManifestFileRef[];\n}) {\n const perFile = cadProject.bySourceFile ?? [];\n const hasPerFileBreakdown = perFile.length > 0;\n\n return (\n <div className=\"panel\" style={{ marginBottom: \"1rem\" }}>\n <h3 style={{ marginTop: 0 }}>Metadati progetto CAD</h3>\n <div className=\"cad-project-summary\">\n <p className=\"muted\" style={{ marginTop: 0 }}>\n Riepilogo da{\" \"}\n <code>{cadProject.sourceFiles.join(\", \")}</code>\n {cadProject.source === \"exocad\" ? \" · Exocad\" : null}\n </p>\n {cadProject.projectName ? (\n <p style={{ margin: \"0.35rem 0\" }}>\n <strong>Progetto:</strong> {cadProject.projectName}\n </p>\n ) : null}\n {cadProject.toothNumbers.length > 0 ? (\n <p style={{ margin: \"0.35rem 0\" }}>\n <strong>Denti (FDI):</strong> {cadProject.toothNumbers.join(\", \")}\n </p>\n ) : null}\n {cadProject.materials.length > 0 ? (\n <p style={{ margin: \"0.35rem 0\" }}>\n <strong>Materiali:</strong> {cadProject.materials.join(\", \")}\n </p>\n ) : null}\n {cadProject.shades.length > 0 ? (\n <p style={{ margin: \"0.35rem 0\" }}>\n <strong>Colori / shade:</strong> {cadProject.shades.join(\", \")}\n </p>\n ) : null}\n </div>\n\n {cadProject.exocad ? (\n <ExocadComponentsSection exocad={cadProject.exocad} />\n ) : null}\n\n {cadProject.threeShape ? (\n <ThreeShapeSection ts={cadProject.threeShape} />\n ) : null}\n\n <strong className=\"cad-source-files-title\">Dettaglio per file sorgente</strong>\n {!hasPerFileBreakdown ? (\n <p className=\"muted\" style={{ margin: 0, fontSize: \"0.9em\" }}>\n File analizzati:{\" \"}\n <code>{cadProject.sourceFiles.join(\", \")}</code>. Ri-carica lo ZIP per\n vedere i campi estratti separatamente da ciascun file.\n </p>\n ) : (\n perFile.map((entry, index) => (\n <CadSourceFileBlock\n key={entry.sourceFile}\n entry={entry}\n zipPath={zipPathForSourceFile(entry.sourceFile, manifestFiles)}\n defaultOpen={index === 0}\n />\n ))\n )}\n </div>\n );\n}\n","import type { CadProjectMetadata } from \"@primocaredentgroup/dental-digital-intake-shared\";\n\ntype SimpleSummary = {\n patientName: string | null;\n software: string | null;\n scanSource: string | null;\n workTypes: string[];\n teeth: string[];\n materials: string[];\n shades: string[];\n isImplant: boolean;\n manufacturer: string | null;\n connection: string | null;\n abutmentKit: string | null;\n components: string[];\n vendor: \"Exocad\" | \"3Shape\" | \"—\";\n};\n\nfunction uniq(values: Array<string | null | undefined>): string[] {\n return [...new Set(values.filter((v): v is string => Boolean(v)))];\n}\n\nfunction buildSummary(cad: CadProjectMetadata): SimpleSummary {\n const ex = cad.exocad;\n const ts = cad.threeShape;\n\n const vendor: SimpleSummary[\"vendor\"] = ts\n ? \"3Shape\"\n : ex || cad.source === \"exocad\"\n ? \"Exocad\"\n : \"—\";\n\n const software = ts\n ? uniq([ts.case.software, ts.case.softwareVersion]).join(\" \") || null\n : (ex?.case.exocadVersion ?? null);\n\n const workTypes = ts?.restoration.type\n ? [ts.restoration.type]\n : ex\n ? uniq(ex.restoration.items.map((i) => i.type))\n : uniq(cad.reconstructions.map((r) => r.reconstructionType));\n\n const teeth =\n ts && ts.restoration.teeth.length > 0\n ? ts.restoration.teeth.map(String)\n : ex && ex.restoration.teeth.length > 0\n ? ex.restoration.teeth\n : cad.toothNumbers.map(String);\n\n const materials = ts?.restoration.materialName\n ? [ts.restoration.materialName]\n : cad.materials;\n\n const shades = ts?.restoration.shade ? [ts.restoration.shade] : cad.shades;\n\n const isImplant = ts?.implant.isImplantCase ?? ex?.isImplantCase ?? false;\n\n const manufacturer =\n ts?.implant.manufacturer ??\n ex?.implantComponents.find((c) => c.manufacturer)?.manufacturer ??\n null;\n\n const connection =\n ts?.implant.connection ??\n ex?.implantComponents.find((c) => c.connection)?.connection ??\n null;\n\n const components = ts\n ? ts.implant.components.map((c) => c.fileName)\n : ex\n ? ex.implantComponents.map(\n (c) => c.component ?? c.geometryFile ?? c.manufacturer ?? \"componente\",\n )\n : [];\n\n return {\n patientName: ex?.case.patientName ?? ts?.case.patientName ?? null,\n software,\n scanSource: ts?.case.scanSource ?? null,\n workTypes,\n teeth,\n materials,\n shades,\n isImplant,\n manufacturer,\n connection,\n abutmentKit: ts?.implant.abutmentKitId ?? null,\n components,\n vendor,\n };\n}\n\nfunction Row({\n label,\n children,\n}: {\n label: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"summary-row\">\n <span className=\"summary-label\">{label}</span>\n <span className=\"summary-value\">{children}</span>\n </div>\n );\n}\n\n/** Riepilogo \"umano\" del caso (paziente, lavorazione, scanner, denti, shade, componentistica). */\nexport function CaseSummaryCard({\n cadProject,\n fallbackTitle,\n}: {\n cadProject: CadProjectMetadata;\n fallbackTitle?: string;\n}) {\n const s = buildSummary(cadProject);\n\n return (\n <div className=\"panel summary-card\" style={{ marginBottom: \"1rem\" }}>\n <div className=\"summary-head\">\n <h3 style={{ margin: 0 }}>\n {s.patientName ?? fallbackTitle ?? \"Riepilogo caso\"}\n </h3>\n {s.vendor !== \"—\" ? (\n <span className=\"vendor-pill vendor-detail\">{s.vendor}</span>\n ) : null}\n </div>\n <div className=\"summary-list\">\n <Row label=\"Lavorazione\">\n {s.workTypes.length > 0 ? s.workTypes.join(\", \") : \"—\"}\n </Row>\n <Row label=\"Software / scanner\">\n {s.software ?? \"—\"}\n {s.scanSource ? ` · ${s.scanSource}` : \"\"}\n </Row>\n <Row label=\"Denti (FDI)\">\n {s.teeth.length > 0 ? s.teeth.join(\", \") : \"—\"}\n </Row>\n <Row label=\"Materiale\">\n {s.materials.length > 0 ? s.materials.join(\", \") : \"—\"}\n </Row>\n <Row label=\"Shade / colore\">\n {s.shades.length > 0 ? s.shades.join(\", \") : \"—\"}\n </Row>\n <Row label=\"Tipo caso\">\n <span\n className={`case-flag ${s.isImplant ? \"case-implant\" : \"case-noimplant\"}`}\n >\n {s.isImplant ? \"Implantare\" : \"Non implantare\"}\n </span>\n </Row>\n {s.isImplant ? (\n <>\n <Row label=\"Produttore\">{s.manufacturer ?? \"Non identificato\"}</Row>\n <Row label=\"Connessione\">{s.connection ?? \"—\"}</Row>\n {s.abutmentKit ? (\n <Row label=\"Abutment kit\">\n <code>{s.abutmentKit}</code>\n </Row>\n ) : null}\n {s.components.length > 0 ? (\n <Row label=\"Componenti\">{s.components.join(\", \")}</Row>\n ) : null}\n </>\n ) : null}\n </div>\n </div>\n );\n}\n","export type AcquisitionEventRow = {\n _id: string;\n _creationTime: number;\n type: string;\n message: string;\n createdAt: number;\n payload?: unknown;\n};\n\nexport function EventTimeline({\n events,\n}: {\n events: AcquisitionEventRow[] | undefined;\n}) {\n if (!events?.length) {\n return (\n <p className=\"muted\">\n Nessun evento registrato. Le azioni sul backend appariranno qui in ordine\n cronologico.\n </p>\n );\n }\n return (\n <div className=\"timeline\">\n {events.map((e) => (\n <div key={e._id} className=\"timeline-item\">\n <div style={{ fontSize: \"0.72rem\", color: \"#8ea0bf\" }}>\n {new Date(e.createdAt).toLocaleString(\"it-IT\")}\n </div>\n <div style={{ fontWeight: 600, marginTop: \"0.15rem\" }}>{e.type}</div>\n <div className=\"muted\" style={{ marginTop: \"0.2rem\" }}>\n {e.message}\n </div>\n </div>\n ))}\n </div>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport { BufferAttribute, Group, Mesh } from \"three\";\nimport {\n isMeshViewerFormat,\n MESH_VIEWER_LARGE_BYTES,\n} from \"../lib/meshFormats\";\nimport {\n disposeObject3DTree,\n loadMeshByFormat,\n normalizeMeshRoot,\n wrapLoadedMeshRoot,\n} from \"../lib/meshLoaders\";\nimport { DentalGeomIntakeViewport } from \"../dentalGeom/DentalGeomIntakeViewport.js\";\nimport type { ViewDirection } from \"../dentalGeom/constants.js\";\nimport {\n applyMockToothBandColors,\n enableVertexColorsOnObjectTree,\n} from \"../dentalGeom/mockSegmentation.js\";\n\nexport type MeshViewerFile = {\n _id: string;\n originalName: string;\n format: string;\n sizeBytes: number;\n role: string;\n storageId?: string;\n};\n\n/**\n * Opzionale: inferenza MeshSegNet (o altro) lato host — es. HTTP verso worker Python.\n * Se omesso, il pulsante «Segmenta» usa solo la demo locale {@link applyMockToothBandColors}.\n * @see https://github.com/Tai-Hsien/MeshSegNet\n */\nexport type MeshSegmentationBridge = {\n segmentMesh?: (args: {\n arrayBuffer: ArrayBuffer;\n format: string;\n fileName: string;\n }) => Promise<Float32Array | null>;\n};\n\nconst VIEW_BUTTONS: { key: ViewDirection; label: string }[] = [\n { key: \"TOP\", label: \"Sopra\" },\n { key: \"BOTTOM\", label: \"Sotto\" },\n { key: \"FRONT\", label: \"Fronte\" },\n { key: \"BACK\", label: \"Retro\" },\n { key: \"LEFT\", label: \"Sin\" },\n { key: \"RIGHT\", label: \"Des\" },\n];\n\n/**\n * Viewer 3D basato sullo stack DentalGeom (camera ortografica, luci, OrbitControls `three-stdlib`).\n * Scarica la mesh da `meshDownloadUrl`.\n */\nexport function MeshViewer({\n meshDownloadUrl,\n selectedFile,\n segmentationBridge,\n}: {\n meshDownloadUrl: string | null | undefined;\n selectedFile: MeshViewerFile | null;\n segmentationBridge?: MeshSegmentationBridge | null;\n}) {\n const containerRef = useRef<HTMLDivElement | null>(null);\n const viewportRef = useRef<DentalGeomIntakeViewport | null>(null);\n const backupRootRef = useRef<Group | null>(null);\n const sceneRootLiveRef = useRef<Group | null>(null);\n\n const [phase, setPhase] = useState<\n \"idle\" | \"confirm_large\" | \"loading\" | \"ready\" | \"error\"\n >(\"idle\");\n const [errorMsg, setErrorMsg] = useState<string | null>(null);\n const [confirmedLarge, setConfirmedLarge] = useState(false);\n const [sceneRoot, setSceneRoot] = useState<Group | null>(null);\n const [segmented, setSegmented] = useState(false);\n const [segBusy, setSegBusy] = useState(false);\n\n useEffect(() => {\n sceneRootLiveRef.current = sceneRoot;\n }, [sceneRoot]);\n\n useEffect(() => {\n return () => {\n if (sceneRootLiveRef.current) {\n disposeObject3DTree(sceneRootLiveRef.current);\n sceneRootLiveRef.current = null;\n }\n if (backupRootRef.current) {\n disposeObject3DTree(backupRootRef.current);\n backupRootRef.current = null;\n }\n };\n }, []);\n\n useEffect(() => {\n if (!selectedFile) {\n if (viewportRef.current) {\n viewportRef.current.dispose();\n viewportRef.current = null;\n }\n return;\n }\n const el = containerRef.current;\n if (!el) return;\n const vp = new DentalGeomIntakeViewport(el);\n viewportRef.current = vp;\n return () => {\n vp.dispose();\n viewportRef.current = null;\n };\n }, [selectedFile?._id]);\n\n useEffect(() => {\n setConfirmedLarge(false);\n setSegmented(false);\n setErrorMsg(null);\n setSceneRoot((prev) => {\n if (prev) disposeObject3DTree(prev);\n return null;\n });\n if (backupRootRef.current) {\n disposeObject3DTree(backupRootRef.current);\n backupRootRef.current = null;\n }\n\n if (!selectedFile) {\n setPhase(\"idle\");\n return;\n }\n\n if (!isMeshViewerFormat(selectedFile.format)) {\n setPhase(\"error\");\n setErrorMsg(\n `Formato «${selectedFile.format}» non supportato nel viewer (solo STL, PLY, OBJ).`,\n );\n return;\n }\n\n if (!selectedFile.storageId) {\n setPhase(\"error\");\n setErrorMsg(\n \"Nessun file su storage per questa mesh (es. record solo mock senza upload reale).\",\n );\n return;\n }\n\n if (selectedFile.sizeBytes > MESH_VIEWER_LARGE_BYTES) {\n setPhase(\"confirm_large\");\n } else {\n setPhase(\"loading\");\n }\n }, [selectedFile?._id]);\n\n useEffect(() => {\n if (!selectedFile || !isMeshViewerFormat(selectedFile.format)) return;\n if (!selectedFile.storageId) return;\n\n if (\n selectedFile.sizeBytes > MESH_VIEWER_LARGE_BYTES &&\n !confirmedLarge\n ) {\n return;\n }\n\n if (meshDownloadUrl === undefined) {\n setPhase(\"loading\");\n return;\n }\n\n if (meshDownloadUrl === null) {\n setPhase(\"error\");\n setErrorMsg(\n \"URL di download non disponibile. L’acquisizione potrebbe essere archiviata oppure il file non ha storage.\",\n );\n return;\n }\n\n let cancelled = false;\n\n (async () => {\n try {\n setPhase(\"loading\");\n setErrorMsg(null);\n\n const res = await fetch(meshDownloadUrl);\n if (!res.ok) {\n throw new Error(`Download fallito (HTTP ${res.status}).`);\n }\n const buf = await res.arrayBuffer();\n if (cancelled) return;\n\n const loaded = loadMeshByFormat(selectedFile.format, buf);\n const wrapped = wrapLoadedMeshRoot(loaded);\n\n if (backupRootRef.current) {\n disposeObject3DTree(backupRootRef.current);\n }\n backupRootRef.current = wrapped.clone(true);\n\n const normalized = wrapped.clone(true);\n const fmt = selectedFile.format.toLowerCase();\n if (fmt === \"stl\") {\n normalized.rotation.x = Math.PI;\n }\n normalizeMeshRoot(normalized, 2);\n\n if (cancelled) {\n disposeObject3DTree(normalized);\n return;\n }\n\n setSceneRoot((prev) => {\n if (prev) disposeObject3DTree(prev);\n return normalized;\n });\n setPhase(\"ready\");\n } catch (e) {\n if (cancelled) return;\n setPhase(\"error\");\n setErrorMsg(\n e instanceof Error\n ? e.message\n : \"Errore durante il caricamento della mesh.\",\n );\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [\n selectedFile?._id,\n selectedFile?.format,\n selectedFile?.storageId,\n selectedFile?.sizeBytes,\n meshDownloadUrl,\n confirmedLarge,\n ]);\n\n useEffect(() => {\n const vp = viewportRef.current;\n if (!vp || phase !== \"ready\" || !sceneRoot) {\n vp?.setRootObject(null);\n return;\n }\n vp.setRootObject(sceneRoot);\n vp.centerCameraOnObject();\n }, [phase, sceneRoot]);\n\n const handleRecentrar = () => {\n const raw = backupRootRef.current;\n if (!raw || !selectedFile) return;\n setSegmented(false);\n setSceneRoot((prev) => {\n if (prev) disposeObject3DTree(prev);\n const next = raw.clone(true);\n if (selectedFile.format.toLowerCase() === \"stl\") {\n next.rotation.x = Math.PI;\n }\n normalizeMeshRoot(next, 2);\n return next;\n });\n };\n\n const handleView = (v: ViewDirection) => {\n viewportRef.current?.setCameraView(v);\n };\n\n const runSegmentation = async () => {\n const sf = selectedFile;\n if (!sf || !backupRootRef.current) return;\n if (segmentationBridge?.segmentMesh && (!meshDownloadUrl || meshDownloadUrl === null)) {\n setErrorMsg(\"URL mesh mancante per segmentazione remota.\");\n return;\n }\n\n setSegBusy(true);\n setErrorMsg(null);\n try {\n let rgb: Float32Array | null = null;\n if (segmentationBridge?.segmentMesh && meshDownloadUrl) {\n const res = await fetch(meshDownloadUrl);\n if (!res.ok) throw new Error(`Segmentazione: download HTTP ${res.status}`);\n const buf = await res.arrayBuffer();\n rgb = await segmentationBridge.segmentMesh({\n arrayBuffer: buf,\n format: sf.format,\n fileName: sf.originalName,\n });\n }\n\n const next = backupRootRef.current.clone(true);\n if (sf.format.toLowerCase() === \"stl\") {\n next.rotation.x = Math.PI;\n }\n normalizeMeshRoot(next, 2);\n\n let remaining: Float32Array | null =\n rgb && rgb.length > 0 ? rgb : null;\n\n next.traverse((o) => {\n if (o instanceof Mesh && o.geometry) {\n const geo = o.geometry;\n const pos = geo.getAttribute(\"position\");\n const need = pos ? pos.count * 3 : 0;\n if (remaining !== null && need > 0 && remaining.length >= need) {\n const chunk = remaining.subarray(0, need);\n const copy = new Float32Array(chunk);\n geo.setAttribute(\"color\", new BufferAttribute(copy, 3));\n remaining = remaining.subarray(need);\n } else {\n applyMockToothBandColors(geo);\n }\n }\n });\n enableVertexColorsOnObjectTree(next);\n\n setSceneRoot((prev) => {\n if (prev) disposeObject3DTree(prev);\n return next;\n });\n setSegmented(true);\n } catch (e) {\n setErrorMsg(\n e instanceof Error ? e.message : \"Segmentazione non riuscita.\",\n );\n } finally {\n setSegBusy(false);\n }\n };\n\n if (!selectedFile) {\n return (\n <div className=\"preview-3d preview-3d-empty\">\n <strong>Anteprima 3D</strong>\n <span>\n Seleziona una mesh (STL, PLY, OBJ) dalla lista o dal pannello review.\n </span>\n </div>\n );\n }\n\n return (\n <div className=\"mesh-viewer-wrap\">\n <div className=\"mesh-viewer-toolbar\">\n <span className=\"muted\" style={{ fontSize: \"0.8rem\", marginRight: \"0.5rem\" }}>\n Viewer{\" \"}\n <a\n href=\"https://github.com/Ellipsis1/DentalGeom\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n style={{ color: \"#93c5fd\" }}\n >\n DentalGeom\n </a>\n -style\n </span>\n {VIEW_BUTTONS.map(({ key, label }) => (\n <button\n key={key}\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={!sceneRoot}\n onClick={() => handleView(key)}\n >\n {label}\n </button>\n ))}\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={!sceneRoot}\n onClick={() => viewportRef.current?.centerCameraOnObject()}\n >\n Centra camera\n </button>\n <button\n type=\"button\"\n className=\"btn btn-ghost\"\n disabled={!sceneRoot}\n onClick={handleRecentrar}\n >\n Reset modello\n </button>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n disabled={!sceneRoot || segBusy || phase !== \"ready\"}\n title={\n segmentationBridge?.segmentMesh\n ? \"Segmentazione tramite bridge host (es. MeshSegNet worker)\"\n : \"Demo locale (bande color)—non è MeshSegNet clinico\"\n }\n onClick={() => void runSegmentation()}\n >\n {segBusy\n ? \"Segmentazione…\"\n : segmented\n ? \"Ri-segmenta\"\n : \"Segmenta denti\"}\n </button>\n </div>\n\n <p className=\"muted\" style={{ fontSize: \"0.76rem\", margin: \"0.25rem 0\" }}>\n MeshSegNet (\n <a\n href=\"https://github.com/Tai-Hsien/MeshSegNet\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Tai-Hsien/MeshSegNet\n </a>\n ) è PyTorch: esporre un servizio esterno e passare{\" \"}\n <code>segmentationBridge</code> dall’host, oppure usare la demo colori\n locale.\n </p>\n\n {phase === \"confirm_large\" ? (\n <div className=\"warning-box\" style={{ marginBottom: \"0.65rem\" }}>\n File di {(selectedFile.sizeBytes / (1024 * 1024)).toFixed(1)} MB: il\n caricamento può essere lento o instabile nel browser. Continuare?\n <div className=\"btn-row\" style={{ marginTop: \"0.5rem\" }}>\n <button\n type=\"button\"\n className=\"btn btn-primary\"\n onClick={() => setConfirmedLarge(true)}\n >\n Carica nel viewer\n </button>\n </div>\n </div>\n ) : null}\n\n {phase === \"loading\" ? (\n <p className=\"muted\" style={{ margin: \"0.35rem 0 0.5rem\" }}>\n Caricamento mesh…\n </p>\n ) : null}\n\n {errorMsg ? <div className=\"err-banner\">{errorMsg}</div> : null}\n\n <div\n ref={containerRef}\n className=\"mesh-viewer-canvas dentalgeom-viewport\"\n style={{ minHeight: 420, width: \"100%\", borderRadius: 12 }}\n />\n </div>\n );\n}\n","/**\n * Loader mesh Three.js per l’example (STL / PLY / OBJ).\n *\n * TODO futuri (fuori scope):\n * - DICOM volume + viewer volumetrico dedicato\n * - Mesh repair / misurazioni distanza tra punti\n * - Annotazioni 3D persistenti\n * - Confronto affiancato upper / lower / bite registrati\n * - Report qualità mesh (holes, non-manifold, area)\n */\nimport {\n Box3,\n BufferGeometry,\n Group,\n Mesh,\n MeshStandardMaterial,\n Object3D,\n Vector3,\n DoubleSide,\n} from \"three\";\nimport { STLLoader } from \"three/examples/jsm/loaders/STLLoader.js\";\nimport { PLYLoader } from \"three/examples/jsm/loaders/PLYLoader.js\";\nimport { OBJLoader } from \"three/examples/jsm/loaders/OBJLoader.js\";\n\nfunction neutralMaterial(): MeshStandardMaterial {\n return new MeshStandardMaterial({\n color: 0xb8c4dc,\n metalness: 0.06,\n roughness: 0.42,\n side: DoubleSide,\n flatShading: false,\n });\n}\n\nexport function loadStlMesh(data: ArrayBuffer): Mesh {\n const loader = new STLLoader();\n const geometry = loader.parse(data);\n geometry.computeVertexNormals();\n return new Mesh(geometry, neutralMaterial());\n}\n\nexport function loadPlyMesh(data: ArrayBuffer): Mesh {\n const loader = new PLYLoader();\n const geometry = loader.parse(data);\n geometry.computeVertexNormals();\n return new Mesh(geometry, neutralMaterial());\n}\n\nexport function loadObjMesh(data: ArrayBuffer): Group {\n const text = new TextDecoder(\"utf-8\").decode(data);\n const loader = new OBJLoader();\n const group = loader.parse(text);\n group.traverse((child) => {\n if (child instanceof Mesh) {\n child.material = neutralMaterial();\n if (child.geometry instanceof BufferGeometry) {\n child.geometry.computeVertexNormals();\n }\n }\n });\n return group;\n}\n\n/** Restituisce un {@link Mesh} o {@link Group} (OBJ multi-oggetto). */\nexport function loadMeshByFormat(\n format: string,\n data: ArrayBuffer,\n): Mesh | Group {\n const f = format.toLowerCase();\n if (f === \"stl\") return loadStlMesh(data);\n if (f === \"ply\") return loadPlyMesh(data);\n if (f === \"obj\") return loadObjMesh(data);\n throw new Error(`Formato mesh non supportato nel viewer: ${format}`);\n}\n\n/**\n * Incapsula il risultato del loader in un {@link Group} radice unico.\n */\nexport function wrapLoadedMeshRoot(loaded: Mesh | Group): Group {\n const root = new Group();\n root.add(loaded);\n return root;\n}\n\n/**\n * Centra nel sistema di riferimento e scala per entrare in una box ~targetSize.\n */\nexport function normalizeMeshRoot(root: Object3D, targetSize = 2): Box3 {\n root.updateMatrixWorld(true);\n const box = new Box3().setFromObject(root);\n const center = new Vector3();\n const size = new Vector3();\n box.getCenter(center);\n box.getSize(size);\n\n root.position.sub(center);\n\n const maxDim = Math.max(size.x, size.y, size.z, 1e-6);\n const s = targetSize / maxDim;\n root.scale.setScalar(s);\n\n root.updateMatrixWorld(true);\n return new Box3().setFromObject(root);\n}\n\nexport function disposeObject3DTree(root: Object3D | null): void {\n if (!root) return;\n root.traverse((obj) => {\n if (obj instanceof Mesh) {\n obj.geometry?.dispose();\n const m = obj.material;\n if (Array.isArray(m)) {\n for (const x of m) x.dispose();\n } else {\n m?.dispose();\n }\n }\n });\n}\n","/**\n * Viewer Three.js ispirato a DentalGeom (camera ortografica, OrbitControls, luci studio).\n * Montaggio su un container React (non fullscreen).\n * @see https://github.com/Ellipsis1/DentalGeom\n */\nimport * as THREE from \"three\";\nimport { OrbitControls } from \"three-stdlib\";\nimport {\n ANIMATION_CONFIG,\n CAMERA_CONFIG,\n CONTROLS_CONFIG,\n LIGHTING_CONFIG,\n RENDERER_CONFIG,\n SCENE_CONFIG,\n VIEW_DIRECTIONS,\n type ViewDirection,\n} from \"./constants.js\";\n\nfunction setupLights(scene: THREE.Scene): void {\n const L = LIGHTING_CONFIG;\n scene.add(new THREE.AmbientLight(L.AMBIENT.COLOR, L.AMBIENT.INTENSITY));\n const key = new THREE.DirectionalLight(L.KEY_LIGHT.COLOR, L.KEY_LIGHT.INTENSITY);\n key.position.set(\n L.KEY_LIGHT.POSITION.x,\n L.KEY_LIGHT.POSITION.y,\n L.KEY_LIGHT.POSITION.z,\n );\n scene.add(key);\n const fill = new THREE.DirectionalLight(L.FILL_LIGHT.COLOR, L.FILL_LIGHT.INTENSITY);\n fill.position.set(\n L.FILL_LIGHT.POSITION.x,\n L.FILL_LIGHT.POSITION.y,\n L.FILL_LIGHT.POSITION.z,\n );\n scene.add(fill);\n const rim = new THREE.DirectionalLight(L.RIM_LIGHT.COLOR, L.RIM_LIGHT.INTENSITY);\n rim.position.set(\n L.RIM_LIGHT.POSITION.x,\n L.RIM_LIGHT.POSITION.y,\n L.RIM_LIGHT.POSITION.z,\n );\n scene.add(rim);\n scene.add(\n new THREE.HemisphereLight(\n L.HEMISPHERE.SKY_COLOR,\n L.HEMISPHERE.GROUND_COLOR,\n L.HEMISPHERE.INTENSITY,\n ),\n );\n}\n\nexport class DentalGeomIntakeViewport {\n readonly scene: THREE.Scene;\n readonly camera: THREE.OrthographicCamera;\n readonly renderer: THREE.WebGLRenderer;\n readonly controls: OrbitControls;\n\n private readonly container: HTMLElement;\n private rootObject: THREE.Object3D | null = null;\n private animationHandle: number | null = null;\n private resizeObserver: ResizeObserver | null = null;\n\n private readonly tick = (): void => {\n this.animationHandle = requestAnimationFrame(this.tick);\n this.controls.update();\n this.renderer.render(this.scene, this.camera);\n };\n\n constructor(container: HTMLElement) {\n this.container = container;\n this.scene = new THREE.Scene();\n this.scene.background = new THREE.Color(SCENE_CONFIG.BACKGROUND_COLOR);\n\n const w = Math.max(1, container.clientWidth);\n const h = Math.max(1, container.clientHeight);\n this.camera = new THREE.OrthographicCamera(\n -1,\n 1,\n 1,\n -1,\n CAMERA_CONFIG.NEAR_PLANE,\n CAMERA_CONFIG.FAR_PLANE,\n );\n this.setDefaultOrthographicFrustum();\n\n this.camera.position.set(\n CAMERA_CONFIG.DEFAULT_POSITION.x,\n CAMERA_CONFIG.DEFAULT_POSITION.y,\n CAMERA_CONFIG.DEFAULT_POSITION.z,\n );\n this.camera.lookAt(\n CAMERA_CONFIG.DEFAULT_LOOK_AT.x,\n CAMERA_CONFIG.DEFAULT_LOOK_AT.y,\n CAMERA_CONFIG.DEFAULT_LOOK_AT.z,\n );\n\n this.renderer = new THREE.WebGLRenderer({\n antialias: RENDERER_CONFIG.ANTIALIAS,\n });\n this.renderer.setPixelRatio(Math.min(2, typeof window !== \"undefined\" ? window.devicePixelRatio : 1));\n this.renderer.setSize(w, h);\n this.renderer.localClippingEnabled = RENDERER_CONFIG.LOCAL_CLIPPING_ENABLED;\n container.appendChild(this.renderer.domElement);\n\n this.controls = new OrbitControls(this.camera, this.renderer.domElement);\n this.controls.enableDamping = CONTROLS_CONFIG.ENABLE_DAMPING;\n this.controls.dampingFactor = CONTROLS_CONFIG.DAMPING_FACTOR;\n this.controls.target.set(\n CONTROLS_CONFIG.DEFAULT_TARGET.x,\n CONTROLS_CONFIG.DEFAULT_TARGET.y,\n CONTROLS_CONFIG.DEFAULT_TARGET.z,\n );\n this.controls.update();\n\n setupLights(this.scene);\n\n this.resizeObserver = new ResizeObserver(() => this.handleResize());\n this.resizeObserver.observe(container);\n\n this.tick();\n }\n\n handleResize(): void {\n const w = Math.max(1, this.container.clientWidth);\n const h = Math.max(1, this.container.clientHeight);\n this.renderer.setSize(w, h);\n if (this.rootObject) {\n this.fitOrthographicFrustumToObject();\n } else {\n this.setDefaultOrthographicFrustum();\n }\n }\n\n /** Frustum fisso (compat DentalGeom) prima del primo modello caricato. */\n private setDefaultOrthographicFrustum(): void {\n const w = Math.max(1, this.container.clientWidth);\n const h = Math.max(1, this.container.clientHeight);\n const aspect = w / h;\n const frustum = CAMERA_CONFIG.FRUSTUM_SIZE;\n this.camera.left = (-frustum * aspect) / 2;\n this.camera.right = (frustum * aspect) / 2;\n this.camera.top = frustum / 2;\n this.camera.bottom = -frustum / 2;\n this.camera.zoom = 1;\n this.camera.updateProjectionMatrix();\n }\n\n /**\n * Adatta left/right/top/bottom all’ingombro reale della mesh.\n * Prima il frustum ~100 unità con modello normalizzato ~2 unità → modello minuscolo.\n */\n private fitOrthographicFrustumToObject(): void {\n if (!this.rootObject) return;\n const box = new THREE.Box3().setFromObject(this.rootObject);\n if (box.isEmpty()) return;\n\n const sphere = new THREE.Sphere();\n box.getBoundingSphere(sphere);\n const r = Math.max(sphere.radius, 1e-6) * 1.35;\n\n const w = Math.max(1, this.container.clientWidth);\n const h = Math.max(1, this.container.clientHeight);\n const viewAspect = w / h;\n\n let halfW: number;\n let halfH: number;\n if (viewAspect >= 1) {\n halfH = r;\n halfW = r * viewAspect;\n } else {\n halfW = r;\n halfH = r / viewAspect;\n }\n\n this.camera.left = -halfW;\n this.camera.right = halfW;\n this.camera.top = halfH;\n this.camera.bottom = -halfH;\n this.camera.zoom = 1;\n this.camera.updateProjectionMatrix();\n }\n\n /** Sostituisce il modello nella scena (rimuove il precedente). */\n setRootObject(root: THREE.Object3D | null): void {\n if (this.rootObject) {\n this.scene.remove(this.rootObject);\n this.rootObject = null;\n }\n this.rootObject = root;\n if (root) this.scene.add(root);\n }\n\n centerCameraOnObject(): void {\n if (!this.rootObject) return;\n const box = new THREE.Box3().setFromObject(this.rootObject);\n if (box.isEmpty()) return;\n\n const center = new THREE.Vector3();\n box.getCenter(center);\n const size = new THREE.Vector3();\n box.getSize(size);\n const maxDim = Math.max(size.x, size.y, size.z, 1e-6);\n const distance = Math.abs(maxDim);\n const frontViewUp = VIEW_DIRECTIONS.FRONT.up;\n\n this.camera.position.set(center.x, center.y + distance, center.z);\n this.camera.up.set(frontViewUp.x, frontViewUp.y, frontViewUp.z);\n this.camera.lookAt(center);\n this.controls.target.copy(center);\n this.fitOrthographicFrustumToObject();\n this.controls.update();\n }\n\n setCameraView(view: ViewDirection): void {\n if (!this.rootObject) return;\n const box = new THREE.Box3().setFromObject(this.rootObject);\n if (box.isEmpty()) return;\n\n const center = new THREE.Vector3();\n box.getCenter(center);\n const size = new THREE.Vector3();\n box.getSize(size);\n const distance = Math.max(size.x, size.y, size.z, 1e-6);\n\n const cfg = VIEW_DIRECTIONS[view];\n if (!cfg) return;\n\n const targetPosition = this.calcViewPos(view, center, distance);\n const targetUp = new THREE.Vector3(cfg.up.x, cfg.up.y, cfg.up.z);\n\n this.animateCameraTransition(targetPosition, targetUp, center);\n }\n\n private calcViewPos(\n view: ViewDirection,\n center: THREE.Vector3,\n distance: number,\n ): THREE.Vector3 {\n switch (view) {\n case \"TOP\":\n return new THREE.Vector3(center.x, center.y, center.z + distance);\n case \"BOTTOM\":\n return new THREE.Vector3(center.x, center.y, center.z - distance);\n case \"FRONT\":\n return new THREE.Vector3(center.x, center.y + distance, center.z);\n case \"BACK\":\n return new THREE.Vector3(center.x, center.y - distance, center.z);\n case \"LEFT\":\n return new THREE.Vector3(center.x + distance, center.y, center.z);\n case \"RIGHT\":\n return new THREE.Vector3(center.x - distance, center.y, center.z);\n default:\n return center.clone();\n }\n }\n\n private animateCameraTransition(\n targetPosition: THREE.Vector3,\n targetUp: THREE.Vector3,\n targetCenter: THREE.Vector3,\n ): void {\n const startPosition = this.camera.position.clone();\n const startUp = this.camera.up.clone();\n const startTarget = this.controls.target.clone();\n const startTime = Date.now();\n const duration = ANIMATION_CONFIG.DURATION_MS;\n\n const animate = () => {\n const elapsed = Date.now() - startTime;\n const progress = Math.min(elapsed / duration, 1);\n const eased =\n progress < ANIMATION_CONFIG.EASING_THRESHOLD\n ? ANIMATION_CONFIG.EASING_POWER * progress * progress\n : 1 - Math.pow(-2 * progress + 2, 2) / 2;\n\n this.camera.position.lerpVectors(startPosition, targetPosition, eased);\n this.camera.up.lerpVectors(startUp, targetUp, eased);\n this.controls.target.lerpVectors(startTarget, targetCenter, eased);\n this.camera.lookAt(this.controls.target);\n this.controls.update();\n\n if (progress < 1) requestAnimationFrame(animate);\n };\n animate();\n }\n\n dispose(): void {\n if (this.animationHandle !== null) {\n cancelAnimationFrame(this.animationHandle);\n this.animationHandle = null;\n }\n this.resizeObserver?.disconnect();\n this.controls.dispose();\n this.setRootObject(null);\n this.renderer.dispose();\n if (this.renderer.domElement.parentNode) {\n this.renderer.domElement.parentNode.removeChild(this.renderer.domElement);\n }\n }\n}\n","/**\n * Costanti adattate da DentalGeom (MIT): camera ortografica, luci, viste.\n * @see https://github.com/Ellipsis1/DentalGeom\n */\n\nexport const MESH_COLORS = [\n 0xf5e6d3, 0x4ecdc4, 0xff6b6b, 0xffe66d, 0x95e1d3, 0xc7b8ea,\n] as const;\n\nexport const CAMERA_CONFIG = {\n FRUSTUM_SIZE: 100,\n NEAR_PLANE: 0.1,\n FAR_PLANE: 1000,\n DEFAULT_POSITION: { x: 20, y: 20, z: 20 },\n DEFAULT_UP: { x: 0, y: 0, z: -1 },\n DEFAULT_LOOK_AT: { x: 0, y: 0, z: -1 },\n} as const;\n\nexport const ANIMATION_CONFIG = {\n DURATION_MS: 1000,\n EASING_THRESHOLD: 0.5,\n EASING_POWER: 2,\n} as const;\n\nexport const CONTROLS_CONFIG = {\n ENABLE_DAMPING: true,\n DAMPING_FACTOR: 0.05,\n DEFAULT_TARGET: { x: 0, y: 0, z: 0 },\n} as const;\n\nexport const LIGHTING_CONFIG = {\n AMBIENT: { COLOR: 0xffffff, INTENSITY: 0.4 },\n KEY_LIGHT: {\n COLOR: 0xffffff,\n INTENSITY: 1.2,\n POSITION: { x: 50, y: 100, z: 50 },\n },\n FILL_LIGHT: {\n COLOR: 0xffffff,\n INTENSITY: 0.6,\n POSITION: { x: -50, y: 50, z: -50 },\n },\n RIM_LIGHT: {\n COLOR: 0xffffff,\n INTENSITY: 0.7,\n POSITION: { x: 0, y: 50, z: -100 },\n },\n HEMISPHERE: {\n SKY_COLOR: 0xffffff,\n GROUND_COLOR: 0x444444,\n INTENSITY: 0.5,\n },\n} as const;\n\nexport const SCENE_CONFIG = {\n BACKGROUND_COLOR: 0x4a4a7a,\n} as const;\n\nexport const RENDERER_CONFIG = {\n ANTIALIAS: true,\n LOCAL_CLIPPING_ENABLED: true,\n} as const;\n\nexport const VIEW_DIRECTIONS = {\n TOP: { name: \"top\", up: { x: 0, y: 1, z: 0 } },\n BOTTOM: { name: \"bottom\", up: { x: 0, y: 1, z: 0 } },\n FRONT: { name: \"front\", up: { x: 0, y: 0, z: -1 } },\n BACK: { name: \"back\", up: { x: 0, y: 0, z: -1 } },\n LEFT: { name: \"left\", up: { x: 0, y: 0, z: -1 } },\n RIGHT: { name: \"right\", up: { x: 0, y: 0, z: -1 } },\n} as const;\n\nexport type ViewDirection = keyof typeof VIEW_DIRECTIONS;\n","/**\n * Segmentazione dimostrativa lato browser (NON MeshSegNet / non clinica).\n * MeshSegNet reale è PyTorch: usare servizio esterno + { segmentationBridge } nel viewer.\n */\nimport {\n Box3,\n BufferAttribute,\n BufferGeometry,\n Color,\n Mesh,\n MeshStandardMaterial,\n Object3D,\n Vector3,\n} from \"three\";\n\n/** ~15 etichette stile MeshSegNet (arcata + gengiva): bande lungo Y normalizzato. */\nexport function applyMockToothBandColors(geometry: BufferGeometry): void {\n const pos = geometry.getAttribute(\"position\");\n if (!pos) return;\n const n = pos.count;\n const colors = new Float32Array(n * 3);\n const tmp = new Vector3();\n const box = new Box3();\n for (let i = 0; i < n; i++) {\n tmp.fromBufferAttribute(pos, i);\n box.expandByPoint(tmp);\n }\n const size = new Vector3();\n box.getSize(size);\n const minY = box.min.y;\n\n for (let i = 0; i < n; i++) {\n const y = pos.getY(i);\n const t = size.y > 1e-9 ? (y - minY) / size.y : 0;\n const segment = Math.min(14, Math.floor(t * 15));\n const hue = (segment / 15) * 0.85;\n const c = new Color().setHSL(hue, 0.62, 0.52);\n colors[i * 3] = c.r;\n colors[i * 3 + 1] = c.g;\n colors[i * 3 + 2] = c.b;\n }\n geometry.setAttribute(\"color\", new BufferAttribute(colors, 3));\n const colAttr = geometry.getAttribute(\"color\");\n if (colAttr) colAttr.needsUpdate = true;\n}\n\n/** Abilita vertexColors su tutte le mesh del gruppo (dopo attributo color). */\nexport function enableVertexColorsOnObjectTree(root: Object3D): void {\n root.traverse((o) => {\n if (o instanceof Mesh && o.material) {\n const mat = o.material;\n if (Array.isArray(mat)) {\n for (const m of mat) {\n if (m instanceof MeshStandardMaterial) {\n m.vertexColors = true;\n m.needsUpdate = true;\n }\n }\n } else if (mat instanceof MeshStandardMaterial) {\n mat.vertexColors = true;\n mat.needsUpdate = true;\n }\n }\n });\n}\n","import { SmallBadge } from \"./StatusBadge\";\nimport {\n isMeshViewerFormat,\n MESH_VIEWER_LARGE_BYTES,\n} from \"../lib/meshFormats\";\n\nexport type MeshSelectable = {\n _id: string;\n originalName: string;\n format: string;\n role: string;\n sizeBytes: number;\n};\n\nexport function MeshFileSelector({\n files,\n selectedId,\n onSelect,\n}: {\n files: MeshSelectable[] | undefined;\n selectedId: string | null;\n onSelect: (file: MeshSelectable) => void;\n}) {\n const meshes = files?.filter((f) => isMeshViewerFormat(f.format)) ?? [];\n\n if (meshes.length === 0) {\n return (\n <p className=\"muted\" style={{ marginBottom: \"0.75rem\" }}>\n Nessuna mesh STL/PLY/OBJ in questa acquisizione. Carica file reali o\n usa il seed demo con geometrie mock.\n </p>\n );\n }\n\n return (\n <div className=\"mesh-selector\" style={{ marginBottom: \"0.85rem\" }}>\n <div className=\"muted\" style={{ marginBottom: \"0.45rem\", fontSize: \"0.85rem\" }}>\n Mesh disponibili ({meshes.length})\n </div>\n <div className=\"mesh-selector-list\">\n {meshes.map((f) => {\n const active = f._id === selectedId;\n const large = f.sizeBytes > MESH_VIEWER_LARGE_BYTES;\n return (\n <button\n key={f._id}\n type=\"button\"\n className={`mesh-selector-item ${active ? \"mesh-selector-item-active\" : \"\"}`}\n onClick={() => onSelect(f)}\n >\n <div style={{ fontWeight: 600 }}>{f.originalName}</div>\n <div className=\"btn-row\" style={{ marginTop: \"0.35rem\", gap: \"0.35rem\" }}>\n <SmallBadge variant=\"role\">{f.role}</SmallBadge>\n <SmallBadge variant=\"format\">{f.format}</SmallBadge>\n <span className=\"muted\" style={{ fontSize: \"0.75rem\" }}>\n {(f.sizeBytes / 1024).toFixed(0)} KB\n {large ? \" · grande\" : \"\"}\n </span>\n </div>\n </button>\n );\n })}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","useState","jsx","jsxs","map","useState","jsx","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","useState","BufferAttribute","Mesh","Box3","Color","Mesh","MeshStandardMaterial","Vector3","jsx","jsxs","useState","Mesh","BufferAttribute","jsx","jsxs","Fragment","jsx","jsxs","useState"]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@primocaredentgroup/dental-digital-intake-ui",
3
+ "version": "0.1.1",
4
+ "description": "Componenti React per dental-digital-intake (nessuna logica backend; bridge verso Convex host).",
5
+ "license": "Apache-2.0",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/primocaredentgroup/componente_zip.git",
9
+ "directory": "packages/ui"
10
+ },
11
+ "homepage": "https://github.com/primocaredentgroup/componente_zip#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/primocaredentgroup/componente_zip/issues"
14
+ },
15
+ "type": "module",
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "sideEffects": false,
20
+ "main": "./dist/index.js",
21
+ "module": "./dist/index.js",
22
+ "types": "./dist/index.d.ts",
23
+ "exports": {
24
+ ".": {
25
+ "types": "./dist/index.d.ts",
26
+ "import": "./dist/index.js"
27
+ },
28
+ "./styles/intake.css": "./src/styles/intake.css"
29
+ },
30
+ "files": ["dist", "src/styles"],
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "typecheck": "tsc --noEmit"
34
+ },
35
+ "dependencies": {
36
+ "@primocaredentgroup/dental-digital-intake-shared": "^0.1.1",
37
+ "three-stdlib": "^2.36.1"
38
+ },
39
+ "peerDependencies": {
40
+ "react": "^18.3.1 || ^19.0.0",
41
+ "react-dom": "^18.3.1 || ^19.0.0",
42
+ "three": ">=0.170.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "three": { "optional": false }
46
+ },
47
+ "devDependencies": {
48
+ "@types/react": "^19.2.14",
49
+ "@types/react-dom": "^19.2.3",
50
+ "@types/three": "^0.181.0",
51
+ "react": "^19.2.5",
52
+ "react-dom": "^19.2.5",
53
+ "three": "^0.184.0",
54
+ "tsup": "^8.5.1",
55
+ "typescript": "6.0.3"
56
+ }
57
+ }