import { useEffect, useState } from "react"; import { AlertCircle } from "lucide-react"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "../../../components/ui/dialog.tsx"; import { Button } from "../../../components/ui/button.tsx"; import { Input } from "../../../components/ui/input.tsx"; import { Label } from "../../../components/ui/label.tsx"; import { Alert, AlertDescription } from "../../../components/ui/alert.tsx"; import { relayServerFailure } from "../../../utils/fetchFailureMessage"; import { useAdmission } from "../../../hooks/useAdmission.ts"; import { ActWithdrawn } from "./ActWithdrawn.tsx"; import { ORDER_REFUSAL_REASONS, REFUSAL_NEXT_STEPS, useRecordOrderRefusal, } from "../../../hooks/useRecordOrderRefusal.ts"; import type { DiagnosticOrderQueueRow } from "../../../hooks/useDiagnosticOrderQueue.ts"; import { Identity } from "./QueueOrderDialogs.tsx"; import "./RecordRefusalDialog.css"; // WRITING DOWN THAT THE LABORATORY WOULD NOT TAKE THE ORDER. // // A DIFFERENT ACT FROM REFUSING A SAMPLE, and offering them together would be the mistake: a // refused sample means stick the patient again, a refused order means fix the order. The tube may // be perfectly good. // // THEIR OWN WORDS ARE ASKED FOR, and that field is the useful one. A practice ringing the // laboratory needs to quote what came back, and a tidied summary of a refusal is a different // refusal. It is optional because a telephone call does not always leave one. // // WHAT HAPPENS NEXT IS REQUIRED, because it is the only thing that decides whether anybody looks // at this again. "Ring them" is offered separately from "fix it" on purpose: a closed account // cannot be fixed from this screen, and leaving only resend or cancel makes somebody choose a lie. const RecordRefusalDialog = ({ row, onClose, onRecorded, withdrawn, }: { row?: DiagnosticOrderQueueRow; onClose: () => void; onRecorded: () => void; /** The caller may no longer make this write: the dialog stays readable and closable, and cannot send. */ withdrawn?: boolean; }) => { const { record } = useRecordOrderRefusal(); const admitted = useAdmission(!withdrawn); // Only a caller following a changing answer passes `withdrawn`; any other sends as it always has. const admission = withdrawn === undefined ? ([] as const) : ([admitted] as const); const [reasonCode, setReasonCode] = useState(""); const [nextStep, setNextStep] = useState(""); const [theirCode, setTheirCode] = useState(""); const [theirMessage, setTheirMessage] = useState(""); const [busy, setBusy] = useState(false); const [error, setError] = useState(); useEffect(() => { setReasonCode(""); setNextStep(""); setTheirCode(""); setTheirMessage(""); setError(undefined); }, [row]); if (!row?.orderId) return null; const submit = async () => { setBusy(true); setError(undefined); try { await record(row.orderId as string, { reasonCode, nextStep, theirCode: theirCode.trim() || undefined, theirMessage: theirMessage.trim() || undefined, }, ...admission); onRecorded(); onClose(); } catch (failure) { console.error("Error recording the laboratory refusal:", failure); setError(relayServerFailure(failure, "That could not be recorded. Please try again.")); } finally { setBusy(false); } }; return ( { if (!open && !busy) onClose(); }}> Laboratory refused this order This is about the order, not the sample — the specimen is not affected. {error && ( {error} )}
setTheirMessage(e.target.value)} />

Their words, not a summary. Whoever rings them will need to quote it.

setTheirCode(e.target.value)} />

Recording the next step does not itself resend or cancel the order.

{withdrawn ? : null}
); }; export default RecordRefusalDialog;