/** * Settings Page Component * Full-page settings dashboard with server control, proxy, auth, ports */ import { useState } from 'react'; import { useQuery } from '@tanstack/react-query'; import { RefreshCw, Server, Shield, Network, Activity, Key, Loader2, CheckCircle, AlertCircle } from 'lucide-react'; import { useI18n } from '@/contexts'; import { ProxySettings } from './ProxySettings'; import { AuthManager } from './AuthManager'; import { PortConfiguration } from './PortConfig'; import styles from './SettingsPage.module.css'; // API functions async function fetchServerStatus() { const response = await fetch('/api/server/status'); if (!response.ok) throw new Error('Failed to fetch server status'); return response.json(); } async function fetchApiKeys() { const response = await fetch('/api/keys'); if (!response.ok) throw new Error('Failed to fetch API keys'); return response.json(); } async function addApiKey(key: string) { const response = await fetch('/api/keys', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key }), }); if (!response.ok) throw new Error('Failed to add API key'); return response.json(); } async function deleteApiKey(key: string) { const response = await fetch('/api/keys', { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key }), }); if (!response.ok) throw new Error('Failed to delete API key'); return response.json(); } interface ServerStatus { status: string; uptime_seconds: number; uptime_formatted: string; launch_mode: string; server_port: number; stream_port: number; version: string; python_version: string; started_at: string; } export function SettingsPage() { const { t } = useI18n(); return (

{t.settingsPage.title}

{/* Minimal Status Bar */} {/* API Keys */} {/* Proxy Settings */}

{t.settingsPage.proxySettings}

{t.settingsPage.proxyDesc}

{/* Auth Management */}

{t.settingsPage.authManagement}

{t.settingsPage.authDesc}

{/* Port Configuration */}

{t.settingsPage.portConfig}

{t.settingsPage.portDesc}

); } function StatusBar() { const { t } = useI18n(); const { data: status, isLoading } = useQuery({ queryKey: ['serverStatus'], queryFn: fetchServerStatus, refetchInterval: 10000, }); if (isLoading) { return (
{t.settingsPage.loading}
); } return (
{status?.status || t.common.unknown} {status?.uptime_formatted || '-'} {t.settingsPage.port} {status?.server_port || '-'} {status?.launch_mode || '-'}
); } function ApiKeysSection() { const { t } = useI18n(); const { data, isLoading, refetch } = useQuery<{ keys: string[] }>({ queryKey: ['apiKeys'], queryFn: fetchApiKeys, }); const [newKey, setNewKey] = useState(''); const [adding, setAdding] = useState(false); const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const handleAdd = async () => { if (!newKey.trim()) return; setAdding(true); setMessage(null); try { await addApiKey(newKey.trim()); setNewKey(''); setMessage({ type: 'success', text: t.settingsPage.keyAdded }); refetch(); } catch { setMessage({ type: 'error', text: t.settingsPage.addFailed }); } finally { setAdding(false); } }; const handleDelete = async (key: string) => { const confirmMsg = t.settingsPage.confirmDelete.replace('{key}', key.substring(0, 8)); if (!confirm(confirmMsg)) return; try { await deleteApiKey(key); setMessage({ type: 'success', text: t.settingsPage.keyDeleted }); refetch(); } catch { setMessage({ type: 'error', text: t.settingsPage.deleteFailed }); } }; if (isLoading) { return (

{t.settingsPage.apiKeys}

); } return (

{t.settingsPage.apiKeys}

{t.settingsPage.apiKeysDesc}

{data?.keys?.length ? ( data.keys.map((key) => (
{key.substring(0, 16)}...
)) ) : (
{t.settingsPage.noApiKeys}
)}
setNewKey(e.target.value)} placeholder={t.settingsPage.enterNewKey} />
{message && (
{message.type === 'success' ? : } {message.text}
)}
); }