diff --git a/frontends/dbal/src/status.ts b/frontends/dbal/src/status.ts new file mode 100644 index 000000000..51acc6dd4 --- /dev/null +++ b/frontends/dbal/src/status.ts @@ -0,0 +1,47 @@ +export type StatusLevel = 'online' | 'degraded' | 'offline' + +export interface ServerHealth { + name: string + status: StatusLevel + message: string + latencyMs?: number +} + +const baseStatuses: ServerHealth[] = [ + { + name: 'DBAL TypeScript Client', + status: 'online', + message: 'Handling CLI and server workflows via Prisma.', + latencyMs: 14, + }, + { + name: 'Prisma ORM', + status: 'online', + message: 'Schema validated & migrations ready (Postgres/MySQL).', + latencyMs: 32, + }, + { + name: 'C++ DBAL Daemon (Phase 3)', + status: 'degraded', + message: 'Running the in-memory prototype while SQL adapters mature.', + latencyMs: 48, + }, + { + name: 'Server Side Metrics', + status: 'online', + message: 'Audit logs streaming successfully and metrics exported.', + latencyMs: 5, + }, +] + +export interface StatusResponse { + updatedAt: string + statuses: ServerHealth[] +} + +export function getStatusResponse(): StatusResponse { + return { + updatedAt: new Date().toISOString(), + statuses: baseStatuses, + } +} diff --git a/frontends/nextjs/src/components/status/ServerStatusPanel.tsx b/frontends/nextjs/src/components/status/ServerStatusPanel.tsx deleted file mode 100644 index d9acc86cd..000000000 --- a/frontends/nextjs/src/components/status/ServerStatusPanel.tsx +++ /dev/null @@ -1,119 +0,0 @@ -"use client" - -import { useEffect, useMemo, useState } from 'react' - -type StatusLevel = 'online' | 'degraded' | 'offline' - -interface ServerHealth { - name: string - status: StatusLevel - message: string - latencyMs?: number -} - -interface StatusResponse { - updatedAt: string - statuses: ServerHealth[] -} - -const statusPalette: Record = { - online: 'bg-emerald-500/90', - degraded: 'bg-amber-500/80', - offline: 'bg-rose-500/80', -} - -export function ServerStatusPanel() { - const [health, setHealth] = useState([]) - const [lastUpdated, setLastUpdated] = useState('') - const [error, setError] = useState(null) - const [loading, setLoading] = useState(true) - - useEffect(() => { - let cancelled = false - - const fetchStatus = async () => { - try { - const response = await fetch('/api/status', { cache: 'no-store' }) - if (!response.ok) { - throw new Error('Status endpoint failed') - } - - const data: StatusResponse = await response.json() - if (cancelled) return - - setHealth(data.statuses) - setLastUpdated(data.updatedAt) - setError(null) - } catch (err) { - if (cancelled) return - setError(err instanceof Error ? err.message : 'Unable to load status') - } finally { - if (!cancelled) setLoading(false) - } - } - - void fetchStatus() - - const refreshInterval = setInterval(fetchStatus, 30_000) - return () => { - cancelled = true - clearInterval(refreshInterval) - } - }, []) - - const summary = useMemo(() => { - if (error) { - return 'Status unavailable right now' - } - - if (health.length === 0) { - return 'Initializing status feed...' - } - - const degraded = health.some(item => item.status !== 'online') - return degraded ? 'Some systems need attention' : 'All systems nominal' - }, [health, error]) - - return ( -
-
-

Server status

-

Observability Feed

-

{summary}

-
- -
- {loading && health.length === 0 ? ( -
Loading status...
- ) : error ? ( -
-

{error}

-

Try refreshing the page in a few moments.

-
- ) : ( - health.map(item => ( -
-
-
- -

{item.name}

-
- - {item.status} - -
-

{item.message}

-
- {item.latencyMs != null ? `${item.latencyMs.toFixed(0)} ms` : 'Latency unknown'} - Updated {lastUpdated ? new Date(lastUpdated).toLocaleTimeString() : '—'} -
-
- )) - )} -
-
- ) -}