import { useEffect, useState } from "react"; import { getModelInfo, getModelsStatus, predict, setModel } from "../api/client"; import { useApp } from "../context/AppContext"; import { useI18n } from "../i18n/I18nContext"; import type { ModelStatusEntry } from "../types/api"; export function SettingsPage() { const { threshold, setThreshold } = useApp(); const { t } = useI18n(); const [modelStatus, setModelStatus] = useState([]); const [active, setActive] = useState(""); const [testText, setTestText] = useState(() => t.settings.defaultTestText); const [testResult, setTestResult] = useState(null); const [testError, setTestError] = useState(null); const [testing, setTesting] = useState(false); const [message, setMessage] = useState(null); const [messageIsError, setMessageIsError] = useState(false); const [switching, setSwitching] = useState(false); const loadStatus = () => { getModelsStatus() .then((r) => { setModelStatus(r.models); setActive(r.active); }) .catch(() => { setMessage(t.settings.couldNotLoadStatus); setMessageIsError(true); }); }; useEffect(() => { loadStatus(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { setTestResult(null); setTestError(null); }, [testText, threshold]); const switchModel = async (name: string) => { const entry = modelStatus.find((m) => m.name === name); if (entry && !entry.available) { setMessage(entry.reason ?? ""); setMessageIsError(true); return; } setMessage(null); setMessageIsError(false); setSwitching(true); try { await setModel(name); setActive(name); setMessage(t.settings.activeModelMsg(name)); setMessageIsError(false); const info = await getModelInfo(); if (info.recommended_threshold != null) { setThreshold(info.recommended_threshold); } loadStatus(); } catch (e) { setMessage(e instanceof Error ? e.message : t.settings.failedSwitch); setMessageIsError(true); loadStatus(); } finally { setSwitching(false); } }; const runTest = async () => { setTesting(true); setTestResult(null); setTestError(null); try { const r = await predict(testText, threshold); setTestResult( t.settings.testResult( r.is_toxic ? t.badges.toxic : t.badges.safe, String(Math.round(r.probability * 100)) ) ); } catch (e) { setTestError(e instanceof Error ? e.message : t.settings.analysisFailed); } finally { setTesting(false); } }; return (

{t.settings.title}

{t.settings.activeModel}

{t.settings.productionNote("0.805", "2.54")}

{t.settings.baselinesNote("0.758", "0.790", "0.16")}

{t.settings.installHint}

{switching &&

{t.settings.switching}

}
{modelStatus.map((m) => ( ))}
{message && (

{message}

)}

{t.settings.thresholdTitle}

setThreshold(Number(e.target.value))} />

{threshold.toFixed(2)} — {t.settings.thresholdNote}

{t.settings.quickTest}