import type { PatientSummary } from "../../api/types";
import { initials } from "../../flow";
import type { Pill, PillIcon } from "../../logic/pills";
import { cn, Icon, StatusPill, type IconName, type Tone } from "../kit";
const pillIcons: Record<PillIcon, IconName> = {
sent: "send-plane-fill",
ringing: "volume-up-line",
live: "mic-fill",
completed: "checkbox-circle-fill",
missed: "phone-fill",
later: "time-fill",
not_reached: "hourglass-fill",
expired: "hourglass-2-fill",
declined: "forbid-fill",
identity: "shield-cross-line",
ended_early: "pause-circle-fill",
cancelled: "close-circle-fill",
urgent: "alarm-warning-fill",
queued: "hourglass-line",
reading: "loader-4-line",
read: "file-text-fill",
failed: "error-warning-fill",
held_back: "forbid-line",
connected: "plug-fill",
paused: "pause-circle-fill",
stopped: "link-unlink",
clinic: "hospital-fill",
draft: "draft-fill",
};
/** A state pill from logic/pills.ts, drawn with the kit: its icon, its colour and its words. */
export function StatePill({ pill, size = "sm" }: { pill: Pill; size?: "sm" | "md" }) {
const outline = pill.tone === "red-outline";
return (
<StatusPill tone={outline ? "red" : (pill.tone as Tone)} outline={outline} icon={pillIcons[pill.icon]} size={size} title={pill.meaning || undefined}>
{pill.label}
</StatusPill>
);
}
/** PAT-2: what needs the clinician, as a pill; null when nothing does. */
export function attentionPill(p: PatientSummary): { tone: Tone; icon: IconName } | null {
if (p.attention.urgent) return { tone: "red", icon: "alarm-warning-fill" };
if (p.attention.unreadNotes) return { tone: "blue", icon: "file-text-fill" };
if (p.attention.newSinceLastCheck) return { tone: "amber", icon: "file-search-fill" };
return null;
}
export function PatientAvatar({ name, size = 32, className }: { name: string; size?: number; className?: string }) {
return (
<span
aria-hidden="true"
style={{ width: size, height: size, fontSize: size < 32 ? 11 : 12 }}
className={cn("inline-flex shrink-0 items-center justify-center rounded-full bg-quiet font-semibold text-body", className)}
>
{initials(name)}
</span>
);
}
/** A thin bar for doses taken of those due; the words beside it carry the numbers. */
export function DoseBar({ taken, expected, className }: { taken: number; expected: number; className?: string }) {
const share = expected > 0 ? Math.min(1, taken / expected) : 0;
return (
<span aria-hidden="true" className={cn("block h-1.5 w-full overflow-hidden rounded-full bg-quiet", className)}>
<span className="block h-full rounded-full bg-green-icon" style={{ width: `${Math.round(share * 100)}%` }} />
</span>
);
}