MotorSignal-App/website/components/ops/operations-top-bar.tsx

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>
);
}