import { useQuery } from '@tanstack/react-query'; import { useTranslation } from 'react-i18next'; import { fetchAudit, fetchInstanceGuilds, fetchInstanceSettings, fetchInstanceUsers, instanceAuditQueryKey, instanceGuildsQueryKey, instanceSettingsQueryKey, instanceUsersQueryKey, } from '@/api/instance'; import { InstanceDashboard } from '@/components/instance/InstanceDashboard'; import { InstanceHealth } from '@/components/instance/InstanceHealth'; import { ErrorNotice, LoadingNotice } from '@/components/ui/ErrorNotice'; import { Card } from '@/components/ui/primitives'; import { formatDateTime } from '@/lib/identity'; import { useCurrentUser } from '@/lib/hooks'; import { useInstanceMetrics } from '@/lib/useInstanceMetrics'; const AUDIT_LIMIT = 50; /** Админский раздел инстанса: настройки, серверы, пользователи, аудит (read-only). */ export default function InstanceSettingsPage() { const { t, i18n } = useTranslation(); const locale = i18n.resolvedLanguage ?? 'ru'; const currentUser = useCurrentUser(); const isAdmin = currentUser.data?.is_instance_admin === true; const settings = useQuery({ queryKey: instanceSettingsQueryKey, queryFn: ({ signal }) => fetchInstanceSettings(signal), enabled: isAdmin, retry: 0, }); const guilds = useQuery({ queryKey: instanceGuildsQueryKey, queryFn: ({ signal }) => fetchInstanceGuilds(signal), enabled: isAdmin, retry: 0, }); const users = useQuery({ queryKey: instanceUsersQueryKey, queryFn: ({ signal }) => fetchInstanceUsers(signal), enabled: isAdmin, retry: 0, }); const audit = useQuery({ queryKey: instanceAuditQueryKey(AUDIT_LIMIT), queryFn: ({ signal }) => fetchAudit(AUDIT_LIMIT, signal), enabled: isAdmin, retry: 0, }); // Живые метрики: опрос раз в секунду, пока раздел открыт (AGENT.md 7.19). const metrics = useInstanceMetrics(isAdmin); if (!isAdmin) { return (

{t('settings.instance.title')}

{t('settings.instance.notAdmin')}

); } const settingsEntries = settings.data === undefined ? [] : Object.entries(settings.data).slice(0, 30); return (

{t('settings.instance.title')}

{t('settings.instance.description')}

{t('settings.instance.settings')}

{settings.isPending ? : null} {settings.isError ? ( void settings.refetch()} /> ) : null} {!settings.isPending && !settings.isError && settingsEntries.length === 0 ? (

{t('settings.instance.settingsEmpty')}

) : null} {settingsEntries.length === 0 ? null : (
{settingsEntries.map(([key, value]) => (
{key}
{format(value)}
))}
)}

{t('settings.instance.guilds', { count: guilds.data?.length ?? 0 })}

{guilds.isPending ? : null} {guilds.isError ? ( void guilds.refetch()} /> ) : null} {guilds.data !== undefined && guilds.data.length === 0 ? (

{t('settings.instance.guildsEmpty')}

) : null} {guilds.data === undefined || guilds.data.length === 0 ? null : (
    {guilds.data.map((guild) => (
  • {guild.name} {guild.is_main ? `${t('settings.instance.mainBadge')} · ` : ''} {t('settings.instance.memberCount', { count: guild.member_count })}
  • ))}
)}

{t('settings.instance.users', { count: users.data?.length ?? 0 })}

{/* ID пользователей — единственное место, где он виден: раздел открыт только администратору инстанса. */}

{t('settings.instance.usersIdHint')}

{users.isPending ? : null} {users.isError ? ( void users.refetch()} /> ) : null} {users.data !== undefined && users.data.length === 0 ? (

{t('settings.instance.usersEmpty')}

) : null} {users.data === undefined || users.data.length === 0 ? null : (
    {users.data.map((user) => (
  • {user.display_name} @{user.username} {user.id} {user.is_instance_admin ? ( {t('settings.instance.adminBadge')} ) : null}
  • ))}
)}

{t('settings.instance.audit', { count: audit.data?.length ?? 0 })}

{audit.isPending ? : null} {audit.isError ? ( void audit.refetch()} /> ) : null} {audit.data !== undefined && audit.data.length === 0 ? (

{t('settings.instance.auditEmpty')}

) : null} {audit.data === undefined || audit.data.length === 0 ? null : (
    {audit.data.map((entry) => (
  • {entry.action} {entry.target === undefined ? '' : ` → ${entry.target}`} {formatDateTime(entry.created_at, locale)}
  • ))}
)}
); } function format(value: unknown): string { if (value === null || value === undefined) { return '—'; } if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return String(value); } try { return JSON.stringify(value); } catch { return '—'; } }