import { useState } from 'react' import { motion } from 'framer-motion' import { X, PlugZap, Database, CheckCircle2, XCircle, Loader2, RotateCcw } from 'lucide-react' import { useStore } from '../store/useStore' import { connectExternalDb, fetchSuggestQuestions } from '../lib/api' interface ConnectDBProps { onClose: () => void } type DbType = 'sqlite' | 'postgres' const SQLITE_EXAMPLES = [ { label: 'In-memory (blank)', value: ':memory:' }, { label: 'Custom path', value: '/path/to/your/database.db' }, ] const POSTGRES_EXAMPLES = [ { label: 'Local default', value: 'postgresql://postgres:password@localhost:5432/mydb' }, { label: 'With SSL', value: 'postgresql://user:pass@host:5432/dbname?sslmode=require' }, ] export function ConnectDB({ onClose }: ConnectDBProps) { const { dbLabel, setDbLabel, setTables, setDbSeeded, setIsCustomDb, setCustomDbSuggestions, setSuggestionsLoading } = useStore() const [dbType, setDbType] = useState('sqlite') const [value, setValue] = useState('') const [status, setStatus] = useState<'idle' | 'connecting' | 'success' | 'error'>('idle') const [message, setMessage] = useState('') const placeholder = dbType === 'postgres' ? 'postgresql://user:password@host:5432/dbname' : '/path/to/database.db' const examples = dbType === 'postgres' ? POSTGRES_EXAMPLES : SQLITE_EXAMPLES const getDsn = () => { if (dbType === 'postgres' && value.trim() && !value.trim().startsWith('postgresql://') && !value.trim().startsWith('postgres://')) { return `postgresql://${value.trim()}` } return value.trim() } const handleConnect = async () => { const dsn = getDsn() if (!dsn) return setStatus('connecting') setMessage('') try { const res = await connectExternalDb(dsn) if (res.success) { setDbLabel(res.dbLabel) setTables(res.tables) setDbSeeded(true) setIsCustomDb(true) setStatus('success') setMessage(res.message) // Start generating suggestions in the background (cached by DSN) setCustomDbSuggestions([]) setSuggestionsLoading(true) fetchSuggestQuestions(dsn) .then((qs) => { setCustomDbSuggestions(qs); setSuggestionsLoading(false) }) .catch(() => setSuggestionsLoading(false)) } else { setStatus('error') setMessage(res.message) } } catch (e) { setStatus('error') setMessage(e instanceof Error ? e.message : 'Connection failed') } } const handleReset = async () => { setStatus('connecting') try { const res = await connectExternalDb('/app/backend/data/benchmark.db') if (res.success) { setDbLabel(res.dbLabel) setTables(res.tables) setDbSeeded(true) setIsCustomDb(false) setCustomDbSuggestions([]) setSuggestionsLoading(false) setStatus('success') setMessage('Reset to built-in benchmark database') } else { setStatus('error') setMessage(res.message) } } catch (e) { setStatus('error') setMessage(e instanceof Error ? e.message : 'Reset failed') } } return ( { if (e.target === e.currentTarget) onClose() }} > {/* Header */}

Connect Database

SQLite file or PostgreSQL connection string

{/* Current DB */}
Active: {dbLabel}
{/* Body */}
{/* DB Type toggle */}
{(['sqlite', 'postgres'] as DbType[]).map((type) => ( ))}
{ setValue(e.target.value); setStatus('idle') }} onKeyDown={(e) => e.key === 'Enter' && void handleConnect()} placeholder={placeholder} className="w-full px-3 py-2.5 text-sm rounded-xl border focus:outline-none transition-all font-mono" style={{ background: 'var(--bg-tertiary)', borderColor: 'var(--border-color)', color: 'var(--text-primary)', }} autoFocus /> {dbType === 'postgres' && (

Format: postgresql://user:password@host:port/dbname

)}
{/* Quick examples */}
Quick select
{examples.map((ex) => ( ))}
{/* Status message */} {status !== 'idle' && (
{status === 'connecting' && } {status === 'success' && } {status === 'error' && } {status === 'connecting' ? 'Connecting…' : message}
)}
{/* Footer */}
) }