import { useCallback, useEffect, useState } from "react"; import { AlertCircle, Loader2, Plus, ScanEye, Trash2 } 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 { EmptyState } from "../../../../components/ui/empty-state.tsx"; import { relayServerFailure } from "../../../../utils/fetchFailureMessage"; import { useImagingReadHandoff, type ImagingReader } from "../../../../hooks/useImagingReadHandoff.ts"; import "./DiagnosticsPage.css"; // The Akashic practices this one sends studies to be read. A reader is found by its NPI; removing one // switches the connection off on the server, so studies already sent keep their history. The list is // a search that lags a write, so each change is applied from what the write returned. const ImagingReaders = () => { const { listReaders, addReader, removeReader } = useImagingReadHandoff(); const [readers, setReaders] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(); const [adding, setAdding] = useState(false); const [npi, setNpi] = useState(""); const [saving, setSaving] = useState(false); const [addError, setAddError] = useState(); const [removing, setRemoving] = useState(); const reload = useCallback(async () => { setLoading(true); setError(undefined); try { setReaders(await listReaders()); } catch (failure) { setError(relayServerFailure(failure, "The reading practices could not be loaded.")); } finally { setLoading(false); } }, [listReaders]); useEffect(() => { void reload(); }, [reload]); const open = () => { setNpi(""); setAddError(undefined); setAdding(true); }; const submit = async () => { if (!/^\d{10}$/.test(npi.trim())) { setAddError("Enter the reading practice's ten-digit NPI."); return; } setSaving(true); setAddError(undefined); try { const added = await addReader(npi.trim()); setReaders((current) => [...current.filter((each) => each.readerId !== added.readerId), added]); setAdding(false); } catch (failure) { setAddError(relayServerFailure(failure, "That practice could not be added. Please try again.")); } finally { setSaving(false); } }; const remove = async (reader: ImagingReader) => { setRemoving(reader.readerId); setError(undefined); try { await removeReader(reader.readerId); setReaders((current) => current.filter((each) => each.readerId !== reader.readerId)); } catch (failure) { setError(relayServerFailure(failure, "That practice could not be removed. Please try again.")); } finally { setRemoving(undefined); } }; if (loading && readers.length === 0 && !error) { return (

Loading the reading practices…

); } return (
{error ? ( {error} ) : null}

Reading practices

A reading practice sees a study only when the patient has authorized it, and accepts or declines each one.

{readers.length === 0 ? ( ) : (
    {readers.map((reader) => (
  • {reader.reader ?? "Unnamed practice"}
  • ))}
)}
{adding ? ( { if (!next && !saving) setAdding(false); }}> Add a reading practice Another practice on Akashic that this practice sends studies to be read. {addError ? ( {addError} ) : null}
setNpi(e.target.value)} placeholder="1548273901" inputMode="numeric" />

Ten digits. The practice must be on Akashic with this NPI in its profile.

) : null}
); }; export default ImagingReaders;