99 lines
4.1 KiB
TypeScript
99 lines
4.1 KiB
TypeScript
'use client';
|
|
|
|
import React from 'react';
|
|
import { OperatorSession } from './types';
|
|
|
|
interface OperationsTopBarProps {
|
|
session: OperatorSession;
|
|
onSignOut: () => void;
|
|
onToggleMobileSidebar: () => void;
|
|
signingOut?: boolean;
|
|
}
|
|
|
|
export function OperationsTopBar({
|
|
session,
|
|
onSignOut,
|
|
onToggleMobileSidebar,
|
|
signingOut = false,
|
|
}: OperationsTopBarProps) {
|
|
const isOwner = session.role === 'owner';
|
|
const environment = session.environment
|
|
? session.environment.charAt(0).toUpperCase() + session.environment.slice(1).toLowerCase()
|
|
: 'Production';
|
|
|
|
return (
|
|
<header className="fixed top-0 right-0 left-0 lg:left-64 z-30 h-16 bg-surface-container-lowest/90 backdrop-blur-md border-b border-outline-variant/30 flex items-center justify-between px-4 sm:px-6 lg:px-8">
|
|
{/* Left: Mobile Drawer Button + Operations Branding Title */}
|
|
<div className="flex items-center gap-3 min-w-0">
|
|
<button
|
|
type="button"
|
|
onClick={onToggleMobileSidebar}
|
|
aria-label="Toggle navigation menu"
|
|
className="lg:hidden p-2 rounded-lg bg-surface-container-low hover:bg-surface-container-high text-on-surface border border-outline-variant/30 focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none"
|
|
>
|
|
<span className="material-symbols-outlined text-[20px]">menu</span>
|
|
</button>
|
|
|
|
<div className="flex items-center gap-2 min-w-0">
|
|
<div className="flex items-center gap-1.5 shrink-0">
|
|
<span className="font-headline-sm text-sm sm:text-base font-bold text-on-surface tracking-tight">
|
|
MotorSignal
|
|
</span>
|
|
<span className="px-1.5 py-0.5 rounded text-[10px] font-semibold bg-surface-container-high text-primary-container border border-primary-container/30">
|
|
Ops
|
|
</span>
|
|
</div>
|
|
|
|
<span className="hidden sm:inline-flex items-center px-2 py-0.5 rounded text-[10px] font-mono bg-surface-container-low text-on-surface-variant border border-outline-variant/30">
|
|
Env: {environment}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Right: Operator Identity + Role Pill + Status + Sign Out */}
|
|
<div className="flex items-center gap-2 sm:gap-3 shrink-0">
|
|
{/* Safe Identity */}
|
|
<div className="hidden md:flex flex-col items-end text-right">
|
|
<span className="text-xs font-semibold text-on-surface tracking-tight truncate max-w-[200px]">
|
|
{session.identity}
|
|
</span>
|
|
<span className="text-[10px] text-on-surface-variant font-mono">
|
|
Current Operations Identity
|
|
</span>
|
|
</div>
|
|
|
|
{/* Role Pill */}
|
|
<span
|
|
className={`px-2 py-0.5 rounded text-[11px] font-semibold capitalize ${
|
|
isOwner
|
|
? 'bg-primary-container/15 text-primary-container border border-primary-container/40'
|
|
: 'bg-surface-container-high text-on-surface-variant border border-outline-variant/40'
|
|
}`}
|
|
>
|
|
{session.role}
|
|
</span>
|
|
|
|
{/* Session Status Dot/Pill */}
|
|
<div className="hidden sm:inline-flex items-center gap-1.5 px-2 py-0.5 rounded-full bg-surface-container-low border border-outline-variant/30">
|
|
<span className="h-1.5 w-1.5 rounded-full bg-secondary-fixed"></span>
|
|
<span className="text-[10px] font-mono text-on-surface-variant">
|
|
Active
|
|
</span>
|
|
</div>
|
|
|
|
{/* Sign Out Action */}
|
|
<button
|
|
type="button"
|
|
onClick={onSignOut}
|
|
disabled={signingOut}
|
|
aria-label="Sign out of Operations"
|
|
className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-surface-container-low hover:bg-surface-container-high text-on-surface hover:text-error border border-outline-variant/30 text-xs font-semibold transition-colors focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none disabled:opacity-50"
|
|
>
|
|
<span className="material-symbols-outlined text-[16px]">logout</span>
|
|
<span className="hidden xs:inline">Sign Out</span>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|