MotorSignal-App/website/components/ops/operations-overview.tsx

204 lines
7.4 KiB
TypeScript

'use client';
import React from 'react';
import { OperationsHealth, ComponentHealthStatus, HealthComponentKey } from './types';
import { HEALTH_COMPONENT_METADATA } from '../../lib/ops-data';
interface OperationsOverviewProps {
health: OperationsHealth;
onRefresh: () => Promise<void> | void;
isRefreshing: boolean;
}
export function OperationsOverview({
health,
onRefresh,
isRefreshing,
}: OperationsOverviewProps) {
const componentKeys: HealthComponentKey[] = [
'operations_api',
'operations_database',
'session_validation',
'audit_persistence',
];
function getStatusBadge(status: ComponentHealthStatus) {
switch (status) {
case 'available':
return {
label: 'AVAILABLE',
icon: 'check_circle',
classes: 'bg-emerald-950/60 text-emerald-400 border-emerald-800/60',
};
case 'degraded':
return {
label: 'DEGRADED',
icon: 'warning',
classes: 'bg-amber-950/60 text-amber-400 border-amber-800/60',
};
case 'unavailable':
return {
label: 'UNAVAILABLE',
icon: 'cancel',
classes: 'bg-rose-950/60 text-rose-400 border-rose-800/60',
};
case 'unknown':
default:
return {
label: 'UNKNOWN',
icon: 'help',
classes: 'bg-surface-container-highest text-on-surface-variant border-outline-variant/40',
};
}
}
const formattedCheckedAt = health.checked_at
? new Date(health.checked_at).toLocaleString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
timeZoneName: 'short',
})
: '--';
return (
<div className="space-y-6">
{/* Header Row: Title & Manual Refresh */}
<div className="flex flex-col sm:flex-row sm:items-end justify-between gap-4 pb-4 border-b border-outline-variant/30">
<div>
<span className="text-[11px] font-mono uppercase tracking-widest text-primary-fixed-dim">
SYSTEM HEALTH
</span>
<h1 className="font-headline-xl text-2xl sm:text-3xl font-bold text-on-surface tracking-tight mt-1">
Operations Overview
</h1>
<p className="text-xs text-on-surface-variant mt-1">
Real-time health telemetry across core Operations subsystems.
</p>
</div>
<div className="flex items-center gap-3 shrink-0">
<div className="text-right">
<span className="block text-[10px] uppercase font-mono text-outline">
Last checked
</span>
<time
dateTime={health.checked_at}
className="text-xs font-mono text-on-surface font-medium"
>
{formattedCheckedAt}
</time>
</div>
<button
type="button"
onClick={() => void onRefresh()}
disabled={isRefreshing}
aria-label="Refresh Operations health status"
className="inline-flex items-center gap-1.5 px-3.5 py-2 rounded-lg bg-surface-container-high hover:bg-surface-bright text-primary-container border border-primary-container/40 text-xs font-semibold shadow-sm transition-all focus-visible:ring-2 focus-visible:ring-primary-container focus-visible:outline-none disabled:opacity-50 disabled:cursor-not-allowed"
>
<span
className={`material-symbols-outlined text-[16px] ${
isRefreshing ? 'animate-spin' : ''
}`}
>
refresh
</span>
<span>{isRefreshing ? 'Checking...' : 'Refresh'}</span>
</button>
</div>
</div>
{/* 4 Health Status Cards */}
<div
className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4"
aria-label="Subsystem Health Telemetry"
>
{componentKeys.map((key) => {
const meta = HEALTH_COMPONENT_METADATA[key];
const comp = health.components?.[key];
const status = comp?.status ?? 'unknown';
const badge = getStatusBadge(status);
return (
<article
key={key}
className="p-4 rounded-xl bg-surface-container-low border border-outline-variant/30 flex flex-col justify-between gap-3 relative overflow-hidden group hover:border-outline-variant/60 transition-colors"
>
<div className="space-y-1">
<span className="text-[10px] font-mono uppercase tracking-wider text-outline">
Subsystem
</span>
<h2 className="text-sm font-bold text-on-surface tracking-tight">
{meta.name}
</h2>
<p className="text-[11px] text-on-surface-variant leading-relaxed">
{comp?.description || meta.description}
</p>
</div>
<div className="pt-2 border-t border-outline-variant/20 flex items-center justify-between">
<span className="text-[10px] text-outline font-mono uppercase">
Status
</span>
<div
className={`inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10px] font-mono font-bold tracking-wider border uppercase ${badge.classes}`}
role="status"
aria-live="polite"
>
<span className="material-symbols-outlined text-[12px]">
{badge.icon}
</span>
<span>{badge.label}</span>
</div>
</div>
</article>
);
})}
</div>
{/* Operational Policy & Architecture Boundary */}
<div className="p-5 rounded-xl bg-surface-container-lowest border border-outline-variant/30 space-y-3">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined text-primary-container text-[18px]">
verified_user
</span>
<h3 className="text-xs font-bold text-on-surface uppercase tracking-wider">
Operational Architecture &amp; Data Boundary
</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 text-xs text-on-surface-variant pt-2 border-t border-outline-variant/20">
<div>
<span className="block font-semibold text-on-surface mb-0.5">
Authority Source
</span>
<p className="leading-normal">
PostgreSQL <code className="text-primary-fixed-dim">ops.operators</code> schema. Consumer roles and Firebase custom claims strictly bypassed.
</p>
</div>
<div>
<span className="block font-semibold text-on-surface mb-0.5">
Privacy Isolation
</span>
<p className="leading-normal">
Zero cross-rider data access. Personal rides, GPS points, vehicles, and billing accounts are structurally inaccessible.
</p>
</div>
<div>
<span className="block font-semibold text-on-surface mb-0.5">
Session Integrity
</span>
<p className="leading-normal">
Governed by host-prefixed <code className="text-primary-fixed-dim">__Host-motorsignal_ops</code> cookies with strict same-origin isolation.
</p>
</div>
</div>
</div>
</div>
);
}