import Section from './Section' import React, { useEffect, useState } from 'react' import { useTranslation } from '../../i18n' import { useToast } from '../shared/Toast' import { Trash2, Copy, Terminal, Plus, Check } from 'lucide-react' import { authApi } from '../../api/client' import { useAddonStore } from '../../store/addonStore' import PhotoProvidersSection from './PhotoProvidersSection' interface McpToken { id: number name: string token_prefix: string created_at: string last_used_at: string | null } export default function IntegrationsTab(): React.ReactElement { const { t, locale } = useTranslation() const toast = useToast() const { isEnabled: addonEnabled, loadAddons } = useAddonStore() const mcpEnabled = addonEnabled('mcp') useEffect(() => { loadAddons() }, [loadAddons]) // MCP state const [mcpTokens, setMcpTokens] = useState([]) const [mcpModalOpen, setMcpModalOpen] = useState(false) const [mcpNewName, setMcpNewName] = useState('') const [mcpCreatedToken, setMcpCreatedToken] = useState(null) const [mcpCreating, setMcpCreating] = useState(false) const [mcpDeleteId, setMcpDeleteId] = useState(null) const [copiedKey, setCopiedKey] = useState(null) const mcpEndpoint = `${window.location.origin}/mcp` const mcpJsonConfig = `{ "mcpServers": { "trek": { "command": "npx", "args": [ "mcp-remote", "${mcpEndpoint}", "--header", "Authorization: Bearer " ] } } }` useEffect(() => { if (mcpEnabled) { authApi.mcpTokens.list().then(d => setMcpTokens(d.tokens || [])).catch(() => {}) } }, [mcpEnabled]) const handleCreateMcpToken = async () => { if (!mcpNewName.trim()) return setMcpCreating(true) try { const d = await authApi.mcpTokens.create(mcpNewName.trim()) setMcpCreatedToken(d.token.raw_token) setMcpNewName('') setMcpTokens(prev => [{ id: d.token.id, name: d.token.name, token_prefix: d.token.token_prefix, created_at: d.token.created_at, last_used_at: null }, ...prev]) } catch { toast.error(t('settings.mcp.toast.createError')) } finally { setMcpCreating(false) } } const handleDeleteMcpToken = async (id: number) => { try { await authApi.mcpTokens.delete(id) setMcpTokens(prev => prev.filter(tk => tk.id !== id)) setMcpDeleteId(null) toast.success(t('settings.mcp.toast.deleted')) } catch { toast.error(t('settings.mcp.toast.deleteError')) } } const handleCopy = (text: string, key: string) => { navigator.clipboard.writeText(text).then(() => { setCopiedKey(key) setTimeout(() => setCopiedKey(null), 2000) }) } return ( <> {mcpEnabled && (
{/* Endpoint URL */}
{mcpEndpoint}
{/* JSON config box */}
              {mcpJsonConfig}
            

{t('settings.mcp.clientConfigHint')}

{/* Token list */}
{mcpTokens.length === 0 ? (

{t('settings.mcp.noTokens')}

) : (
{mcpTokens.map((token, i) => (

{token.name}

{token.token_prefix}... {t('settings.mcp.tokenCreatedAt')} {new Date(token.created_at).toLocaleDateString(locale)} {token.last_used_at && ( · {t('settings.mcp.tokenUsedAt')} {new Date(token.last_used_at).toLocaleDateString(locale)} )}

))}
)}
)} {/* Create MCP Token modal */} {mcpModalOpen && (
{ if (e.target === e.currentTarget && !mcpCreatedToken) setMcpModalOpen(false) }}>
{!mcpCreatedToken ? ( <>

{t('settings.mcp.modal.createTitle')}

setMcpNewName(e.target.value)} onKeyDown={e => e.key === 'Enter' && handleCreateMcpToken()} placeholder={t('settings.mcp.modal.tokenNamePlaceholder')} className="w-full px-3 py-2.5 border rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-indigo-300" style={{ borderColor: 'var(--border-primary)', background: 'var(--bg-secondary)', color: 'var(--text-primary)' }} autoFocus />
) : ( <>

{t('settings.mcp.modal.createdTitle')}

{t('settings.mcp.modal.createdWarning')}

                    {mcpCreatedToken}
                  
)}
)} {/* Delete MCP Token confirm */} {mcpDeleteId !== null && (
{ if (e.target === e.currentTarget) setMcpDeleteId(null) }}>

{t('settings.mcp.deleteTokenTitle')}

{t('settings.mcp.deleteTokenMessage')}

)} ) }