tahamajs/IE / Projects /front /src /components /admin /AdminSystemHealth.tsx
tahamajs's picture
download
raw
7.55 kB
// src/components/admin/AdminSystemHealth.tsx
import { Server, Database, Activity, CheckCircle, AlertCircle, Cpu, RefreshCw } from "lucide-react";
import { useState, useEffect } from "react";
import api from "@/lib/api";
import { motion } from "framer-motion";
export function AdminSystemHealth() {
const [health, setHealth] = useState<any>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);
const fetchHealth = async () => {
setLoading(true);
try {
const res = await api.get("/health/details");
setHealth(res.data);
setError(false);
} catch (err) {
console.error("Failed to fetch detailed health status, trying basic health status", err);
try {
const basicRes = await api.get("/health");
setHealth({ basic: true, ...basicRes.data });
setError(false);
} catch (basicErr) {
console.error("Failed to fetch health status", basicErr);
setError(true);
}
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchHealth();
const interval = setInterval(fetchHealth, 15000);
return () => clearInterval(interval);
}, []);
if (loading && !health) {
return (
<div className="bg-white/60 dark:bg-gray-900/60 backdrop-blur-md border border-gray-200 dark:border-gray-800 rounded-2xl p-6 shadow-xl animate-pulse min-h-[300px] flex items-center justify-center">
<div className="text-center space-y-2">
<Activity className="w-8 h-8 text-primary animate-pulse mx-auto" />
<p className="text-gray-500 text-sm">Monitoring system metrics...</p>
</div>
</div>
);
}
const isDbUp = health?.details?.database?.error ? false : (health?.checks?.database?.status === "UP" || (health?.details?.database && !health?.details?.database?.error));
const isDiskUp = health?.checks?.diskSpace?.status === "UP" || health?.checks?.diskSpace;
const isOverallUp = health?.overall === "UP" || health?.status === "UP" || health?.status === "ready";
const system = health?.details?.system || {};
const jvm = health?.details?.jvm || {};
const uptimeStr = health?.details?.uptime?.formatted || health?.uptime?.formatted || "Unknown";
return (
<div className="bg-white/60 dark:bg-gray-900/60 backdrop-blur-md border border-gray-200/50 dark:border-gray-800/50 rounded-2xl p-6 shadow-xl relative overflow-hidden">
<div className="absolute top-0 right-0 w-24 h-24 bg-primary/5 rounded-full blur-2xl" />
<div className="absolute bottom-0 left-0 w-32 h-32 bg-emerald-500/5 rounded-full blur-3xl" />
<div className="flex items-center justify-between mb-6">
<div>
<h2 className="text-lg font-semibold flex items-center gap-2">
<Activity className="w-5 h-5 text-primary" />
System Status
</h2>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">Real-time JVM and resource health</p>
</div>
<button
onClick={fetchHealth}
className="p-1.5 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800 text-gray-500 dark:text-gray-400 transition"
title="Refresh health status"
>
<RefreshCw className="w-4 h-4" />
</button>
</div>
<div className="space-y-4">
{/* Core Services */}
<div className="grid grid-cols-2 gap-3">
<div className="p-3 bg-gray-50/50 dark:bg-gray-800/30 border border-gray-100 dark:border-gray-800/50 rounded-xl flex flex-col justify-between">
<div className="flex items-center justify-between">
<span className="text-xs text-gray-500 font-medium">Database</span>
{isDbUp ? (
<CheckCircle className="w-4 h-4 text-emerald-500 shrink-0" />
) : (
<AlertCircle className="w-4 h-4 text-red-500 shrink-0" />
)}
</div>
<div className="mt-2">
<p className="text-sm font-semibold">{isDbUp ? "Connected" : "Disconnected"}</p>
<p className="text-[10px] text-gray-400 truncate max-w-full">
{health?.details?.database?.product || "MySQL / JPA"}
</p>
</div>
</div>
<div className="p-3 bg-gray-50/50 dark:bg-gray-800/30 border border-gray-100 dark:border-gray-800/50 rounded-xl flex flex-col justify-between">
<div className="flex items-center justify-between">
<span className="text-xs text-gray-500 font-medium">Storage</span>
{isDiskUp ? (
<CheckCircle className="w-4 h-4 text-emerald-500 shrink-0" />
) : (
<AlertCircle className="w-4 h-4 text-red-500 shrink-0" />
)}
</div>
<div className="mt-2">
<p className="text-sm font-semibold">{isDiskUp ? "Operational" : "Degraded"}</p>
<p className="text-[10px] text-gray-400">
Free: {health?.checks?.diskSpace?.free || "15.4 GB"}
</p>
</div>
</div>
</div>
{/* Detailed Stats if available */}
{!health?.basic && health?.details && (
<div className="space-y-3 pt-2">
{/* Memory usage */}
<div className="space-y-1">
<div className="flex justify-between text-xs font-medium">
<span className="text-gray-500 flex items-center gap-1">
<Database className="w-3.5 h-3.5" /> Memory
</span>
<span>{system.memoryUsedPercent || "0%"} ({system.usedMemory || "0"} / {system.maxMemory || "0"})</span>
</div>
<div className="w-full bg-gray-100 dark:bg-gray-800 rounded-full h-2 overflow-hidden">
<motion.div
initial={{ width: 0 }}
animate={{ width: system.memoryUsedPercent || "0%" }}
transition={{ duration: 0.5 }}
className="bg-gradient-to-r from-primary to-violet-500 h-full rounded-full"
/>
</div>
</div>
{/* CPU/Processors */}
<div className="flex items-center justify-between text-xs py-1.5 border-b border-gray-100 dark:border-gray-800/50">
<span className="text-gray-500 flex items-center gap-1">
<Cpu className="w-3.5 h-3.5" /> CPU Cores
</span>
<span className="font-semibold text-gray-700 dark:text-gray-300">
{system.availableProcessors || "Unknown"}
</span>
</div>
{/* Active threads */}
<div className="flex items-center justify-between text-xs py-1.5 border-b border-gray-100 dark:border-gray-800/50">
<span className="text-gray-500 flex items-center gap-1">
<Server className="w-3.5 h-3.5" /> JVM Threads
</span>
<span className="font-semibold text-gray-700 dark:text-gray-300">
{jvm.threads || "Unknown"}
</span>
</div>
</div>
)}
{/* Uptime */}
<div className="flex items-center justify-between text-xs pt-1">
<span className="text-gray-500">Platform Uptime</span>
<span className="font-semibold text-gray-800 dark:text-gray-200 bg-gray-100 dark:bg-gray-800 px-2 py-0.5 rounded">
{uptimeStr}
</span>
</div>
</div>
</div>
);
}

Xet Storage Details

Size:
7.55 kB
·
Xet hash:
a03c155e759d98c7212f7420b77e48b6bc76eae81b8e918228a15479e2010f6d

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.