import React, { useEffect, useState } from "react"; import { Alert, Box, Button, Paper, Typography } from "@mui/material"; import { api } from "../api"; type SummarizerMetrics = { healthy: boolean; model?: string | null; healthLatencyMs?: number | null; probeLatencyMs?: number | null; lastProbeAt?: string | null; lastProbeSuccessAt?: string | null; lastProbeFailureAt?: string | null; probeFailures: number; requests: number; cacheHits: number; cacheMisses: number; failures: number; averageLatencyMs?: number | null; lastError?: string | null; }; type SystemStatus = { environment: string; contentRoot: string; version: string; commitSha?: string | null; buildStamp?: string | null; storage: { dataRoot: string; dbPath: string; dbExists: boolean; dbSizeBytes?: number | null; companyCount: number; jobCount: number; deletedCount: number; }; email: { enabled: boolean; host?: string | null; port: number; enableSsl: boolean; from?: string | null; fromName?: string | null; }; summarizer: SummarizerMetrics; }; function formatBytes(bytes?: number | null) { if (bytes == null) return "-"; if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } function displayMetadata(value?: string | null) { return value && value.trim().length > 0 ? value : "-"; } export default function AdminSystemPage() { const [status, setStatus] = useState(null); const [loading, setLoading] = useState(false); const [runningProbe, setRunningProbe] = useState(false); const [error, setError] = useState(null); const load = async () => { setLoading(true); setError(null); try { const res = await api.get("/admin/system"); setStatus(res.data); } catch (e: any) { setError(e?.response?.data || e?.message || "Failed to load system status."); setStatus(null); } finally { setLoading(false); } }; useEffect(() => { void load(); }, []); return ( System status Quick operational view of storage, email, and summarizer health. {error ? {error} : null} Environment {status?.environment ?? "-"} Version {displayMetadata(status?.version)} Commit {displayMetadata(status?.commitSha)} {displayMetadata(status?.buildStamp)} Database {status?.storage.dbExists ? "Ready" : "Missing"} {formatBytes(status?.storage.dbSizeBytes)} SMTP {status?.email.enabled ? "Enabled" : "Disabled"} {status?.email.host || "No SMTP host configured"} Summarizer {status?.summarizer.healthy ? "Healthy" : "Offline"} {status?.summarizer.probeLatencyMs != null ? `${status.summarizer.probeLatencyMs} ms probe` : status?.summarizer.healthLatencyMs != null ? `${status.summarizer.healthLatencyMs} ms health` : "No latency data"} Storage Data root: {status?.storage.dataRoot || "-"} DB path: {status?.storage.dbPath || "-"} Companies: {status?.storage.companyCount ?? 0} Jobs: {status?.storage.jobCount ?? 0} Deleted jobs: {status?.storage.deletedCount ?? 0} Content root: {status?.contentRoot || "-"} Email From: {status?.email.from || "-"} From name: {status?.email.fromName || "-"} Host: {status?.email.host || "-"} Port: {status?.email.port ?? "-"} SSL: {status?.email.enableSsl ? "Yes" : "No"} Summarizer telemetry Requests {status?.summarizer.requests ?? 0} Cache hits {status?.summarizer.cacheHits ?? 0} Failures {status?.summarizer.failures ?? 0} Avg latency {status?.summarizer.averageLatencyMs != null ? `${status.summarizer.averageLatencyMs} ms` : "-"} Probe latency {status?.summarizer.probeLatencyMs != null ? `${status.summarizer.probeLatencyMs} ms` : "-"} Probe failures: {status?.summarizer.probeFailures ?? 0} {status?.summarizer.lastError ? {status.summarizer.lastError} : null} ); }