import React, { useMemo, useState } from 'react'; import { api } from '../api.js'; import { flagFor } from '../utils/country.js'; import { formatRelative } from '../utils/format.js'; function PingCell({ ping }) { if (!ping) return ; if (ping.checking) return проверяем…; if (!ping.ok) return offline; const ms = ping.latency; const kind = ms < 80 ? 'success' : ms < 200 ? 'warning' : 'danger'; return {ms} ms; } function StatusCell({ ping }) { if (!ping) return unknown; if (ping.checking) return ; return ping.ok ? ● online : ● offline; } export function ServersPage({ state, servers, selectedTag, setSelectedTag, pendingTag, setPendingTag, busy, onApply, onRollback, pings, setPings, pushToast, }) { const [filter, setFilter] = useState('all'); // all | online const [search, setSearch] = useState(''); async function pingOne(server) { setPings((prev) => ({ ...prev, [server.tag]: { checking: true } })); try { const res = await api.servers.ping(server.server, server.server_port); setPings((prev) => ({ ...prev, [server.tag]: { ok: res.ok, latency: res.latency, error: res.error, checkedAt: new Date().toISOString() }, })); } catch (err) { setPings((prev) => ({ ...prev, [server.tag]: { ok: false, error: err.message } })); } } async function pingAll() { setPings((prev) => { const next = { ...prev }; for (const s of servers) next[s.tag] = { checking: true }; return next; }); try { const res = await api.servers.pingAll(); const map = {}; for (const r of res.results || []) { map[r.tag] = { ok: r.ok, latency: r.latency, error: r.error, checkedAt: r.checkedAt }; } setPings((prev) => ({ ...prev, ...map })); pushToast({ kind: 'success', title: 'Пинг завершён' }); } catch (err) { pushToast({ kind: 'danger', title: 'Ошибка пинга', message: err.message }); } } const filtered = useMemo(() => { return servers.filter((s) => { if (search && !s.tag.toLowerCase().includes(search.toLowerCase()) && !s.server.toLowerCase().includes(search.toLowerCase())) { return false; } if (filter === 'online' && !pings[s.tag]?.ok) return false; return true; }); }, [servers, search, filter, pings]); const pendingDifferent = pendingTag && pendingTag !== state?.selectedTag; const activeServer = servers.find((s) => s.tag === state?.selectedTag); const pendingServer = servers.find((s) => s.tag === pendingTag); if (!servers.length) { return (

Серверы ещё не загружены

Загрузите подписку в разделе «Настройки», чтобы получить список серверов.

); } return (
{pendingDifferent && (
Выбран: {flagFor(pendingServer)} {pendingServer?.tag}
Текущий: {state?.selectedTag ? `${flagFor(activeServer)} ${state.selectedTag}` : 'нет'}
)}

Серверы ({servers.length})

{state?.previousTag && ( )}
setSearch(e.target.value)} />
{filtered.map((server) => { const isActive = server.tag === state?.selectedTag; const isPending = server.tag === pendingTag && !isActive; const ping = pings[server.tag]; return ( ); })} {!filtered.length && ( )}
Сервер Хост Тип Ping Статус Действие
{flagFor(server)}
{server.tag} {isActive && ACTIVE} {isPending && pending}
{server.server}:{server.server_port} {server.type}
{isActive ? ( ) : ( )}
Ничего не найдено
); }