'use client' import { useEffect, useState } from 'react' import { useRouter } from 'next/navigation' import { authFetch, clearToken, getApiBase, getToken } from '../lib/auth' type DiagnosticCatalogItem = { key: string label: string category: string description: string live_safe: boolean target: string | null configured: boolean config_status: string config_detail: string } type DiagnosticResult = { key: string label: string category: string description: string target: string | null live_safe: boolean configured: boolean status: string message: string detail?: unknown checked_at?: string duration_ms?: number } type DiagnosticsResponse = { checks: DiagnosticCatalogItem[] categories: string[] generated_at: string } type RunDiagnosticsResponse = { results: DiagnosticResult[] summary: { total: number up: number down: number degraded: number not_configured: number disabled: number } checked_at: string } type RunMode = 'safe' | 'all' | 'single' type AdminDiagnosticsPanelProps = { embedded?: boolean } const REFRESH_INTERVAL_MS = 30000 const STATUS_LABELS: Record = { idle: 'Ready', up: 'Up', down: 'Down', degraded: 'Degraded', disabled: 'Disabled', not_configured: 'Not configured', } function formatCheckedAt(value?: string) { if (!value) return 'Not yet run' const parsed = new Date(value) if (Number.isNaN(parsed.getTime())) return value return parsed.toLocaleString() } function formatDuration(value?: number) { if (typeof value !== 'number' || Number.isNaN(value) || value <= 0) { return 'Pending' } return `${value.toFixed(1)} ms` } function statusLabel(status: string) { return STATUS_LABELS[status] ?? status } export default function AdminDiagnosticsPanel({ embedded = false }: AdminDiagnosticsPanelProps) { const router = useRouter() const [loading, setLoading] = useState(true) const [authorized, setAuthorized] = useState(false) const [checks, setChecks] = useState([]) const [resultsByKey, setResultsByKey] = useState>({}) const [runningKeys, setRunningKeys] = useState([]) const [autoRefresh, setAutoRefresh] = useState(true) const [pageError, setPageError] = useState('') const [lastRunAt, setLastRunAt] = useState(null) const [lastRunMode, setLastRunMode] = useState(null) const [emailRecipient, setEmailRecipient] = useState('') const liveSafeKeys = checks.filter((check) => check.live_safe).map((check) => check.key) async function runDiagnostics(keys?: string[], mode: RunMode = 'single') { const baseUrl = getApiBase() const effectiveKeys = keys && keys.length > 0 ? keys : checks.map((check) => check.key) if (effectiveKeys.length === 0) { return } setRunningKeys((current) => Array.from(new Set([...current, ...effectiveKeys]))) setPageError('') try { const response = await authFetch(`${baseUrl}/admin/diagnostics/run`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ keys: effectiveKeys, ...(emailRecipient.trim() ? { recipient_email: emailRecipient.trim() } : {}), }), }) if (response.status === 401) { clearToken() router.push('/login') return } if (!response.ok) { const text = await response.text() throw new Error(text || `Diagnostics run failed: ${response.status}`) } const data = (await response.json()) as { status: string } & RunDiagnosticsResponse const nextResults: Record = {} for (const result of data.results ?? []) { nextResults[result.key] = result } setResultsByKey((current) => ({ ...current, ...nextResults })) setLastRunAt(data.checked_at ?? new Date().toISOString()) setLastRunMode(mode) } catch (error) { console.error(error) setPageError(error instanceof Error ? error.message : 'Diagnostics run failed.') } finally { setRunningKeys((current) => current.filter((key) => !effectiveKeys.includes(key))) } } useEffect(() => { let active = true const loadPage = async () => { if (!getToken()) { router.push('/login') return } try { const baseUrl = getApiBase() const authResponse = await authFetch(`${baseUrl}/auth/me`) if (!authResponse.ok) { if (authResponse.status === 401) { clearToken() router.push('/login') return } router.push('/') return } const me = await authResponse.json() if (!active) return if (me?.role !== 'admin') { router.push('/') return } const diagnosticsResponse = await authFetch(`${baseUrl}/admin/diagnostics`) if (!diagnosticsResponse.ok) { const text = await diagnosticsResponse.text() throw new Error(text || `Diagnostics load failed: ${diagnosticsResponse.status}`) } const data = (await diagnosticsResponse.json()) as { status: string } & DiagnosticsResponse if (!active) return setChecks(data.checks ?? []) setAuthorized(true) setLoading(false) const safeKeys = (data.checks ?? []).filter((check) => check.live_safe).map((check) => check.key) if (safeKeys.length > 0) { void runDiagnostics(safeKeys, 'safe') } } catch (error) { console.error(error) if (!active) return setPageError(error instanceof Error ? error.message : 'Unable to load diagnostics.') setLoading(false) } } void loadPage() return () => { active = false } }, [router]) useEffect(() => { if (!authorized || !autoRefresh || liveSafeKeys.length === 0) { return } const interval = window.setInterval(() => { void runDiagnostics(liveSafeKeys, 'safe') }, REFRESH_INTERVAL_MS) return () => { window.clearInterval(interval) } }, [authorized, autoRefresh, liveSafeKeys.join('|')]) if (loading) { return
Loading diagnostics...
} if (!authorized) { return null } const orderedCategories: string[] = [] for (const check of checks) { if (!orderedCategories.includes(check.category)) { orderedCategories.push(check.category) } } const mergedResults = checks.map((check) => { const result = resultsByKey[check.key] if (result) { return result } return { key: check.key, label: check.label, category: check.category, description: check.description, target: check.target, live_safe: check.live_safe, configured: check.configured, status: check.configured ? 'idle' : check.config_status, message: check.configured ? 'Ready to test.' : check.config_detail, checked_at: undefined, duration_ms: undefined, } satisfies DiagnosticResult }) const summary = { total: mergedResults.length, up: 0, down: 0, degraded: 0, disabled: 0, not_configured: 0, idle: 0, } for (const result of mergedResults) { const key = result.status as keyof typeof summary if (key in summary) { summary[key] += 1 } } return (

{embedded ? 'Connectivity diagnostics' : 'Control center'}

Use live checks for Magent and service connectivity. Use run all when you want outbound notification channels to send a real ping through the configured provider.

{autoRefresh ? 'Auto refresh on' : 'Auto refresh off'} {lastRunMode ? `Last run: ${lastRunMode}` : 'No run yet'}
Total {summary.total}
Up {summary.up}
Degraded {summary.degraded}
Down {summary.down}
Disabled {summary.disabled}
Not configured {summary.not_configured}
Last completed run: {formatCheckedAt(lastRunAt ?? undefined)}
{pageError ?
{pageError}
: null} {orderedCategories.map((category) => { const categoryChecks = mergedResults.filter((check) => check.category === category) return (

{category}

{category === 'Notifications' ? 'These tests can emit real messages.' : 'Safe live health checks.'}

{categoryChecks.length} checks
{categoryChecks.map((check) => { const isRunning = runningKeys.includes(check.key) return (

{check.label}

{statusLabel(check.status)}

{check.description}

Target {check.target || 'Not set'}
Latency {formatDuration(check.duration_ms)}
Mode {check.live_safe ? 'Live safe' : 'Manual only'}
Last checked {formatCheckedAt(check.checked_at)}
{isRunning ? 'Running diagnostic...' : check.message}
) })}
) })}
) }