import FormField from './FormField'; import { useEffect, useState } from 'react'; import api from '../lib/api.js'; import { IconSettings, IconDeviceFloppy } from '@tabler/icons-react'; import ErrorAlert from './ErrorAlert'; /** * SettingsModal - модальное окно настроек интерфейса * Простой подход со встроенным backdrop (как в HistoryModal) */ export default function SettingsModal({ open, onClose }) { const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); const [etag, setEtag] = useState(''); const [dohServer, setDohServer] = useState(''); const [wsUrl, setWsUrl] = useState(''); useEffect(() => { if (!open) return; setError(''); setSuccess(''); setLoading(true); (async () => { try { const res = await api.get('/ui-settings'); const data = res?.data || {}; setDohServer(String(data?.dohServer || '')); setWsUrl(String(data?.wsUpdateUrl || '')); const e = res?.headers?.etag || res?.headers?.ETag || ''; setEtag(e ? String(e) : ''); } catch (e) { setError('Не удалось загрузить настройки'); } finally { setLoading(false); } })(); }, [open]); if (!open) return null; const validateDoh = (value) => { if (!value) return { valid: true, message: '' }; try { const u = new URL(String(value)); return u.protocol === 'https:' ? { valid: true, message: 'Корректный HTTPS URL' } : { valid: false, message: 'Используйте HTTPS' }; } catch { return { valid: false, message: 'Некорректный URL' }; } }; const validateWs = (value) => { if (!value) return { valid: true, message: '' }; try { const u = new URL(String(value)); return u.protocol === 'ws:' || u.protocol === 'wss:' ? { valid: true, message: 'Корректный WebSocket URL' } : { valid: false, message: 'Используйте ws:// или wss://' }; } catch { return { valid: false, message: 'Некорректный URL' }; } }; const onSave = async () => { setError(''); setSuccess(''); const dohValidation = validateDoh(dohServer); const wsValidation = validateWs(wsUrl); if (!dohValidation.valid) { setError('Укажите корректный HTTPS URL для DoH'); return; } if (!wsValidation.valid) { setError('Укажите корректный WebSocket URL (ws:// или wss://)'); return; } setSaving(true); try { const payload = { settings: { dohServer: String(dohServer || '').trim(), wsUpdateUrl: String(wsUrl || '').trim() }, etag }; const res = await api.post('/ui-settings', payload); const meta = res?.data || {}; setSuccess('Настройки успешно сохранены'); setEtag(String(meta?.etag || '')); setTimeout(() => setSuccess(''), 3000); } catch (e) { setError(e?.response?.data?.message || 'Ошибка при сохранении настроек'); } finally { setSaving(false); } }; return (
{ if (e.key === 'Escape') onClose?.(); }} >
Настройки интерфейса
{error && setError('')} />} {success && (
{success}
)}
); }