import { useEffect } from "react";
import { clinicianApi } from "../../api/client";
import { tabNames, visibleTabs } from "../../logic/patients";
import { CheckTab } from "../check/CheckTab";
import { CheckInsTab } from "../checkin/CheckInsTab";
import { LivePanel } from "../checkin/LivePanel";
import { PlanEditor } from "../checkin/PlanEditor";
import { cn, EmptyState, Icon, TipProvider } from "../kit";
import { Link } from "../router";
import { useClinician } from "../session";
import Shell, { type Crumb } from "../Shell";
import { ErrorNote, Spinner, useLoad } from "../ui";
import { fromSlug } from "./links";
import { Overview } from "./Overview";
import { PatientHeader, StatRow } from "./PatientHeader";
import { PatientRail } from "./PatientRail";
import { PatientTabs } from "./PatientTabs";
import { RecordsTab } from "./Records";
import { SharedTab } from "./Shared";
/**
* PAT-3: the patient's name and state, the stat row, the sections as tabs, and a rail with
* Details and Activity. Writing a check-in plan or reading a call takes the full width.
*/
export default function PatientPage({ id, segments }: { id: string; segments: string[] }) {
const { clinic } = useClinician();
const patient = useLoad(() => clinicianApi.patient(id), [id]);
useEffect(() => {
const t = setInterval(() => patient.reload(true), 30_000);
return () => clearInterval(t);
}, [patient.reload]);
const p = patient.data;
const lastCheckId = p?.lastCheckId ?? null;
const lastCheck = useLoad(() => (lastCheckId ? clinicianApi.check(lastCheckId) : Promise.resolve(null)), [lastCheckId]);
// The old /activity address opens the rail on Activity.
const asked = fromSlug(segments[0]);
const railOnActivity = asked === "activity";
const tab = railOnActivity ? "overview" : asked;
const tabs = p ? visibleTabs(p) : [];
const sub = segments[1];
const focused = tab === "check_ins" && !!sub;
const crumbs: Crumb[] = [{ label: "Patients", to: "/app/patients" }, { label: p?.name ?? "Patient", to: `/app/patients/${id}` }];
if (tab !== "overview") crumbs.push({ label: sub === "new" ? "Ask Yasmar to check in" : sub ? "Check-in call" : tabNames[tab] });
return (
<Shell crumbs={crumbs} active="patients">
<TipProvider>
{!p && patient.loading && <Spinner label="Opening the patient" />}
<ErrorNote error={patient.error} onRetry={() => patient.reload()} />
{p && (
<div className="@container/pd">
<div className={cn("grid grid-cols-1 gap-8 pb-8", !focused && "@min-[960px]/pd:grid-cols-[minmax(0,1fr)_320px] @min-[960px]/pd:gap-0")}>
<div className="flex min-w-0 flex-col gap-[22px]">
<BackLink />
<PatientHeader patient={p} clinicName={clinic.name} />
{!focused && <StatRow patient={p} check={lastCheck.data} checkLoading={lastCheck.loading} />}
<PatientTabs patient={p} tabs={tabs} active={tab} />
<div className="min-w-0">
{!tabs.includes(tab) ? (
<EmptyState title="This section is not shared with you." />
) : tab === "overview" ? (
<Overview key={p.id} patient={p} lastCheck={lastCheck.data} lastCheckLoading={lastCheck.loading} />
) : tab === "shared" ? (
<SharedTab key={p.id} patient={p} />
) : tab === "check" ? (
<CheckTab key={p.id} patient={p} onChanged={() => patient.reload(true)} />
) : tab === "check_ins" ? (
sub === "new" ? (
<PlanEditor key={p.id} patient={p} />
) : sub ? (
<LivePanel key={`${p.id}-${sub}`} patient={p} checkInId={sub} onChanged={() => patient.reload(true)} />
) : (
<CheckInsTab key={p.id} patient={p} />
)
) : (
<RecordsTab key={p.id} patient={p} />
)}
</div>
</div>
{!focused && <PatientRail key={`${p.id}-${railOnActivity}`} patient={p} initial={railOnActivity ? "activity" : "details"} />}
</div>
</div>
)}
{!p && !patient.loading && !patient.error && (
<EmptyState
title="Patient not found."
action={
<Link to="/app/patients" className="text-[13.5px] font-medium text-ink underline decoration-line underline-offset-4 hover:decoration-ink">
Back to patients
</Link>
}
/>
)}
</TipProvider>
</Shell>
);
}
function BackLink() {
return (
<Link
to="/app/patients"
className="inline-flex items-center gap-1.5 self-start rounded-md text-[13.5px] text-cell no-underline transition-colors outline-none hover:text-ink focus-visible:shadow-[0_0_0_2px_var(--color-brand)]"
>
<Icon name="arrow-left-line" size={15} />
Back<span className="sr-only"> to patients</span>
</Link>
);
}