import { useMemo } from "react"; import { useNavigate } from "react-router-dom"; import type { MedicationRequest, MedicationStatement } from "fhir/r4"; import { ChevronRight, Pill, Plus } from "lucide-react"; import { useFhirMedicationRequests, useFhirMedicationStatements } from "../../../../hooks"; import { EmptyState } from "../../../../components/ui/empty-state"; import { OrgBadge } from "../../../../components/ui/org-badge"; import { Skeleton } from "../../../../components/ui/skeleton"; import { relayServerFailure } from "../../../../utils/fetchFailureMessage"; import { usePracticeToday } from "../../../../hooks/usePracticeToday"; import { buildMedicationLists, currentSummary, fillByLine, type MedicationRow } from "./medicationRows"; import { RecordPracticeNote, recordPracticeId, useRecordPracticeView, useRetireOnPracticeChange } from "../../../../contexts/RecordPracticeContext"; import "./MedicationsOverview.css"; type MedicationRecord = MedicationRequest | MedicationStatement; const isRequest = (record: MedicationRecord): record is MedicationRequest => record.resourceType === "MedicationRequest"; const isStatement = (record: MedicationRecord): record is MedicationStatement => record.resourceType === "MedicationStatement"; // A dose given in the room is not listed here: it belongs to the visit that gave it, and the page says so. /** The fill deadline, said only once the prescribing practice's calendar is known. */ const FillByLine = ({ row }: { row: MedicationRow }) => { const practice = usePracticeToday(row.validUntil ? row.organizationId : undefined); if (practice.state !== "ready") return null; const line = fillByLine(row, practice.today, practice.zone); return line ? {line} : null; }; const MedicationsOverview = () => { const navigate = useNavigate(); const requests = useFhirMedicationRequests(); const statements = useFhirMedicationStatements(); // A read that has not answered is still loading, never an empty list. const loading = requests.loading || statements.loading || !requests.answered || !statements.answered; const failure = requests.error || statements.error; // A 403 cannot be retried into a list, so it is named rather than offered again. const refused = Boolean((requests.error && requests.refused) || (statements.error && statements.refused)); // The record's practice context: its own medicines under a named practice; the empty state speaks for the whole record. // Read from the records themselves, since a statement's row does not carry the practice it was written at. const records = useMemo( () => [...requests.medicationRequestsList, ...statements.medicationStatementsList], [requests.medicationRequestsList, statements.medicationStatementsList], ); const practiceView = useRecordPracticeView(records, recordPracticeId); // A medicine opens on its own page, so nothing on this list is left open to close. useRetireOnPracticeChange(() => undefined); const wholeRecord = buildMedicationLists( requests.medicationRequestsList, statements.medicationStatementsList, ); const lists = buildMedicationLists( practiceView.shown.filter(isRequest), practiceView.shown.filter(isStatement), ); const rowButton = (row: MedicationRow) => { const className = `ak-card ak-card--edge ak-meds__row${row.own ? " ak-meds__row--own" : ""}`; const body = ( {row.name} {row.schedule && {row.schedule}} {/* The practice travels with whoever is named (Spencer, 2026-08-29), so a medicine the patient added names none - there is no clinician on it to travel with. */} {row.organization && !row.own && ( {row.organization} )} {row.provenance} ); // A record with no id is still shown by its name; it has no page to open. return row.path ? ( ) : (
{body}
); }; // Nothing current is not nothing recorded: other and past records may still be on the list below. const anyRecorded = wholeRecord.current.length + wholeRecord.other.length + wholeRecord.past.length > 0; const addButton = ( ); if (failure) { return ( ); } return (

Current prescriptions and reported use

{currentSummary(lists)}
{/* The fetch polls, so `loading` outlives the first result. Only the list waits - the headings and the right-hand column are the same whether anything has arrived. */} {lists.current.length > 0 ? ( lists.current.map(rowButton) ) : loading ? (
) : wholeRecord.current.length === 0 && ( )} {addButton}
{lists.other.length > 0 && ( <>

Other medication records

{lists.other.map(rowButton)}
)} {lists.past.length > 0 && ( <>

Past medication records

{lists.past.map(rowButton)}
)}

What is not on this page

Medicines given to you at a visit An injection, a drip, a dose in the room
Vaccinations Including what is due

If you stop taking a medication

Update the medication record so your healthcare providers are aware.
); }; export default MedicationsOverview;