import { useState, useEffect } from 'react'; import { Button } from './ui/button'; import { Input } from './ui/input'; import { Key, Plus, Trash2, Eye, EyeOff, Copy, Check, Github, ExternalLink } from 'lucide-react'; import { useVersionCheck } from '../hooks/useVersionCheck'; import { version } from '../../package.json'; import { authenticatedFetch } from '../utils/api'; import { useTranslation } from 'react-i18next'; function CredentialsSettings() { const { t } = useTranslation('settings'); const [apiKeys, setApiKeys] = useState([]); const [githubCredentials, setGithubCredentials] = useState([]); const [loading, setLoading] = useState(true); const [showNewKeyForm, setShowNewKeyForm] = useState(false); const [showNewGithubForm, setShowNewGithubForm] = useState(false); const [newKeyName, setNewKeyName] = useState(''); const [newGithubName, setNewGithubName] = useState(''); const [newGithubToken, setNewGithubToken] = useState(''); const [newGithubDescription, setNewGithubDescription] = useState(''); const [showToken, setShowToken] = useState({}); const [copiedKey, setCopiedKey] = useState(null); const [newlyCreatedKey, setNewlyCreatedKey] = useState(null); // Version check hook const { updateAvailable, latestVersion, releaseInfo } = useVersionCheck('siteboon', 'claudecodeui'); useEffect(() => { fetchData(); }, []); const fetchData = async () => { try { setLoading(true); // Fetch API keys const apiKeysRes = await authenticatedFetch('/api/settings/api-keys'); const apiKeysData = await apiKeysRes.json(); setApiKeys(apiKeysData.apiKeys || []); // Fetch GitHub credentials only const credentialsRes = await authenticatedFetch('/api/settings/credentials?type=github_token'); const credentialsData = await credentialsRes.json(); setGithubCredentials(credentialsData.credentials || []); } catch (error) { console.error('Error fetching settings:', error); } finally { setLoading(false); } }; const createApiKey = async () => { if (!newKeyName.trim()) return; try { const res = await authenticatedFetch('/api/settings/api-keys', { method: 'POST', body: JSON.stringify({ keyName: newKeyName }) }); const data = await res.json(); if (data.success) { setNewlyCreatedKey(data.apiKey); setNewKeyName(''); setShowNewKeyForm(false); fetchData(); } } catch (error) { console.error('Error creating API key:', error); } }; const deleteApiKey = async (keyId) => { if (!confirm(t('apiKeys.confirmDelete'))) return; try { await authenticatedFetch(`/api/settings/api-keys/${keyId}`, { method: 'DELETE' }); fetchData(); } catch (error) { console.error('Error deleting API key:', error); } }; const toggleApiKey = async (keyId, isActive) => { try { await authenticatedFetch(`/api/settings/api-keys/${keyId}/toggle`, { method: 'PATCH', body: JSON.stringify({ isActive: !isActive }) }); fetchData(); } catch (error) { console.error('Error toggling API key:', error); } }; const createGithubCredential = async () => { if (!newGithubName.trim() || !newGithubToken.trim()) return; try { const res = await authenticatedFetch('/api/settings/credentials', { method: 'POST', body: JSON.stringify({ credentialName: newGithubName, credentialType: 'github_token', credentialValue: newGithubToken, description: newGithubDescription }) }); const data = await res.json(); if (data.success) { setNewGithubName(''); setNewGithubToken(''); setNewGithubDescription(''); setShowNewGithubForm(false); fetchData(); } } catch (error) { console.error('Error creating GitHub credential:', error); } }; const deleteGithubCredential = async (credentialId) => { if (!confirm(t('apiKeys.github.confirmDelete'))) return; try { await authenticatedFetch(`/api/settings/credentials/${credentialId}`, { method: 'DELETE' }); fetchData(); } catch (error) { console.error('Error deleting GitHub credential:', error); } }; const toggleGithubCredential = async (credentialId, isActive) => { try { await authenticatedFetch(`/api/settings/credentials/${credentialId}/toggle`, { method: 'PATCH', body: JSON.stringify({ isActive: !isActive }) }); fetchData(); } catch (error) { console.error('Error toggling GitHub credential:', error); } }; const copyToClipboard = (text, id) => { navigator.clipboard.writeText(text); setCopiedKey(id); setTimeout(() => setCopiedKey(null), 2000); }; if (loading) { return
{t('apiKeys.loading')}
; } return (
{/* New API Key Alert */} {newlyCreatedKey && (

{t('apiKeys.newKey.alertTitle')}

{t('apiKeys.newKey.alertMessage')}

{newlyCreatedKey.apiKey}
)} {/* API Keys Section */}

{t('apiKeys.title')}

{t('apiKeys.description')}

{t('apiKeys.apiDocsLink')}
{showNewKeyForm && (
setNewKeyName(e.target.value)} className="mb-2" />
)}
{apiKeys.length === 0 ? (

{t('apiKeys.empty')}

) : ( apiKeys.map((key) => (
{key.key_name}
{key.api_key}
{t('apiKeys.list.created')} {new Date(key.created_at).toLocaleDateString()} {key.last_used && ` • ${t('apiKeys.list.lastUsed')} ${new Date(key.last_used).toLocaleDateString()}`}
)) )}
{/* GitHub Credentials Section */}

{t('apiKeys.github.title')}

{t('apiKeys.github.descriptionAlt')}

{showNewGithubForm && (
setNewGithubName(e.target.value)} />
setNewGithubToken(e.target.value)} className="pr-10" />
setNewGithubDescription(e.target.value)} />
{t('apiKeys.github.form.howToCreate')}
)}
{githubCredentials.length === 0 ? (

{t('apiKeys.github.empty')}

) : ( githubCredentials.map((credential) => (
{credential.credential_name}
{credential.description && (
{credential.description}
)}
{t('apiKeys.github.added')} {new Date(credential.created_at).toLocaleDateString()}
)) )}
{/* Version Information */}
v{version} {updateAvailable && latestVersion && ( {t('apiKeys.version.updateAvailable', { version: latestVersion })} )}
); } export default CredentialsSettings;