// Servers screen — VPN server monitoring
const { useState: useStateSv, useEffect: useEffectSv } = React;
function ServerCard({ server }) {
const statusCfg = {
ok: { dot: "bg-[#22c55e]", label: "В сети", labelColor: "text-[#22c55e]", bg: "border-[#22c55e]/20" },
high: { dot: "bg-[#eab308]", label: "Высокая нагрузка", labelColor: "text-[#eab308]", bg: "border-[#eab308]/20" },
down: { dot: "bg-[#ef4444]", label: "Недоступен", labelColor: "text-[#ef4444]", bg: "border-[#ef4444]/20" },
}[server.status] || { dot: "bg-zinc-500", label: "Неизвестно", labelColor: "text-zinc-400", bg: "" };
return (
{server.name}
{statusCfg.label}
Нагрузка
{server.load != null ? server.load + "%" : "—"}
Пинг
{server.ping != null ? server.ping + " мс" : "—"}
Uptime
{server.uptime != null ? server.uptime + "%" : "—"}
{server.location && (
📍 {server.location}
)}
);
}
function ServersScreen() {
const [data, setData] = useStateSv({ servers: [], last_updated: null });
const [loading, setLoading] = useStateSv(true);
function load() {
setLoading(true);
window.apiFetch("GET", "/api/servers")
.then((d) => { setData(d); setLoading(false); })
.catch(() => setLoading(false));
}
useEffectSv(() => { load(); }, []);
const servers = data.servers || [];
const online = servers.filter((s) => s.status === "ok").length;
const high = servers.filter((s) => s.status === "high").length;
const down = servers.filter((s) => s.status === "down").length;
return (
{/* Stub mode banner */}
{data.is_stub && (
⚠
Тестовый режим
— показаны случайные данные. Настройте переменную SERVERS в .env для мониторинга реальных серверов.
)}
{/* Header */}
Серверы VPN
{data.last_updated ? `Обновлено: ${data.last_updated}` : "Ожидание первой проверки..."}
{/* Summary */}
{servers.length > 0 && (
)}
{/* Server grid */}
{loading && (
Загрузка...
)}
{!loading && servers.length === 0 && (
Серверы не настроены
Добавьте серверы в .env через переменную SERVERS и задайте SERVERS_MONITOR_TYPE=tcp
)}
{!loading && servers.length > 0 && (
{servers.map((s) => )}
)}
);
}
Object.assign(window, { ServersScreen });