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 { Textarea } from "../../../components/ui/textarea.tsx"; import { Alert, AlertDescription } from "../../../components/ui/alert.tsx"; import { ReferralDirectorySearch, type ReferralTarget, } from "../../../components/ReferralDirectorySearch/ReferralDirectorySearch.tsx"; import { useReferralWorkbenchService } from "../../../services/ReferralWorkbenchService"; import { relayServerFailure } from "../../../utils/fetchFailureMessage"; import { openPdfInTab, useSendOutDiagnosticOrder, type SendMethod, type SentOut, } from "../../../hooks/useSendOutDiagnosticOrder.ts"; import { useLabConnections, type LabConnection } from "../../../hooks/useLabConnections.ts"; import SendMethodField, { reviewedPairing } from "./SendMethodField.tsx"; import "./SendOutDialog.css"; // Sending a test out to a laboratory the practice does not run. // // THE LABORATORY COMES FROM THE ADDRESS BOOK EVERY REFERRAL ALREADY USES, keyed on NPI. A send-out // laboratory is the same animal as a referral recipient -- an outside organization with a fax number // and a desk things go to -- and a second directory would duplicate the registry client, the // shared-and-private split and the fax number one coordinator learned on a phone call. // // THE ACCOUNT NUMBER IS WHAT MAKES THE PAPER WORK and it is refused when empty: it is what the // laboratory files and bills against, so a requisition without one comes straight back. interface Props { orderId?: string; test?: string; /** The order's code; electronic sending needs a reviewed pairing for it. */ testCode?: string; testCodeSystem?: string; patient?: string; orderedBy?: string; onClose: () => void; onSent: (sent: SentOut) => void; } const SendOutDialog = ({ orderId, test, testCode, testCodeSystem, patient, orderedBy, onClose, onSent }: Props) => { const { sendOut, requisition } = useSendOutDiagnosticOrder(); const { readReferralContact } = useReferralWorkbenchService(); const { connections, loading: labsLoading } = useLabConnections(); const ours = connections.filter((lab) => lab.active !== false && lab.npi); const [target, setTarget] = useState(); const [manual, setManual] = useState(false); const [ourLabId, setOurLabId] = useState(""); const [npi, setNpi] = useState(""); const [name, setName] = useState(""); const [accountNumber, setAccountNumber] = useState(""); const [theirOrderCode, setTheirOrderCode] = useState(""); const [note, setNote] = useState(""); const [fax, setFax] = useState(); const [method, setMethod] = useState("paper"); const [busy, setBusy] = useState(false); // Once sent it cannot be sent again from here, whether or not its requisition opened. const [sent, setSent] = useState(); const [error, setError] = useState(); useEffect(() => { setTarget(undefined); setManual(false); setNpi(""); setName(""); setAccountNumber(""); setNote(""); setFax(undefined); setMethod("paper"); setSent(undefined); setError(undefined); }, [orderId]); // Their order code follows the laboratory: one the practice set up brings its reviewed pairing for this test, // and any other laboratory starts empty, so one laboratory's code is never sent to the next. const chosenNpi = npi.trim(); const configured = ours.find((lab) => lab.npi === chosenNpi); const pairedCode = reviewedPairing(configured, { system: testCodeSystem, code: testCode })?.theirCode ?? ""; useEffect(() => { setTheirOrderCode(pairedCode); }, [orderId, chosenNpi, pairedCode]); // What one coordinator learned about reaching this laboratory, so the next one does not phone to // find out. Best effort: a registry that will not answer must not stop a specimen leaving. const choose = async (chosen: ReferralTarget) => { setTarget(chosen); setOurLabId(""); setNpi(chosen.organization.npi); setName(chosen.organization.name); try { const contact = await readReferralContact(chosen.organization.npi); setFax(contact?.shared?.fax ?? chosen.location?.fax); } catch { setFax(chosen.location?.fax); } }; // Most send-outs go to a laboratory the practice has set up, whose account number is already on file. const chooseOurs = async (lab: LabConnection) => { setTarget(undefined); setManual(true); setOurLabId(lab.id ?? lab.npi ?? ""); setNpi(lab.npi ?? ""); setName(lab.name ?? ""); setAccountNumber(lab.accountNumber ?? ""); if (!lab.npi) return; try { setFax((await readReferralContact(lab.npi))?.shared?.fax); } catch { setFax(undefined); } }; // labs.html opens on the practice's own laboratory, already chosen, with the form showing. const firstOurs = ours[0]; useEffect(() => { if (firstOurs && !target && !manual && !sent) void chooseOurs(firstOurs); // eslint-disable-next-line react-hooks/exhaustive-deps }, [firstOurs?.id, firstOurs?.npi, target, manual, sent]); if (!orderId) return null; // The page re-reads only once this closes: re-reading remounts the dialog, which would drop the outcome // and offer the same order for sending again. const close = () => { if (sent) onSent(sent); onClose(); }; const chosen = Boolean(target) || manual; const submittable = /^\d{10}$/.test(npi.trim()) && accountNumber.trim().length > 0; const submit = async () => { // Opened BEFORE the await, while the click's activation is still alive, or the blocker eats it. const tab = window.open("", "_blank"); if (tab) tab.opener = null; setBusy(true); setError(undefined); let outcome: SentOut | undefined; try { outcome = await sendOut(orderId, { npi: npi.trim(), display: name, accountNumber, theirOrderCode, note, method, }); } catch (err) { tab?.close(); console.error("Error sending the order out:", err); setError(relayServerFailure(err, "Could not send this out. Please try again.")); setBusy(false); return; } setSent(outcome ?? {}); try { openPdfInTab(tab, await requisition(orderId)); } catch (err) { tab?.close(); console.error("Sent out, but the requisition did not open:", err); setError("Sent out. The requisition could not be opened, so print it from the order."); } finally { setBusy(false); } }; return ( { if (!open && !busy) close(); }}> Prepare send-out {[patient, test ?? "This test"].filter(Boolean).join(" · ")} {orderedBy ? {"Ordered by " + orderedBy} : null} {error ? ( {error} ) : null} {sent ? (

{sent.akashic ? `Delivered to ${name || "the laboratory"} through Akashic. Awaiting their acceptance; acceptance does not mean the specimen was received.` : sent.transmission === "refused" || sent.transmission === "unconfirmed" ? `Saved, but the electronic send to ${name || "the laboratory"} was not confirmed. Retry it from the order, or send the requisition with the specimen.` : sent.transmitting ? `Queued for electronic delivery to ${name || "the laboratory"}. Delivery has not been confirmed, and delivery does not prove the laboratory accepted the order or received the specimen.` : `Requisition prepared for ${name || "the laboratory"}. Printing it does not confirm delivery; send it with the specimen.`}

) : chosen ? (
{ours.length ? ( <>
Use another laboratory / enter manually void choose(chosenTarget)} onEnterManually={() => setOurLabId("")} chooseLabel="Send to this laboratory" />
setName(e.target.value)} placeholder="Riverbend Reference Laboratory" />
setNpi(e.target.value)} placeholder="1548273901" />
setAccountNumber(e.target.value)} placeholder="GRF-88213" />
) : ( <>
setName(e.target.value)} placeholder="Riverbend Reference Laboratory" />
setNpi(e.target.value)} placeholder="1548273901" />
setAccountNumber(e.target.value)} placeholder="GRF-88213" />
)} {fax ?

Results come back by fax to {fax}

: null}
setTheirOrderCode(e.target.value)} placeholder="RB-4471" />