- Add _build_reason() to backend — per-patient reason strings with specific day counts (e.g. "Supply lapsed 70 days ago. Prescriber contact required.") - Add reason field to RecordOut model and backend /api/export CSV - Fix export column headers: Coverage End Date → Resupply End Date, Days Until Coverage End → Days Until Resupply End - Pass reason through apiRecordToLocal in frontend api.js - Display reason as muted sub-line under status badge in WorklistTable - Add reason column to client-side CSVExport - Add signal-ui React source to repo (was untracked) - CLAUDE.md: add Billing and CMS integrations to Phase 2 deferred table - research: restore Section 14 stat verification (May 23 recovery) Deployed to Railway production — health check confirmed live. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
132 lines
No EOL
4.6 KiB
JavaScript
132 lines
No EOL
4.6 KiB
JavaScript
export default function Sidebar({
|
|
oocCount,
|
|
visitDueCount,
|
|
refillCount,
|
|
activeFilter,
|
|
onFilterChange,
|
|
onImportClick,
|
|
}) {
|
|
const navItems = [
|
|
{
|
|
label: "All Patients",
|
|
key: "all",
|
|
icon: "≡",
|
|
badge: null,
|
|
},
|
|
{
|
|
label: "Resupply Ready",
|
|
key: "REFILL_WINDOW",
|
|
icon: "⚠",
|
|
badge: refillCount,
|
|
badgeWarn: true,
|
|
},
|
|
{
|
|
label: "Renewal Due",
|
|
key: "VISIT_DUE",
|
|
icon: "⚡",
|
|
badge: visitDueCount,
|
|
},
|
|
{
|
|
label: "Supply Lapsed",
|
|
key: "OUT_OF_COVERAGE",
|
|
icon: "✕",
|
|
badge: oocCount,
|
|
},
|
|
];
|
|
|
|
return (
|
|
<aside className="w-[240px] bg-teal-900 border-r border-teal-700 flex flex-col shrink-0 fixed top-0 left-0 bottom-0 z-20">
|
|
{/* Header */}
|
|
<div className="px-5 pt-[22px] pb-[18px] border-b border-[rgba(15,94,94,0.5)]">
|
|
<div className="flex items-center gap-[10px] mb-1">
|
|
<div className="w-[33px] h-[33px] bg-gradient-to-br from-[#1A8A8A] to-[#147A7A] rounded-lg flex items-center justify-center font-heading font-bold text-[16px] text-warm-white shrink-0 shadow-[0_2px_8px_rgba(20,122,122,0.35)]">
|
|
S
|
|
</div>
|
|
<span className="font-heading font-bold text-[17px] text-warm-white tracking-[-0.01em]">
|
|
Signal
|
|
</span>
|
|
</div>
|
|
<div className="text-[11px] text-teal-300 ml-[43px] tracking-[0.01em]">
|
|
by STTIL Solutions
|
|
</div>
|
|
</div>
|
|
|
|
{/* Nav */}
|
|
<nav className="py-[10px] flex-1 overflow-y-auto">
|
|
<div className="text-[10px] font-medium tracking-[0.09em] uppercase text-[#426060] px-5 pt-[10px] pb-1">
|
|
Worklist
|
|
</div>
|
|
{navItems.map((item) => (
|
|
<a
|
|
key={item.key}
|
|
href="#"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
onFilterChange(item.key);
|
|
}}
|
|
className={`flex items-center gap-[10px] px-5 py-[9px] text-[13.5px] no-underline transition-all cursor-pointer border-l-[3px] ${
|
|
activeFilter === item.key
|
|
? "text-warm-white font-medium border-l-[var(--accent)] bg-[rgba(10,68,68,0.55)]"
|
|
: "text-[#7A9E9E] border-l-transparent hover:text-teal-400 hover:bg-[rgba(46,163,163,0.07)]"
|
|
}`}
|
|
>
|
|
<span className="w-[18px] text-center text-[14px] shrink-0">
|
|
{item.icon}
|
|
</span>
|
|
{item.label}
|
|
{item.badge != null && item.badge > 0 && (
|
|
<span
|
|
className={`ml-auto text-[10px] font-semibold px-[7px] py-[1px] rounded-[20px] font-mono ${
|
|
item.badgeWarn
|
|
? "bg-[rgba(217,123,53,0.22)] text-[#E49655]"
|
|
: "bg-[rgba(200,48,48,0.22)] text-[#FF8080]"
|
|
}`}
|
|
>
|
|
{item.badge}
|
|
</span>
|
|
)}
|
|
</a>
|
|
))}
|
|
<div className="text-[10px] font-medium tracking-[0.09em] uppercase text-[#426060] px-5 pt-4 pb-1">
|
|
System
|
|
</div>
|
|
<a
|
|
href="#"
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
onImportClick();
|
|
}}
|
|
className="flex items-center gap-[10px] px-5 py-[9px] text-[13.5px] text-[#7A9E9E] no-underline transition-all cursor-pointer border-l-[3px] border-l-transparent hover:text-teal-400 hover:bg-[rgba(46,163,163,0.07)]"
|
|
>
|
|
<span className="w-[18px] text-center text-[14px] shrink-0">↑</span>
|
|
Import CSV
|
|
</a>
|
|
<a
|
|
href="#"
|
|
onClick={(e) => e.preventDefault()}
|
|
className="flex items-center gap-[10px] px-5 py-[9px] text-[13.5px] text-[#7A9E9E] no-underline transition-all cursor-pointer border-l-[3px] border-l-transparent hover:text-teal-400 hover:bg-[rgba(46,163,163,0.07)]"
|
|
>
|
|
<span className="w-[18px] text-center text-[14px] shrink-0">⚙</span>
|
|
Settings
|
|
</a>
|
|
</nav>
|
|
|
|
{/* Footer */}
|
|
<div className="px-5 py-[14px] border-t border-[rgba(15,94,94,0.5)]">
|
|
<div className="flex items-center gap-[10px]">
|
|
<div className="w-[30px] h-[30px] bg-[rgba(46,163,163,0.18)] border border-[rgba(46,163,163,0.3)] rounded-full flex items-center justify-center text-[11px] text-teal-400 font-semibold shrink-0">
|
|
DS
|
|
</div>
|
|
<div>
|
|
<div className="text-xs font-medium text-warm-white">
|
|
Demo Supplier
|
|
</div>
|
|
<div className="text-[10px] text-teal-300 mt-[1px]">
|
|
Billing Staff
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</aside>
|
|
);
|
|
} |