"use client"; import { useState, useEffect, useRef } from "react"; import Link from "next/link"; import { ArrowLeft, Server, Activity, Database, HardDrive, DownloadCloud, ShieldAlert, UploadCloud, Loader2, CheckCircle2 } from "lucide-react"; import { getSystemMetrics, exportDatabase, restoreDatabase } from "./actions"; import { useHqUi } from "@/components/hq/Toast"; export default function SystemHealth() { const ui = useHqUi(); const [metrics, setMetrics] = useState(null); const [isExporting, setIsExporting] = useState(false); // Restore State const [isRestoring, setIsRestoring] = useState(false); const [restoreError, setRestoreError] = useState(""); const [restoreSuccess, setRestoreSuccess] = useState(false); const [selectedFile, setSelectedFile] = useState(null); const fileInputRef = useRef(null); const fetchMetrics = async () => { const res = await getSystemMetrics(); if (res.success) setMetrics(res); }; useEffect(() => { fetchMetrics(); // Actualizar métricas cada 10 segundos const interval = setInterval(fetchMetrics, 10000); return () => clearInterval(interval); }, []); const formatUptime = (seconds: number) => { const d = Math.floor(seconds / (3600 * 24)); const h = Math.floor(seconds % (3600 * 24) / 3600); const m = Math.floor(seconds % 3600 / 60); return `${d}d ${h}h ${m}m`; }; const handleExport = async () => { setIsExporting(true); const res = await exportDatabase(); if (res.success && res.data) { // Crear un Blob y forzar la descarga del JSON const blob = new Blob([res.data], { type: "application/json" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `flux-db-snapshot-${new Date().toISOString().split('T')[0]}.json`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } else { ui.toast(res.error || "Export failed.", "error"); } setIsExporting(false); }; const handleRestore = async (e: React.FormEvent) => { e.preventDefault(); if (!selectedFile) return setRestoreError("Please select a JSON backup file."); setIsRestoring(true); setRestoreError(""); try { const reader = new FileReader(); reader.onload = async (event) => { const jsonString = event.target?.result as string; const formData = new FormData(e.currentTarget as HTMLFormElement); formData.append("jsonString", jsonString); const res = await restoreDatabase(formData); if (res.error) { setRestoreError(res.error); } else { setRestoreSuccess(true); // Recargar para forzar la re-lectura de la BD setTimeout(() => window.location.href = "/hq-command/dashboard", 3000); } setIsRestoring(false); }; reader.readAsText(selectedFile); } catch (error) { setRestoreError("Failed to read the file."); setIsRestoring(false); } }; return (
{/* HEADER */}
Back to Command Center

System Health & Vault

Server telemetry, data snapshots, and disaster recovery protocols.

{/* TELEMETRÍA (MÉTRICAS) */}
Node.js Uptime

{metrics ? formatUptime(metrics.uptime) : "Loading..."}

Heap Memory Usage

{metrics ? `${metrics.memory.used} MB ` : "0 MB "} / {metrics ? metrics.memory.total : 0} MB

Postgres Connection

{metrics ? metrics.dbStatus : "Connecting..."}

{/* ZONA VERDE: EXPORTAR (BACKUP) */}

Data Snapshot

Download a complete JSON snapshot of your PostgreSQL database. This file contains all configurations, users, and content needed to perfectly clone or restore your environment via Docker.

{/* ZONA ROJA: RESTAURAR (DANGER ZONE) */}
{restoreSuccess ? (

Restoration Complete

The database has been successfully overwritten. Rebooting session...

) : ( <>

Disaster Recovery

WARNING: Uploading a snapshot will instantaneously erase all current database records and overwrite them. This process is irreversible.

{selectedFile ? selectedFile.name : "No backup selected"} setSelectedFile(e.target.files?.[0] || null)} className="hidden" />
{restoreError &&
{restoreError}
}
)}
); }