fix(header): relocate staff role switcher to sub-tab ribbon and streamline Tier 1 so portal buttons have full clearance
This commit is contained in:
+83
-80
@@ -612,11 +612,11 @@ export default function Home() {
|
||||
{/* Top Hospital Command Header */}
|
||||
<header className="sticky top-0 z-40 bg-white border-b border-slate-200/90 shadow-2xs">
|
||||
{/* Tier 1: System Command & Tenant Navigation */}
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2.5">
|
||||
<div className="flex items-center justify-between gap-3 flex-wrap lg:flex-nowrap">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
{/* Left Cluster: Hospital Brand & Clinic Identity */}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="flex items-center gap-2.5 shrink-0">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="w-8 h-8 rounded-lg bg-sky-700 flex items-center justify-center font-black text-xs text-white shadow-xs">
|
||||
+M
|
||||
</span>
|
||||
@@ -627,21 +627,21 @@ export default function Home() {
|
||||
v2.5
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[10px] text-slate-400 font-mono flex items-center gap-1">
|
||||
<div className="text-[10px] text-slate-400 font-mono hidden 2xl:flex items-center gap-1">
|
||||
<Globe className="w-2.5 h-2.5 text-sky-700" />
|
||||
https://{activeTenant.domain}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="h-5 w-[1px] bg-slate-200 hidden sm:block" />
|
||||
<div className="h-4 w-[1px] bg-slate-200 hidden sm:block" />
|
||||
|
||||
{/* Clinic Dropdown Selector */}
|
||||
<div className="relative">
|
||||
<select
|
||||
value={activeTenantId}
|
||||
onChange={(e) => handleSwitchTenant(e.target.value)}
|
||||
className="appearance-none bg-slate-50 hover:bg-slate-100 border border-slate-300 text-slate-800 text-xs font-bold rounded-lg pl-2.5 pr-7 py-1.5 cursor-pointer focus:outline-none focus:border-sky-500 transition shadow-2xs max-w-[190px] sm:max-w-[240px] truncate"
|
||||
className="appearance-none bg-slate-50 hover:bg-slate-100 border border-slate-300 text-slate-800 text-xs font-bold rounded-lg pl-2 pr-6 py-1.5 cursor-pointer focus:outline-none focus:border-sky-500 transition shadow-2xs max-w-[150px] sm:max-w-[190px] md:max-w-[210px] truncate"
|
||||
title="Switch Clinic Location / Practice"
|
||||
>
|
||||
{tenants.map((t) => (
|
||||
@@ -650,33 +650,33 @@ export default function Home() {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="w-3.5 h-3.5 text-slate-500 absolute right-2 top-1/2 -translate-y-1/2 pointer-events-none" />
|
||||
<ChevronDown className="w-3.5 h-3.5 text-slate-500 absolute right-1.5 top-1/2 -translate-y-1/2 pointer-events-none" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Center: Command Palette / Search Bar (Responsive) */}
|
||||
<div className="flex-1 max-w-xs xl:max-w-sm hidden md:block">
|
||||
{/* Center: Command Palette / Search Bar (Responsive, doesn't crowd out right tools) */}
|
||||
<div className="hidden md:block flex-1 max-w-[200px] lg:max-w-[240px] xl:max-w-xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsCommandPaletteOpen(true);
|
||||
}}
|
||||
className="w-full flex items-center justify-between px-3 py-1.5 bg-slate-50 hover:bg-slate-100 border border-slate-200 rounded-lg text-slate-500 text-xs transition shadow-2xs group"
|
||||
className="w-full flex items-center justify-between px-2.5 py-1.5 bg-slate-50 hover:bg-slate-100 border border-slate-200 rounded-lg text-slate-500 text-xs transition shadow-2xs group"
|
||||
>
|
||||
<div className="flex items-center gap-2 truncate">
|
||||
<Search className="w-3.5 h-3.5 text-slate-400 group-hover:text-sky-600 transition" />
|
||||
<span className="truncate">Search patients, charts, or actions...</span>
|
||||
<div className="flex items-center gap-1.5 truncate">
|
||||
<Search className="w-3.5 h-3.5 text-slate-400 group-hover:text-sky-600 transition shrink-0" />
|
||||
<span className="truncate text-[11px]">Search (⌘K)...</span>
|
||||
</div>
|
||||
<kbd className="px-1.5 py-0.5 text-[9px] font-mono bg-white border border-slate-200 rounded text-slate-500 font-bold shrink-0 ml-2">
|
||||
<kbd className="px-1.5 py-0.5 text-[9px] font-mono bg-white border border-slate-200 rounded text-slate-500 font-bold shrink-0 ml-1">
|
||||
⌘K
|
||||
</kbd>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Right Cluster: Quick Tools + Role Switcher + Portal Switcher */}
|
||||
<div className="flex items-center gap-2 shrink-0 flex-wrap justify-end">
|
||||
{/* Search button on small screens where full bar is hidden */}
|
||||
{/* Right Cluster: Quick Tools + Portal Switcher */}
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{/* Search button on mobile screens where input is hidden */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
@@ -734,62 +734,7 @@ export default function Home() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Staff Role Switcher (RBAC) */}
|
||||
<div className="flex items-center bg-slate-100 p-0.5 rounded-lg border border-slate-200 text-xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('doctor');
|
||||
addToast('info', 'Role: Attending Doctor (D.C.)', 'Full clinical SOAP, 2D spine & telehealth unlocked');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'doctor'
|
||||
? 'bg-white text-sky-800 shadow-2xs border border-slate-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="Full Doctor Clinical Access"
|
||||
>
|
||||
Doctor
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('front_desk');
|
||||
if (clinicTab === 'charting' || clinicTab === 'telehealth') {
|
||||
setClinicTab('calendar');
|
||||
}
|
||||
addToast('alert', 'Role: Front Desk (HIPAA Safe)', 'Protected medical notes locked for privacy');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'front_desk'
|
||||
? 'bg-amber-100 text-amber-900 shadow-2xs border border-amber-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="HIPAA-Safe: Hides Clinical Notes, Shows Schedule, Retail & Billing"
|
||||
>
|
||||
Front Desk
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('billing_admin');
|
||||
addToast('info', 'Role: Billing Administrator', 'Superbill claims and memberships prioritized');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'billing_admin'
|
||||
? 'bg-white text-emerald-800 shadow-2xs border border-slate-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="Financial & Billing Administrator"
|
||||
>
|
||||
Billing
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Portal Mode Switcher */}
|
||||
{/* Portal Mode Switcher (Always 100% visible on the right) */}
|
||||
<div className="flex items-center bg-slate-100 p-0.5 rounded-lg border border-slate-200 text-xs font-semibold">
|
||||
<button
|
||||
type="button"
|
||||
@@ -888,7 +833,7 @@ export default function Home() {
|
||||
|
||||
{/* Pre-Launch / Pending BAA Banner */}
|
||||
{portalMode === 'clinic' && activeTenant.baaStatus === 'pending' && (
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-2.5">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-2">
|
||||
<div className="p-2.5 bg-emerald-50 border border-emerald-200/90 rounded-xl flex flex-col sm:flex-row items-center justify-between gap-2 text-xs">
|
||||
<div className="flex items-center gap-2 text-emerald-950">
|
||||
<span className="w-2.5 h-2.5 rounded-full bg-emerald-500 animate-pulse shrink-0" />
|
||||
@@ -911,10 +856,10 @@ export default function Home() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tier 2: Sub-Tabs for Doctor Clinic OS (Cleanly Grouped, No Horizontal Overflow) */}
|
||||
{/* Tier 2: Sub-Tabs for Doctor Clinic OS + Staff Role Switcher */}
|
||||
{portalMode === 'clinic' && (
|
||||
<div className="border-t border-slate-100 bg-slate-50/50">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-2 flex items-center justify-between flex-wrap gap-2 text-xs">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-1.5 flex items-center justify-between flex-wrap gap-2 text-xs">
|
||||
{/* Grouped Clinical Workspace Navigation */}
|
||||
<div className="flex items-center flex-wrap gap-1.5">
|
||||
{/* Group 1: Clinical Operations */}
|
||||
@@ -1042,10 +987,68 @@ export default function Home() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Active Clinician Presence Indicator */}
|
||||
<div className="hidden xl:flex items-center gap-2 text-xs text-slate-500 font-mono">
|
||||
{/* Right Side: Staff Role Switcher (RBAC) + Attending Doctor */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Staff Role Switcher */}
|
||||
<div className="flex items-center bg-slate-100 p-0.5 rounded-lg border border-slate-200 text-xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('doctor');
|
||||
addToast('info', 'Role: Attending Doctor (D.C.)', 'Full clinical SOAP, 2D spine & telehealth unlocked');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'doctor'
|
||||
? 'bg-white text-sky-800 shadow-2xs border border-slate-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="Full Doctor Clinical Access"
|
||||
>
|
||||
Doctor
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('front_desk');
|
||||
if (clinicTab === 'charting' || clinicTab === 'telehealth') {
|
||||
setClinicTab('calendar');
|
||||
}
|
||||
addToast('alert', 'Role: Front Desk (HIPAA Safe)', 'Protected medical notes locked for privacy');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'front_desk'
|
||||
? 'bg-amber-100 text-amber-900 shadow-2xs border border-amber-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="HIPAA-Safe: Hides Clinical Notes, Shows Schedule, Retail & Billing"
|
||||
>
|
||||
Front Desk
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('billing_admin');
|
||||
addToast('info', 'Role: Billing Administrator', 'Superbill claims and memberships prioritized');
|
||||
}}
|
||||
className={`px-2 py-1 rounded-md text-[11px] font-bold transition ${
|
||||
staffRole === 'billing_admin'
|
||||
? 'bg-white text-emerald-800 shadow-2xs border border-slate-200'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
title="Financial & Billing Administrator"
|
||||
>
|
||||
Billing
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Active Clinician Presence Indicator */}
|
||||
<div className="hidden 2xl:flex items-center gap-1.5 text-xs text-slate-600 font-mono bg-white px-2 py-1 rounded-lg border border-slate-200 shadow-2xs">
|
||||
<span className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
|
||||
<span>Active: <strong>{activeProvider.name}</strong></span>
|
||||
<span className="font-semibold">{activeProvider.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user