fix: update UI to 7-state display framework

- WorklistTable: consolidate 9 filter tabs to 8 matching 7-state labels
  (Docs Required, Escalate, Confirm Appt., Begin Outreach, Clear to Ship,
  New Patient, On Track) + add combined "escalate" filter key for
  RENEWAL_CRITICAL + VISIT_REQUIRED
- Sidebar: fix broken filter keys (REFILL_WINDOW/VISIT_DUE/OUT_OF_COVERAGE
  never matched any r.flag value) - replace with SUPPLY_LAPSED, escalate,
  RESUPPLY_READY; update labels to 7-state names
- App: rename Sidebar props to match new framework; update stat cards to
  Needs Attention / Outreach in Progress / Clear to Ship

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Kisa 2026-06-07 16:27:25 -04:00
parent e57f803f26
commit 77a1cdb2c0
3 changed files with 41 additions and 38 deletions

View file

@ -21,15 +21,16 @@ function AppInner() {
const [importLabel, setImportLabel] = useState("No data imported"); const [importLabel, setImportLabel] = useState("No data imported");
const csvImportRef = useRef(null); const csvImportRef = useRef(null);
// New flag names from backend v0.2
const supplyLapsed = records.filter((r) => r.flag === "SUPPLY_LAPSED").length; const supplyLapsed = records.filter((r) => r.flag === "SUPPLY_LAPSED").length;
const visitRequired = records.filter((r) => r.flag === "VISIT_REQUIRED").length; const visitRequired = records.filter((r) => r.flag === "VISIT_REQUIRED").length;
const renewalCritical = records.filter((r) => r.flag === "RENEWAL_CRITICAL").length; const renewalCritical = records.filter((r) => r.flag === "RENEWAL_CRITICAL").length;
const renewalElevated = records.filter((r) => r.flag === "RENEWAL_ELEVATED").length; const renewalElevated = records.filter((r) => r.flag === "RENEWAL_ELEVATED").length;
const renewalSoon = records.filter((r) => r.flag === "RENEWAL_SOON").length;
const transferPending = records.filter((r) => r.flag === "TRANSFER_PENDING").length; const transferPending = records.filter((r) => r.flag === "TRANSFER_PENDING").length;
const refill = records.filter((r) => r.flag === "RESUPPLY_READY").length; const refill = records.filter((r) => r.flag === "RESUPPLY_READY").length;
const okCount = records.filter((r) => r.flag === "ACTIVE").length; const okCount = records.filter((r) => r.flag === "ACTIVE").length;
const urgent = supplyLapsed + visitRequired + renewalCritical + renewalElevated + transferPending; const escalateCount = visitRequired + renewalCritical;
const outreachCount = renewalSoon + renewalElevated;
const handleResults = useCallback(async (file) => { const handleResults = useCallback(async (file) => {
const label = new Date().toLocaleDateString("en-US", { const label = new Date().toLocaleDateString("en-US", {
@ -71,9 +72,9 @@ function AppInner() {
<div className="flex w-full min-h-screen bg-[var(--bg-page)] text-[var(--text-primary)] transition-colors"> <div className="flex w-full min-h-screen bg-[var(--bg-page)] text-[var(--text-primary)] transition-colors">
{/* Sidebar */} {/* Sidebar */}
<Sidebar <Sidebar
oocCount={supplyLapsed} supplyLapsedCount={supplyLapsed}
visitDueCount={visitRequired + renewalCritical + renewalElevated} escalateCount={escalateCount}
refillCount={refill} clearToShipCount={refill}
activeFilter={activeFilter} activeFilter={activeFilter}
onFilterChange={setActiveFilter} onFilterChange={setActiveFilter}
onImportClick={() => csvImportRef.current?.trigger()} onImportClick={() => csvImportRef.current?.trigger()}
@ -111,19 +112,19 @@ function AppInner() {
<div className="grid grid-cols-3 gap-4 mb-6"> <div className="grid grid-cols-3 gap-4 mb-6">
<StatCard <StatCard
priority priority
label="Prescriber Action" label="Needs Attention"
value={urgent} value={supplyLapsed + escalateCount + transferPending}
sub={`${supplyLapsed} supply lapsed · ${visitRequired + renewalCritical + renewalElevated} renewal/visit action · ${transferPending} transfer`} sub={`${supplyLapsed} docs required · ${escalateCount} escalate · ${transferPending} new patient`}
/> />
<StatCard <StatCard
label="⚠ Resupply Ready" label="Outreach in Progress"
value={outreachCount}
sub={`${renewalElevated} confirm appt. · ${renewalSoon} begin outreach`}
/>
<StatCard
label="Clear to Ship"
value={refill} value={refill}
sub="patients within resupply window — initiate now" sub={`${refill} patients in resupply window · ${okCount} on track`}
/>
<StatCard
label="✓ Active"
value={okCount}
sub="patients with supply on track — no action needed"
/> />
</div> </div>

View file

@ -1,7 +1,7 @@
export default function Sidebar({ export default function Sidebar({
oocCount, supplyLapsedCount,
visitDueCount, escalateCount,
refillCount, clearToShipCount,
activeFilter, activeFilter,
onFilterChange, onFilterChange,
onImportClick, onImportClick,
@ -14,23 +14,24 @@ export default function Sidebar({
badge: null, badge: null,
}, },
{ {
label: "Resupply Ready", label: "Docs Required",
key: "REFILL_WINDOW", key: "SUPPLY_LAPSED",
icon: "", icon: "!",
badge: refillCount, badge: supplyLapsedCount,
badgeWarn: true, badgeWarn: true,
}, },
{ {
label: "Renewal Due", label: "Escalate",
key: "VISIT_DUE", key: "escalate",
icon: "⚡", icon: "!",
badge: visitDueCount, badge: escalateCount,
badgeWarn: true,
}, },
{ {
label: "Supply Lapsed", label: "Clear to Ship",
key: "OUT_OF_COVERAGE", key: "RESUPPLY_READY",
icon: "", icon: "",
badge: oocCount, badge: clearToShipCount,
}, },
]; ];

View file

@ -24,14 +24,13 @@ function scoreClass(priority) {
const FILTERS = [ const FILTERS = [
{ key: "all", label: "All" }, { key: "all", label: "All" },
{ key: "SUPPLY_LAPSED", label: "Supply Lapsed" }, { key: "SUPPLY_LAPSED", label: "Docs Required" },
{ key: "VISIT_REQUIRED", label: "Visit Required" }, { key: "escalate", label: "Escalate" },
{ key: "RENEWAL_CRITICAL", label: "Renewal Critical" }, { key: "RENEWAL_ELEVATED", label: "Confirm Appt." },
{ key: "RENEWAL_ELEVATED", label: "Renewal Elevated" }, { key: "RENEWAL_SOON", label: "Begin Outreach" },
{ key: "RENEWAL_SOON", label: "Renewal Due" }, { key: "RESUPPLY_READY", label: "Clear to Ship" },
{ key: "RESUPPLY_READY", label: "Resupply Ready" }, { key: "TRANSFER_PENDING", label: "New Patient" },
{ key: "ACTIVE", label: "Active" }, { key: "ACTIVE", label: "On Track" },
{ key: "TRANSFER_PENDING", label: "Transfer" },
]; ];
const HIGH_PRIORITY_FLAGS = ["SUPPLY_LAPSED", "VISIT_REQUIRED", "RENEWAL_CRITICAL", "TRANSFER_PENDING"]; const HIGH_PRIORITY_FLAGS = ["SUPPLY_LAPSED", "VISIT_REQUIRED", "RENEWAL_CRITICAL", "TRANSFER_PENDING"];
@ -55,6 +54,8 @@ export default function WorklistTable({ records, activeFilter, onFilterChange })
const filtered = const filtered =
activeFilter === "all" activeFilter === "all"
? localRecords ? localRecords
: activeFilter === "escalate"
? localRecords.filter((r) => r.flag === "RENEWAL_CRITICAL" || r.flag === "VISIT_REQUIRED")
: localRecords.filter((r) => r.flag === activeFilter); : localRecords.filter((r) => r.flag === activeFilter);
const todayStr = new Date().toLocaleDateString("en-US", { const todayStr = new Date().toLocaleDateString("en-US", {