fix(layout): streamline header layout and sub-tab navigation to eliminate horizontal overflow
This commit is contained in:
+407
-325
@@ -116,6 +116,7 @@ export default function Home() {
|
||||
const [isTerminalLocked, setIsTerminalLocked] = useState(false);
|
||||
const [toasts, setToasts] = useState<ToastMessage[]>([]);
|
||||
const [audioEnabled, setAudioEnabled] = useState(true);
|
||||
const [isMoreMenuOpen, setIsMoreMenuOpen] = useState(false);
|
||||
|
||||
const [activePatient, setActivePatient] = useState<Patient>(INITIAL_PATIENTS[0]);
|
||||
const [activeSoapNote, setActiveSoapNote] = useState<SoapNote | undefined>(INITIAL_SOAP_NOTES[0]);
|
||||
@@ -607,365 +608,446 @@ export default function Home() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50 text-slate-900 flex flex-col">
|
||||
<div className="min-h-screen bg-slate-50 text-slate-900 flex flex-col w-full max-w-full overflow-x-hidden">
|
||||
{/* Top Hospital Command Header */}
|
||||
<header className="sticky top-0 z-40 bg-white border-b border-slate-200/90 px-4 lg:px-8 py-3 shadow-2xs">
|
||||
<div className="max-w-7xl mx-auto flex flex-col md:flex-row md:items-center justify-between gap-4">
|
||||
{/* Hospital Brand & Domain */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<span className="w-9 h-9 rounded-lg bg-sky-700 flex items-center justify-center font-black text-sm text-white shadow-xs">
|
||||
+M
|
||||
</span>
|
||||
<div>
|
||||
<div className="text-xs font-black tracking-tight text-slate-900 flex items-center gap-1.5">
|
||||
<span>MEDIUSA CLINIC OS</span>
|
||||
<span className="text-[10px] px-2 py-0.5 rounded-full bg-sky-100 text-sky-800 font-bold border border-sky-200">
|
||||
CLINICAL v2.5
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-slate-500 font-mono flex items-center gap-1 mt-0.5">
|
||||
<Globe className="w-3 h-3 text-sky-700" />
|
||||
https://{activeTenant.domain}
|
||||
<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">
|
||||
{/* Left Cluster: Hospital Brand & Clinic Identity */}
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<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>
|
||||
<div>
|
||||
<div className="text-xs font-black tracking-tight text-slate-900 flex items-center gap-1.5">
|
||||
<span>MEDIUSA CLINIC OS</span>
|
||||
<span className="text-[10px] px-1.5 py-0.2 rounded-full bg-sky-100 text-sky-800 font-bold border border-sky-200">
|
||||
v2.5
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-[10px] text-slate-400 font-mono 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" />
|
||||
|
||||
{/* 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"
|
||||
title="Switch Clinic Location / Practice"
|
||||
>
|
||||
{tenants.map((t) => (
|
||||
<option key={t.id} value={t.id}>
|
||||
🏥 {t.name}
|
||||
</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" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Command Palette Trigger (Cmd+K) */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsCommandPaletteOpen(true);
|
||||
}}
|
||||
className="hidden xl:flex items-center gap-2 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"
|
||||
>
|
||||
<Search className="w-3.5 h-3.5 text-slate-400" />
|
||||
<span>Search patients or actions...</span>
|
||||
<kbd className="px-1.5 py-0.5 text-[9px] font-mono bg-white border border-slate-200 rounded text-slate-500 font-bold">
|
||||
⌘K
|
||||
</kbd>
|
||||
</button>
|
||||
|
||||
{/* Audio Toggle Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleToggleAudio}
|
||||
title={audioEnabled ? 'Tactile Audio Active (Click to Mute)' : 'Tactile Audio Muted (Click to Enable)'}
|
||||
className={`p-1.5 rounded-lg border text-xs transition flex items-center gap-1 shadow-2xs ${
|
||||
audioEnabled
|
||||
? 'bg-sky-50 border-sky-200 text-sky-700 hover:bg-sky-100'
|
||||
: 'bg-slate-100 border-slate-200 text-slate-400 hover:bg-slate-200'
|
||||
}`}
|
||||
>
|
||||
{audioEnabled ? <Volume2 className="w-4 h-4" /> : <VolumeX className="w-4 h-4" />}
|
||||
</button>
|
||||
|
||||
{/* Court & HIPAA Compliance Vault Trigger Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsCourtVaultOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-slate-900 hover:bg-slate-800 text-white text-xs font-bold transition shadow-xs border border-slate-700"
|
||||
title="21 CFR Part 11 Court Defense Audit Trail, Non-Repudiation Seal & BAA"
|
||||
>
|
||||
<Scale className="w-3.5 h-3.5 text-sky-400" />
|
||||
<span className="hidden sm:inline">Court & HIPAA Vault</span>
|
||||
<span className="sm:hidden">Vault</span>
|
||||
</button>
|
||||
|
||||
{/* Quick Terminal Lockout Button (HIPAA 45 CFR § 164.312(a)(2)(iii)) */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsTerminalLocked(true);
|
||||
}}
|
||||
className="flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg bg-slate-100 hover:bg-rose-50 border border-slate-200 hover:border-rose-300 text-slate-700 hover:text-rose-700 text-xs font-bold transition shadow-2xs"
|
||||
title="Lock Clinical Terminal (Cmd+L / 45 CFR § 164.312(a)(2)(iii))"
|
||||
>
|
||||
<Lock className="w-3.5 h-3.5 text-slate-500 hover:text-rose-600" />
|
||||
<span className="hidden md:inline">Lock</span>
|
||||
</button>
|
||||
|
||||
{/* Clinic Dropdown */}
|
||||
<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 px-3 py-1.5 pr-8 cursor-pointer focus:outline-none focus:border-sky-500 transition shadow-2xs"
|
||||
>
|
||||
{tenants.map((t) => (
|
||||
<option key={t.id} value={t.id}>
|
||||
🏥 {t.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<ChevronDown className="w-3.5 h-3.5 text-slate-500 absolute right-2.5 top-1/2 -translate-y-1/2 pointer-events-none" />
|
||||
</div>
|
||||
|
||||
{/* Staff Role Switcher (RBAC) */}
|
||||
<div className="flex items-center gap-1 bg-slate-100 p-1 rounded-lg border border-slate-200 text-xs">
|
||||
<span className="text-[10px] uppercase font-bold text-slate-500 px-1.5">Role:</span>
|
||||
{/* Center: Command Palette / Search Bar (Responsive) */}
|
||||
<div className="flex-1 max-w-xs xl:max-w-sm hidden md:block">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setStaffRole('doctor');
|
||||
addToast('info', 'Role: Attending Doctor (D.C.)', 'Full clinical SOAP, 2D spine & telehealth unlocked');
|
||||
setIsCommandPaletteOpen(true);
|
||||
}}
|
||||
className={`px-2 py-1 rounded text-xs 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"
|
||||
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"
|
||||
>
|
||||
Doctor (D.C.)
|
||||
</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 text-xs 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 text-xs 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 Admin
|
||||
<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>
|
||||
<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">
|
||||
⌘K
|
||||
</kbd>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Portal Switcher Tabs */}
|
||||
<div className="flex items-center gap-1 bg-slate-100 p-1 rounded-lg border border-slate-200 text-xs font-semibold">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('clinic');
|
||||
}}
|
||||
className={`px-3 py-1.5 rounded-md flex items-center gap-1.5 transition ${
|
||||
portalMode === 'clinic'
|
||||
? 'bg-sky-700 text-white font-bold shadow-xs'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Stethoscope className="w-3.5 h-3.5" />
|
||||
Doctor & Practice OS
|
||||
</button>
|
||||
{/* 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 */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsCommandPaletteOpen(true);
|
||||
}}
|
||||
className="md:hidden p-1.5 rounded-lg border border-slate-200 bg-slate-50 hover:bg-slate-100 text-slate-600 shadow-2xs"
|
||||
title="Search patients (⌘K)"
|
||||
>
|
||||
<Search className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('patient');
|
||||
}}
|
||||
className={`px-3 py-1.5 rounded-md flex items-center gap-1.5 transition ${
|
||||
portalMode === 'patient'
|
||||
? 'bg-sky-700 text-white font-bold shadow-xs'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Laptop className="w-3.5 h-3.5" />
|
||||
Patient Booking & Intake
|
||||
</button>
|
||||
{/* Utility & Security Actions Cluster */}
|
||||
<div className="flex items-center gap-0.5 bg-slate-100/80 p-0.5 rounded-lg border border-slate-200">
|
||||
{/* Audio Toggle */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleToggleAudio}
|
||||
title={audioEnabled ? 'Tactile Audio Active (Click to Mute)' : 'Tactile Audio Muted (Click to Enable)'}
|
||||
className={`p-1.5 rounded-md text-xs transition ${
|
||||
audioEnabled
|
||||
? 'bg-white text-sky-700 shadow-2xs font-semibold'
|
||||
: 'text-slate-400 hover:text-slate-600'
|
||||
}`}
|
||||
>
|
||||
{audioEnabled ? <Volume2 className="w-3.5 h-3.5 text-sky-600" /> : <VolumeX className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setPortalMode('superadmin')}
|
||||
className={`px-3 py-1.5 rounded-md flex items-center gap-1.5 transition ${
|
||||
portalMode === 'superadmin'
|
||||
? 'bg-slate-900 text-white font-bold shadow-xs'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Building2 className="w-3.5 h-3.5" />
|
||||
Mediusa Super-Admin
|
||||
</button>
|
||||
{/* Court Vault Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsCourtVaultOpen(true);
|
||||
}}
|
||||
className="flex items-center gap-1 px-2 py-1 rounded-md text-slate-700 hover:text-slate-950 hover:bg-white text-xs font-semibold transition"
|
||||
title="21 CFR Part 11 Court Defense Audit Vault & BAA Non-Repudiation Seal"
|
||||
>
|
||||
<Scale className="w-3.5 h-3.5 text-sky-600" />
|
||||
<span className="hidden sm:inline text-[11px]">Vault</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('onboarding');
|
||||
}}
|
||||
className={`px-3 py-1.5 rounded-md flex items-center gap-1.5 transition ${
|
||||
portalMode === 'onboarding'
|
||||
? 'bg-emerald-700 text-white font-bold shadow-xs'
|
||||
: 'text-emerald-700 hover:text-emerald-900 bg-emerald-50/70 hover:bg-emerald-100/70 border border-emerald-200/60'
|
||||
}`}
|
||||
>
|
||||
<Sparkles className="w-3.5 h-3.5 text-amber-500 animate-pulse" />
|
||||
+ Onboard Doctor (BAA)
|
||||
</button>
|
||||
{/* Terminal Lock Button */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setIsTerminalLocked(true);
|
||||
}}
|
||||
className="flex items-center gap-1 px-2 py-1 rounded-md text-slate-700 hover:text-rose-700 hover:bg-rose-50 text-xs font-semibold transition"
|
||||
title="Lock Clinical Terminal (HIPAA 45 CFR § 164.312(a)(2)(iii))"
|
||||
>
|
||||
<Lock className="w-3.5 h-3.5 text-slate-500" />
|
||||
<span className="hidden sm:inline text-[11px]">Lock</span>
|
||||
</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 */}
|
||||
<div className="flex items-center bg-slate-100 p-0.5 rounded-lg border border-slate-200 text-xs font-semibold">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('clinic');
|
||||
}}
|
||||
className={`px-2.5 py-1 rounded-md flex items-center gap-1.5 transition text-[11px] ${
|
||||
portalMode === 'clinic'
|
||||
? 'bg-sky-700 text-white font-bold shadow-xs'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Stethoscope className="w-3 h-3" />
|
||||
<span>Doctor OS</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('patient');
|
||||
}}
|
||||
className={`px-2.5 py-1 rounded-md flex items-center gap-1.5 transition text-[11px] ${
|
||||
portalMode === 'patient'
|
||||
? 'bg-sky-700 text-white font-bold shadow-xs'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Laptop className="w-3 h-3" />
|
||||
<span>Patient Intake</span>
|
||||
</button>
|
||||
|
||||
{/* More Views Dropdown */}
|
||||
<div className="relative">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setIsMoreMenuOpen((prev) => !prev)}
|
||||
className={`px-2 py-1 rounded-md flex items-center gap-1 text-[11px] transition ${
|
||||
portalMode === 'superadmin' || portalMode === 'onboarding'
|
||||
? 'bg-slate-900 text-white font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900 hover:bg-slate-200/60'
|
||||
}`}
|
||||
title="Administrative & Onboarding Views"
|
||||
>
|
||||
<span>{portalMode === 'superadmin' ? 'Admin' : portalMode === 'onboarding' ? 'Onboard' : 'More'}</span>
|
||||
<ChevronDown className="w-3 h-3 opacity-60" />
|
||||
</button>
|
||||
|
||||
{isMoreMenuOpen && (
|
||||
<>
|
||||
<div
|
||||
className="fixed inset-0 z-40"
|
||||
onClick={() => setIsMoreMenuOpen(false)}
|
||||
/>
|
||||
<div className="absolute right-0 top-full mt-1.5 bg-white border border-slate-200 shadow-xl rounded-xl py-1.5 w-52 z-50 animate-in fade-in zoom-in-95 duration-100">
|
||||
<div className="px-3 py-1 text-[10px] uppercase font-bold text-slate-400 tracking-wider">
|
||||
Administrative Views
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('superadmin');
|
||||
setIsMoreMenuOpen(false);
|
||||
}}
|
||||
className={`w-full px-3 py-2 text-left text-xs font-semibold flex items-center gap-2 transition ${
|
||||
portalMode === 'superadmin' ? 'bg-slate-100 text-slate-950 font-bold' : 'text-slate-700 hover:bg-slate-50'
|
||||
}`}
|
||||
>
|
||||
<Building2 className="w-3.5 h-3.5 text-slate-500" />
|
||||
<span>Mediusa Super-Admin</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('onboarding');
|
||||
setIsMoreMenuOpen(false);
|
||||
}}
|
||||
className={`w-full px-3 py-2 text-left text-xs font-semibold flex items-center gap-2 transition ${
|
||||
portalMode === 'onboarding' ? 'bg-emerald-50 text-emerald-950 font-bold' : 'text-emerald-700 hover:bg-emerald-50'
|
||||
}`}
|
||||
>
|
||||
<Sparkles className="w-3.5 h-3.5 text-amber-500" />
|
||||
<span>+ Onboard Doctor (BAA)</span>
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Pre-Launch / Pending BAA Banner */}
|
||||
{portalMode === 'clinic' && activeTenant.baaStatus === 'pending' && (
|
||||
<div className="max-w-7xl mx-auto mt-2.5 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" />
|
||||
<span className="font-bold">{activeTenant.name}:</span>
|
||||
<span className="text-emerald-800">
|
||||
Scheduling, calendars, and digital intake are active for testing. Ready for doctor BAA sign-off on go-live!
|
||||
</span>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pb-2.5">
|
||||
<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" />
|
||||
<span className="font-bold">{activeTenant.name}:</span>
|
||||
<span className="text-emerald-800">
|
||||
Scheduling, calendars, and digital intake are active for testing. Ready for doctor BAA sign-off on go-live!
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('onboarding');
|
||||
}}
|
||||
className="px-3 py-1 bg-emerald-700 hover:bg-emerald-800 text-white font-bold rounded-lg transition shadow-xs flex items-center gap-1.5 shrink-0"
|
||||
>
|
||||
<ShieldCheck className="w-3.5 h-3.5" /> Sign BAA to Go Live
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
clinicalAudio.playClick();
|
||||
setPortalMode('onboarding');
|
||||
}}
|
||||
className="px-3 py-1 bg-emerald-700 hover:bg-emerald-800 text-white font-bold rounded-lg transition shadow-xs flex items-center gap-1.5 shrink-0"
|
||||
>
|
||||
<ShieldCheck className="w-3.5 h-3.5" /> Sign BAA to Go Live
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Sub-Tabs for Doctor Clinic OS */}
|
||||
{/* Tier 2: Sub-Tabs for Doctor Clinic OS (Cleanly Grouped, No Horizontal Overflow) */}
|
||||
{portalMode === 'clinic' && (
|
||||
<div className="max-w-7xl mx-auto flex items-center gap-2 mt-3 pt-2.5 border-t border-slate-100 overflow-x-auto text-xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('calendar')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'calendar'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Calendar className="w-3.5 h-3.5 text-sky-700" />
|
||||
Schedule & Encounters
|
||||
</button>
|
||||
<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">
|
||||
{/* Grouped Clinical Workspace Navigation */}
|
||||
<div className="flex items-center flex-wrap gap-1.5">
|
||||
{/* Group 1: Clinical Operations */}
|
||||
<div className="flex items-center bg-white p-0.5 rounded-lg border border-slate-200/90 shadow-2xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('calendar')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'calendar'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Calendar className="w-3.5 h-3.5 text-sky-700" />
|
||||
<span>Schedule</span>
|
||||
</button>
|
||||
|
||||
{/* Clinical Charts - Hidden if in Front Desk HIPAA-safe mode */}
|
||||
{staffRole !== 'front_desk' ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('charting')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'charting'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<FileText className="w-3.5 h-3.5 text-sky-700" />
|
||||
SOAP Chart & Spine ({activePatient.firstName} {activePatient.lastName})
|
||||
</button>
|
||||
) : (
|
||||
<span className="px-2.5 py-1 text-[11px] text-amber-700 bg-amber-50 rounded-md border border-amber-200 font-medium flex items-center gap-1">
|
||||
<Shield className="w-3 h-3 text-amber-600" /> HIPAA: Notes Protected
|
||||
</span>
|
||||
)}
|
||||
{staffRole !== 'front_desk' ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('charting')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'charting'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<FileText className="w-3.5 h-3.5 text-sky-700" />
|
||||
<span>SOAP Chart</span>
|
||||
<span className="text-[10px] px-1.5 py-0.2 rounded bg-sky-100 text-sky-800 font-mono font-medium">
|
||||
{activePatient.firstName} {activePatient.lastName.charAt(0)}.
|
||||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<span className="px-2 py-1 text-[10px] text-amber-700 bg-amber-50 rounded font-medium flex items-center gap-1">
|
||||
<Shield className="w-3 h-3 text-amber-600" /> Notes Locked
|
||||
</span>
|
||||
)}
|
||||
|
||||
{staffRole !== 'front_desk' && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('telehealth')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'telehealth'
|
||||
? 'bg-purple-50 text-purple-800 border border-purple-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Video className="w-3.5 h-3.5 text-purple-600" />
|
||||
Telehealth Virtual Room
|
||||
</button>
|
||||
)}
|
||||
{staffRole !== 'front_desk' && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('telehealth')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'telehealth'
|
||||
? 'bg-purple-50 text-purple-800 border border-purple-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Video className="w-3.5 h-3.5 text-purple-600" />
|
||||
<span>Telehealth</span>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('retail')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'retail'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<ShoppingBag className="w-3.5 h-3.5 text-sky-700" />
|
||||
Retail & Supplement POS
|
||||
</button>
|
||||
{/* Group 2: Practice & Revenue */}
|
||||
<div className="flex items-center bg-white p-0.5 rounded-lg border border-slate-200/90 shadow-2xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('billing')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'billing'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<DollarSign className="w-3.5 h-3.5 text-emerald-600" />
|
||||
<span>Superbills & Billing</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('memberships')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'memberships'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Repeat className="w-3.5 h-3.5 text-sky-700" />
|
||||
Memberships & Packages
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('retail')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'retail'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<ShoppingBag className="w-3.5 h-3.5 text-sky-700" />
|
||||
<span>Retail POS</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('billing')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'billing'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<DollarSign className="w-3.5 h-3.5 text-sky-700" />
|
||||
Superbills & Invoicing
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('memberships')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'memberships'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Repeat className="w-3.5 h-3.5 text-sky-700" />
|
||||
<span>Memberships</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('retention')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'retention'
|
||||
? 'bg-amber-50 text-amber-800 border border-amber-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Users className="w-3.5 h-3.5 text-amber-600" />
|
||||
Retention Radar
|
||||
</button>
|
||||
{/* Group 3: Patient Retention & Growth */}
|
||||
<div className="flex items-center bg-white p-0.5 rounded-lg border border-slate-200/90 shadow-2xs">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('retention')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'retention'
|
||||
? 'bg-amber-50 text-amber-800 border border-amber-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<Users className="w-3.5 h-3.5 text-amber-600" />
|
||||
<span>Retention</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('growth')}
|
||||
className={`px-3 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition whitespace-nowrap ${
|
||||
clinicTab === 'growth'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<TrendingUp className="w-3.5 h-3.5 text-emerald-600" />
|
||||
Growth & SEO (GSC/GA4)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setClinicTab('growth')}
|
||||
className={`px-2.5 py-1.5 rounded-md font-semibold flex items-center gap-1.5 transition text-xs ${
|
||||
clinicTab === 'growth'
|
||||
? 'bg-sky-50 text-sky-800 border border-sky-200 shadow-2xs font-bold'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
<TrendingUp className="w-3.5 h-3.5 text-emerald-600" />
|
||||
<span>Growth & SEO</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Active Clinician Presence Indicator */}
|
||||
<div className="hidden xl:flex items-center gap-2 text-xs text-slate-500 font-mono">
|
||||
<span className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse" />
|
||||
<span>Active: <strong>{activeProvider.name}</strong></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user