import React, { useMemo, useState } from 'react'; import type { Encounter, Patient } from 'fhir/r4'; import { MapPin } from 'lucide-react'; import PresenceDot from '../../../components/PresenceDot/PresenceDot'; import { usePatientSnapshot } from '../../../hooks/usePatientSnapshot'; import { SnapshotChart } from '../../../components/PatientSnapshot/SnapshotChart'; import { availableActions, type ActionDescriptor, type QueueItem } from './encounterLifecycle'; import { useEncounterActions } from './useEncounterActions'; import { VitalsForm } from './VitalsForm'; import { RoomPickerDialog } from './RoomPickerDialog'; import { BTN_CLASS, ageSex, ModalityBadge, VisitStatus } from './queueItemDisplay'; interface Props { item: QueueItem; patient?: Patient; onChanged?: () => void; onEnter: (encounter: Encounter, item: QueueItem) => void; rooming?: boolean; } /** * Support-tier equivalent of `EncounterFocusPanel`: a prep view (reason + chart snapshot + a Vitals * slot) with a support action bar (Room patient room picker, Mark ready, Open chart). Support staff * never document the encounter itself - the body is read-only prep, not a documentation workspace. */ export const SupportFocusPanel: React.FC = ({ item, patient: supplied, onChanged, onEnter, rooming: roomsInUse = true }) => { // Only the patient this row names. Until it has loaded, nothing of another patient is shown or captured here. const patient = supplied?.id === item.patientId ? supplied : undefined; const actions = useEncounterActions({ onChanged, onEnter }); // Bump on a vitals save so `asOf` advances and the chart snapshot re-fetches - the just-entered // vitals then show in place, without waiting for the panel to be reopened. const [vitalsTick, setVitalsTick] = useState(0); const asOf = useMemo(() => new Date().toISOString(), [item.patientId, vitalsTick]); const { results } = usePatientSnapshot(patient, patient ? asOf : undefined); const [roomPickerOpen, setRoomPickerOpen] = useState(false); const run = (a: ActionDescriptor) => { switch (a.kind) { case 'room': setRoomPickerOpen(true); return; case 'mark-ready': return actions.markReady(item); case 'open-chart': case 'preview': return actions.openChart(item); } }; const selectRoom = (room: { id: string; name?: string }) => { actions.roomPatient(item, room); setRoomPickerOpen(false); }; const busy = actions.busyKey === item.key; return (
{/* header */}
{item.room && Room {item.room}}

{item.patientName ?? patient?.name?.[0]?.text ?? 'Unknown patient'}

{ageSex(patient)}

Reason {item.reason ?? 'No reason given'}

{/* action bar */}
{availableActions(item.status, 'support', Boolean(item.room), roomsInUse).map((a) => ( ))}
{/* body — read-only prep, not a documentation workspace */}

Prep

{/* 🏷️ Card 644 — level 4: the "Prep" heading above is an h3. */}

Vitals

{patient ? ( // One form per selected row: another row - even another appointment for the same patient - starts empty. { setVitalsTick((t) => t + 1); onChanged?.(); }} /> ) : (
Vitals open once this patient's record has loaded.
)}
{/* room picker */}
); }; export default SupportFocusPanel;