import React, { useEffect, useMemo, useState } from "react"; import { Alert, Box, Button, Chip, Paper, Stack, Typography, } from "@mui/material"; import { api } from "../api"; type SummarizerMetrics = { healthy: boolean; model?: string | null; device?: string | null; gpuAvailable?: boolean; gpuName?: 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; lastSuccessAt?: string | null; lastFailureAt?: string | 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; }; database: { provider: string; looksConfigured: boolean; canConnect: boolean; target?: string | null; usesFileStorage: boolean; warning?: string | null; }; runtime: { framework: string; osDescription: string; processArchitecture: string; machineName?: string | null; }; auth: { required: boolean; hasJwtKey: boolean; googleConfigured: boolean; gmailConfigured: boolean; }; 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 : "-"; } function formatDate(value?: string | null) { return value ? new Date(value).toLocaleString() : "-"; } function SummaryCard({ title, value, subtitle, tone = "default" }: { title: string; value: string; subtitle?: string; tone?: "default" | "success" | "warning" | "error" }) { const color = tone === "success" ? "success.main" : tone === "warning" ? "warning.main" : tone === "error" ? "error.main" : "text.primary"; return ( {title} {value} {subtitle || "-"} ); } function DetailRow({ label, value }: { label: string; value: React.ReactNode }) { return {label}: {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(); }, []); const dbTone = useMemo(() => { if (!status) return "default" as const; if (!status.database.looksConfigured || !status.database.canConnect) return "error" as const; if (status.database.warning) return "warning" as const; return "success" as const; }, [status]); const summarizerTone = useMemo(() => { if (!status) return "default" as const; if (!status.summarizer.healthy) return "error" as const; if (status.summarizer.probeFailures > 0 || status.summarizer.failures > 0) return "warning" as const; return "success" as const; }, [status]); return ( System status Production diagnostics for runtime, database, auth, email, and summarizer health. {error ? {error} : null} {status?.database.warning ? {status.database.warning} : null} {status?.summarizer.lastError ? {status.summarizer.lastError} : null} Database and storage Runtime and auth Email configuration Summarizer runtime Summarizer telemetry Requests{status?.summarizer.requests ?? 0} Cache hits{status?.summarizer.cacheHits ?? 0} Cache misses{status?.summarizer.cacheMisses ?? 0} Failures{status?.summarizer.failures ?? 0} Probe failures{status?.summarizer.probeFailures ?? 0} Avg latency{status?.summarizer.averageLatencyMs != null ? `${status.summarizer.averageLatencyMs} ms` : "-"} ); }