diff --git a/src/app/(dashboard)/einstellungen/ai-settings.tsx b/src/app/(dashboard)/einstellungen/ai-settings.tsx index 2c23165..d8e9167 100644 --- a/src/app/(dashboard)/einstellungen/ai-settings.tsx +++ b/src/app/(dashboard)/einstellungen/ai-settings.tsx @@ -10,7 +10,9 @@ interface AISettings { } interface ApiKeyInfo { + id: string; provider: string; + keyHint: string; isActive: boolean; } @@ -25,6 +27,8 @@ export default function AISettingsForm() { const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null); const [loading, setLoading] = useState(true); const [apiKeys, setApiKeys] = useState([]); + const [apiKeyInput, setApiKeyInput] = useState(''); + const [savingKey, setSavingKey] = useState(false); useEffect(() => { fetch('/api/settings/ai') @@ -107,12 +111,77 @@ export default function AISettingsForm() { const activeKey = apiKeys.find( (k) => k.provider === settings.provider && k.isActive, ); + const providerLabel = settings.provider === 'anthropic' ? 'Anthropic' : 'OpenAI'; + + async function handleSaveApiKey() { + if (!apiKeyInput || apiKeyInput.length < 8) { + setMessage({ type: 'error', text: 'API-Schlüssel muss mindestens 8 Zeichen lang sein.' }); + return; + } + setSavingKey(true); + setMessage(null); + try { + let res: Response; + if (activeKey) { + res = await fetch(`/api/settings/api-keys/${activeKey.id}`, { + method: 'PATCH', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ apiKey: apiKeyInput }), + }); + } else { + res = await fetch('/api/settings/api-keys', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ provider: settings.provider, apiKey: apiKeyInput }), + }); + } + if (res.ok) { + const updated = await res.json(); + setApiKeys((prev) => { + if (activeKey) { + return prev.map((k) => (k.id === activeKey.id ? { ...k, ...updated } : k)); + } + return [...prev, updated]; + }); + setApiKeyInput(''); + setMessage({ type: 'success', text: `API-Schlüssel für ${providerLabel} gespeichert.` }); + } else { + const data = await res.json(); + setMessage({ type: 'error', text: data.error ?? 'Fehler beim Speichern des Schlüssels.' }); + } + } catch { + setMessage({ type: 'error', text: 'Netzwerkfehler beim Speichern des Schlüssels.' }); + } finally { + setSavingKey(false); + } + } + return ( -
- - {activeKey - ? `API-Schlüssel für ${settings.provider === 'anthropic' ? 'Anthropic' : 'OpenAI'} ist konfiguriert.` - : `Kein API-Schlüssel für ${settings.provider === 'anthropic' ? 'Anthropic' : 'OpenAI'} hinterlegt. Bitte unten unter „API-Schlüssel" einen Schlüssel hinzufügen.`} +
+ +
+ setApiKeyInput(e.target.value)} + placeholder={activeKey ? `Aktuell: ${activeKey.keyHint} — neuen Schlüssel eingeben zum Ersetzen` : `${providerLabel} API-Schlüssel eingeben`} + className="flex-1 rounded-lg border border-card-border bg-background px-3 py-2 text-sm text-foreground placeholder:text-muted/50" + /> + +
+
+ + {activeKey + ? `API-Schlüssel für ${providerLabel} ist konfiguriert (${activeKey.keyHint}).` + : `Kein API-Schlüssel für ${providerLabel} hinterlegt.`} +
); })()}