import { useEffect, useRef, useState } from 'react' import { useLanguage } from '../contexts/LanguageContext' interface AdvancedConfigPageProps { onBack: () => void serverRunning: boolean } interface ModelMappingRow { id: string source: string target: string } function createModelMappingRow(source = '', target = ''): ModelMappingRow { return { id: `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`, source, target, } } function toRows(modelMappings: Record): ModelMappingRow[] { return Object.entries(modelMappings).map(([source, target]) => createModelMappingRow(source, target), ) } export default function AdvancedConfigPage({ onBack, serverRunning }: AdvancedConfigPageProps) { const { t } = useLanguage() const translationRef = useRef(t) const [configPath, setConfigPath] = useState('') const [rows, setRows] = useState([]) const [loading, setLoading] = useState(true) const [saving, setSaving] = useState(false) const [error, setError] = useState('') const [saveMessage, setSaveMessage] = useState('') useEffect(() => { translationRef.current = t }, [t]) useEffect(() => { if (serverRunning) { return } setLoading(false) setConfigPath('') setRows([]) setSaveMessage('') setError(t('advancedConfig.serverRequired')) }, [serverRunning, t]) useEffect(() => { if (!serverRunning) { return } let cancelled = false const loadModelMappings = async () => { setLoading(true) setError('') try { const result = await window.electronAPI.getModelMappingsConfig() if (cancelled) { return } setConfigPath(result.configPath) setRows(toRows(result.modelMappings)) } catch (err) { if (cancelled) { return } setError( `${translationRef.current('advancedConfig.loadFailed')}: ${(err as Error).message}`, ) } finally { if (!cancelled) { setLoading(false) } } } void loadModelMappings() return () => { cancelled = true } }, [serverRunning]) const handleRowChange = ( id: string, field: 'source' | 'target', value: string, ) => { setRows((currentRows) => currentRows.map((row) => row.id === id ? { ...row, [field]: value } : row, ), ) setError('') setSaveMessage('') } const handleAddRow = () => { setRows((currentRows) => [...currentRows, createModelMappingRow()]) setError('') setSaveMessage('') } const handleRemoveRow = (id: string) => { setRows((currentRows) => currentRows.filter((row) => row.id !== id)) setError('') setSaveMessage('') } const buildModelMappings = (): Record | null => { const modelMappings: Record = {} for (const row of rows) { if (!row.source && !row.target) { continue } if (!row.source || !row.target) { setError(t('advancedConfig.validationIncomplete')) return null } if (Object.hasOwn(modelMappings, row.source)) { setError(t('advancedConfig.validationDuplicate', { model: row.source })) return null } modelMappings[row.source] = row.target } return modelMappings } const handleSave = async () => { setError('') setSaveMessage('') const nextModelMappings = buildModelMappings() if (!nextModelMappings) { return } setSaving(true) try { await window.electronAPI.saveModelMappings(nextModelMappings) setRows(toRows(nextModelMappings)) setSaveMessage(t('advancedConfig.saved')) } catch (err) { setError(`${t('advancedConfig.saveFailed')}: ${(err as Error).message}`) } finally { setSaving(false) } } return (
{t('header.advancedConfig')}

{t('advancedConfig.title')}

{t('advancedConfig.subtitle')}

{error && (
{error}
)} {saveMessage && !error && (
{saveMessage}
)}

{t('advancedConfig.modelMappingsTitle')}

{t('advancedConfig.modelMappingsDesc')}

{t('advancedConfig.scopeLabel')}

{t('advancedConfig.scopeNote')}

{t('advancedConfig.restartNote')}

{t('advancedConfig.configPath')}
{configPath || '—'}
{loading ? (
{t('dashboard.loading')}
) : rows.length === 0 ? (
{t('advancedConfig.emptyTitle')}

{t('advancedConfig.emptyDescription')}

) : ( rows.map((row) => (
)) )}

{t('advancedConfig.saveHelp')}

) }