import { useMemo } from "react"; import { useAdminOverview } from "~/shared/services/admin"; import { Section, Badge, InfoRow } from "../components"; import { useAdminContext } from "../context"; import { formatBytes, formatDate, formatUnknown, numberFormatter } from "../utils/format"; export const AdminOverviewPage = () => { const { isAuthorized, handleRequestError } = useAdminContext(); const overviewQuery = useAdminOverview({ enabled: isAuthorized, retry: false, refetchInterval: 60_000, onError: (error) => { handleRequestError(error, "Не удалось загрузить обзор"); }, }); const overviewCards = useMemo(() => { const data = overviewQuery.data; if (!data) { return []; } const { project, content, node, ipfs, codebase, runtime } = data; return [ { label: "Хост", value: project.host || "локальный", helper: project.name, }, { label: "TON Master", value: node.ton_master, helper: "Платформа", }, { label: "Service Wallet", value: node.service_wallet, helper: node.id, }, { label: "Контент", value: `${numberFormatter.format(content.encrypted_total)} зашифр.`, helper: `${numberFormatter.format(content.derivatives_ready)} деривативов`, }, { label: "IPFS Repo", value: formatBytes(Number((ipfs.repo as Record)?.RepoSize ?? 0)), helper: "Размер репозитория", }, { label: "Bitswap", value: numberFormatter.format(Number((ipfs.bitswap as Record)?.Peers ?? 0)), helper: "Пиры", }, { label: "Билд", value: codebase.commit ?? "n/a", helper: codebase.branch ?? "", }, { label: "Python", value: runtime.python, helper: runtime.implementation, }, ]; }, [overviewQuery.data]); if (!overviewQuery.data) { return overviewQuery.isLoading ? (
Загрузка…
) : null; } const { project, services, ton, runtime, ipfs } = overviewQuery.data; return (
overviewQuery.refetch()} disabled={overviewQuery.isFetching} > {overviewQuery.isFetching ? "Обновляем…" : "Обновить"} } >
{overviewCards.map((card) => (

{card.label}

{card.value}

{card.helper ?

{card.helper}

: null}
))}

Проект

{project.host || "—"} {project.name} {project.privacy} {ton.testnet ? "Да" : "Нет"} {ton.api_key_configured ? "Настроен" : "Нет"} {ton.host || "—"}

Среда выполнения

{runtime.python} {runtime.implementation} {runtime.platform} {formatDate(runtime.utc_now)}

IPFS

{formatUnknown((ipfs.identity as Record)?.ID)} {formatUnknown((ipfs.identity as Record)?.AgentVersion)} {numberFormatter.format(Number((ipfs.bitswap as Record)?.Peers ?? 0))} {formatBytes(Number((ipfs.repo as Record)?.RepoSize ?? 0))} {formatBytes(Number((ipfs.repo as Record)?.StorageMax ?? 0))}

Сервисы

    {services.length === 0 ? (
  • Нет зарегистрированных сервисов
  • ) : ( services.map((service) => { const status = service.status ?? "—"; const tone: "success" | "warn" | "danger" | "neutral" = status.includes("working") ? "success" : status.includes("timeout") ? "danger" : "neutral"; return (
  • {service.name}
    {service.last_reported_seconds != null ? `Обновлён ${Math.round(service.last_reported_seconds)} сек назад` : "Нет данных"} {status}
  • ); }) )}
); };