48 lines
1.9 KiB
TypeScript
48 lines
1.9 KiB
TypeScript
'use client'
|
|
import { useEngineStore } from '@/store/engineStore'
|
|
import { useSSE } from '@/hooks/useSSE'
|
|
import { formatUptime, cn } from '@/lib/utils'
|
|
|
|
export default function StatusBar() {
|
|
useSSE()
|
|
const { status, uptime_seconds, total_scanned, total_alerts, isOffline } = useEngineStore()
|
|
|
|
if (isOffline) {
|
|
return (
|
|
<div className="flex items-center gap-2 bg-g-red/5 border-b border-g-red/15 px-6 py-1.5 text-xs text-g-red">
|
|
<span className="w-2 h-2 rounded-full bg-g-red animate-pulse flex-shrink-0" />
|
|
Engine offline — cannot reach server
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const isRunning = status === 'Running'
|
|
const isPaused = status === 'Paused'
|
|
|
|
return (
|
|
<div className="flex items-center gap-6 bg-g-base/60 backdrop-blur-sm border-b border-g-border/30 px-6 py-1.5 text-xs text-g-faint">
|
|
<Stat
|
|
dot={isRunning ? 'bg-g-green shadow-[0_0_4px_rgba(0,232,123,0.6)] animate-pulse' : isPaused ? 'bg-g-amber' : 'bg-g-faint'}
|
|
label="Engine"
|
|
value={status}
|
|
valueClass={isRunning ? 'text-g-green' : isPaused ? 'text-g-amber' : 'text-g-muted'}
|
|
/>
|
|
<Stat label="Uptime" value={formatUptime(uptime_seconds)} valueClass="text-g-muted" />
|
|
<Stat label="Scanned" value={String(total_scanned)} valueClass="text-g-text font-semibold" />
|
|
<Stat label="Alerts" value={String(total_alerts)} valueClass={total_alerts > 0 ? 'text-g-amber font-semibold' : 'text-g-muted'} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function Stat({ label, value, valueClass = 'text-g-muted', dot }: {
|
|
label: string; value: string; valueClass?: string; dot?: string
|
|
}) {
|
|
return (
|
|
<span className="flex items-center gap-1.5">
|
|
{dot && <span className={cn('w-1.5 h-1.5 rounded-full flex-shrink-0', dot)} />}
|
|
<span className="text-g-faint/70">{label}</span>
|
|
<span className={cn('font-medium tabular-nums', valueClass)}>{value}</span>
|
|
</span>
|
|
)
|
|
}
|