import { useMemo, useState } from "react"; import { AlertCircle, Loader2 } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../../../components/ui/dialog.tsx"; import { Alert, AlertDescription } from "../../../components/ui/alert.tsx"; import { Button } from "../../../components/ui/button.tsx"; import { Input } from "../../../components/ui/input.tsx"; import { Label } from "../../../components/ui/label.tsx"; import { Textarea } from "../../../components/ui/textarea.tsx"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../components/ui/select.tsx"; import { useDiagnosticPublicationOperation } from "../../../hooks/useDiagnosticPublicationOperation"; import { ActWithdrawn } from "./ActWithdrawn.tsx"; import { CRITICAL_FINDING_CHANNELS, useReleaseDiagnosticResult, type CriticalFindingChannel, } from "../../../hooks/useReleaseDiagnosticResult.ts"; import { useDiagnosticResult } from "../../../hooks/useDiagnosticResult.ts"; import { useDiagnosticCatalogue } from "../../../hooks/useDiagnosticCatalogue.ts"; import { measurementsFromCatalogue } from "./RecordDiagnosticResult/measurementsFromCatalogue.ts"; import "./ReleaseResultDialog.css"; import { controlRunLine, qualityControlNotice } from "../../../utils/qualityControlNotice"; // Reviewing and releasing one test. The entered values are read back first so nobody signs off a // value they have not seen, and nothing is releasable until they are. Release makes this test final // and touches no other test; a critical-finding call goes in the same act and must name somebody. interface Props { orderId?: string; test?: string; /** The test's code and system, which decide its catalogue components. */ testCode?: string; testCodeSystem?: string; patient?: string; /** Accession and when it was entered, as the row already says it. */ detail?: string; /** One test of a panel: releasing it leaves the others as they are. */ inPanel?: boolean; /** Where the other tests of the panel stand, each said as a whole clause. */ siblings?: string[]; /** A reader signing their own report: the act attributes it to them and sends it to the orderer. */ signing?: boolean; /** Who ordered it, named when signing says where the report goes. */ orderedBy?: string; /** A practice not on Akashic that read the study: the report is released in its name, not the signer's. */ readBy?: string; onClose: () => void; /** The state the server set, so the row can move without re-reading a lagging projection. */ onReleased: (state?: string, returned?: { outcome: string; version?: number; at?: string }) => void; /** The caller may no longer make this write: the dialog stays readable and closable, and cannot send. */ withdrawn?: boolean; /** Where the control records are, offered beside a control warning; the dialog closes on the way. */ onOpenControls?: () => void; } const ReleaseResultDialog = ({ orderId, test, testCode, testCodeSystem, patient, detail, inPanel, siblings, signing, orderedBy, readBy, onClose, onReleased, withdrawn, onOpenControls }: Props) => { const release = useReleaseDiagnosticResult(); const { result, error: readError, loading, loadMore } = useDiagnosticResult(orderId); const { orderables } = useDiagnosticCatalogue(); const defined = useMemo( () => measurementsFromCatalogue(test, "laboratory", orderables, testCode, testCodeSystem), [test, orderables, testCode, testCodeSystem], ); // A catalogue component with no value is unreported, and releasing does not make it otherwise. const unreported = result && !signing ? (defined ?? []).map((field) => field.name).filter((name) => !result.measurements.some((m) => m.name === name && m.value)) : []; const [telling, setTelling] = useState(false); const [told, setTold] = useState(""); const [how, setHow] = useState("telephone"); const [readBack, setReadBack] = useState(false); const [note, setNote] = useState(""); const operation = useDiagnosticPublicationOperation('release', orderId, patient, result, !withdrawn, release, (saved, closed) => { onReleased(saved.state, saved.returned); if (closed) onClose(); }); const { busy, notice: error } = operation; if (!orderId) return null; // Control runs are a laboratory instrument's; an imaging read has none to show. const qcNotice = result && !signing ? qualityControlNotice(result.qualityControl, test) : undefined; const qcRun = qcNotice ? controlRunLine(result?.qualityControl) : undefined; // Nothing is released unseen, and a call that names nobody is not a record of a call. const submittable = operation.available && !operation.pending && (!telling || told.trim().length > 0); const submit = async () => { await operation.run(telling ? { criticalFinding: { told: told.trim(), how, readBack, ...(note.trim() ? { note: note.trim() } : {}) } } : undefined); }; return ( { if (!open && !busy) onClose(); }}> {signing ? "Sign & release" : "Review & release"}
{`${patient ?? "Patient not named"} · ${test ?? "Test not named"}`} {detail ? {detail} : null}
{qcNotice ? (

{qcNotice}

{qcRun ?

{qcRun}

: null} {onOpenControls ? ( ) : null}
) : null} {result?.qualityControl?.outcome === "outside" ? (

{`Performed by ${result.qualityControl.performer ?? "another laboratory"}. This practice’s quality control does not apply to it.`}

) : null} {loading ? (

Reading the entered result…

) : null} {readError ? ( {readError} ) : null} {result ? (result.measurements.length ? ( {result.measurements.map((measurement, index) => ( ))}
MeasurementValueUnit
{measurement.name ?? "Not named"} {[measurement.value ?? "Not recorded", measurement.flag].filter(Boolean).join(" ")} {measurement.unit ?? ""}
) : (

No measurement was entered on this result.

)) : null} {unreported.length ? (

{`Not reported: ${unreported.join(", ")}. Releasing makes this result final without them.`}

) : null} {result?.findings ?

{result.findings}

: null} {result?.impression ?

Impression {result.impression}

: null} {inPanel || siblings?.length ? (

{`This action affects ${test ?? "this test"} only. ${siblings?.length ? `${siblings.join("; ")}.` : "The other tests retain their own state."}`}

) : null} {signing && readBy ? "Signing releases this report as read by " + readBy + " and sends it to " + (orderedBy ?? "the clinician who ordered it") + ". It goes onto " + (patient ?? "the patient") + "'s record at the same moment, and they can read it straight away. A signed report is never edited; an addendum goes beside it." : signing ? "Signing attributes this report to you and sends it to " + (orderedBy ?? "the clinician who ordered it") + ". It goes onto " + (patient ?? "the patient") + "'s record at the same moment, and they can read it straight away. A signed report is never edited; an addendum goes beside it." : "This makes the result final and available to the patient. It cannot be undone, and it does not mark it reviewed by the ordering clinician."} {/* Closed until somebody opens it: a form asked every time is answered by habit. */}
{ event.preventDefault(); if (!busy) setTelling(!telling); }}> Record critical-result communication {telling ? (
setTold(event.target.value)} />