'use client'; import { useEffect, useMemo, useState } from 'react'; import { Chrome, Loader2, Save, Settings2, ToggleLeft, ToggleRight } from 'lucide-react'; import { useAuth } from '@/components/id/auth-provider'; import { AdminShell } from '@/components/id/admin-shell'; import { usePublicSettings } from '@/components/id/public-settings-provider'; import { useToast } from '@/components/id/toast-provider'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { apiFetch, buildSystemSettingPayload, SocialProvider, SystemSetting } from '@/lib/api'; import { getSettingMeta, sortSettingsByCatalog, SYSTEM_SETTING_GROUPS } from '@/lib/system-settings-catalog'; function parseBoolean(value: string) { return ['true', '1', 'yes'].includes(value.trim().toLowerCase()); } export default function AdminSettingsPage() { const { token, user } = useAuth(); const { showToast } = useToast(); const { refreshPublicSettings } = usePublicSettings(); const [settings, setSettings] = useState([]); const [providers, setProviders] = useState([]); const [loading, setLoading] = useState(true); const [savingKey, setSavingKey] = useState(null); useEffect(() => { if (!token || !user?.canManageSettings) return; Promise.all([ apiFetch<{ settings: SystemSetting[] }>('/admin/settings', {}, token), apiFetch<{ providers: SocialProvider[] }>('/admin/settings/oauth/providers', {}, token) ]) .then(([settingsResponse, providersResponse]) => { setSettings(sortSettingsByCatalog(settingsResponse.settings ?? [])); setProviders(providersResponse.providers ?? []); }) .catch((error) => showToast(error instanceof Error ? error.message : 'Не удалось загрузить настройки')) .finally(() => setLoading(false)); }, [showToast, token, user?.canManageSettings]); const groupedSettings = useMemo(() => { const groups = new Map(); for (const setting of settings) { const meta = getSettingMeta(setting.key); const group = meta?.group ?? 'other'; const list = groups.get(group) ?? []; list.push(setting); groups.set(group, list); } return groups; }, [settings]); async function saveSetting(setting: SystemSetting) { if (!token) return; setSavingKey(setting.key); try { const updated = await apiFetch( '/admin/settings', { method: 'PUT', body: JSON.stringify(buildSystemSettingPayload(setting)) }, token ); setSettings((current) => sortSettingsByCatalog(current.map((item) => (item.key === updated.key ? updated : item)))); if (updated.key === 'PROJECT_NAME' || updated.key === 'PROJECT_TAGLINE' || updated.key === 'LDAP_ENABLED' || updated.key === 'LDAP_USE_LDAPS') { await refreshPublicSettings(); } showToast('Настройка сохранена'); } catch (error) { showToast(error instanceof Error ? error.message : 'Не удалось сохранить настройку'); } finally { setSavingKey(null); } } function updateSettingValue(key: string, value: string) { setSettings((current) => current.map((item) => (item.key === key ? { ...item, value } : item))); } function toProviderPayload(provider: SocialProvider) { return { providerName: provider.providerName, clientId: provider.clientId, isEnabled: provider.isEnabled }; } async function toggleProvider(provider: SocialProvider) { if (!token) return; try { const updated = await apiFetch('/admin/settings/oauth/providers', { method: 'PUT', body: JSON.stringify({ ...toProviderPayload(provider), isEnabled: !provider.isEnabled }) }, token); setProviders((current) => current.map((item) => (item.providerName === updated.providerName ? updated : item))); showToast(updated.isEnabled ? 'Провайдер включён' : 'Провайдер отключён'); } catch (error) { showToast(error instanceof Error ? error.message : 'Не удалось обновить провайдера'); } } if (!user?.canManageSettings) { return (

У вас нет прав на изменение глобальных настроек.

); } return (

Глобальные настройки

Параметры хранятся в SystemSetting и применяются сервисами без релиза frontend.

{loading ? (
Загрузка...
) : ( <> {[...groupedSettings.entries()].map(([groupKey, groupSettings]) => (

{SYSTEM_SETTING_GROUPS[groupKey] ?? 'Прочие настройки'}

{groupSettings.map((setting) => { const meta = getSettingMeta(setting.key); const label = meta?.label ?? setting.key; const type = meta?.type ?? 'text'; return (
{label}

{meta?.hint ?? setting.description ?? setting.key}

{type === 'boolean' ? ( ) : (
updateSettingValue(setting.key, event.target.value)} /> {meta?.unit ? {meta.unit} : null}
)}
); })}
))}

OAuth Social Providers

{(providers.length ? providers : [{ id: 'google', providerName: 'google', clientId: '', isEnabled: false }, { id: 'yandex', providerName: 'yandex', clientId: '', isEnabled: false }]).map((provider) => (
{provider.providerName === 'google' ? :
Я
}

{provider.providerName}

{provider.isEnabled ? 'Провайдер включен глобально.' : 'Провайдер отключен.'}

setProviders((current) => current.map((item) => (item.providerName === provider.providerName ? { ...item, clientId: event.target.value } : item)))} />
))}
)}
); }