import { useState, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { IconDatabase, IconBrandMysql, IconArrowRight, IconLoader2, IconAlertCircle, IconRefresh } from '@tabler/icons-react'; import AIVisualization from '../components/AIVisualization'; interface QueryResults { results: any; query: string; visualization?: { type: 'bar' | 'pie' | 'line'; config: any; }; } interface ApiError { message: string; details?: string | Record; } export default function Home() { const [dbConfig, setDbConfig] = useState({ host: '', port: '3306', database: '', username: '', password: '' }); const [tables, setTables] = useState([]); const [selectedTable, setSelectedTable] = useState(''); const [prompt, setPrompt] = useState(''); const [results, setResults] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [dbUri, setDbUri] = useState(''); const [showDbConfig, setShowDbConfig] = useState(false); useEffect(() => { const uri = `mysql://${dbConfig.username}:${dbConfig.password}@${dbConfig.host}:${dbConfig.port}/${dbConfig.database}`; setDbUri(uri); }, [dbConfig]); const fetchTables = async () => { if (!dbUri) return; setLoading(true); setError(null); try { const response = await fetch('/api/tables', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ dbUri }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message); } setTables(data.tables); } catch (err: any) { setError({ message: 'Failed to fetch tables', details: err.message }); } finally { setLoading(false); } }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!selectedTable) { setError({ message: "Table selection required", details: "Please select a table before submitting the query" }); return; } setLoading(true); setError(null); setResults(null); try { const response = await fetch('/api/sql', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ dbUri, userPrompt: `${prompt} from table ${selectedTable}` }), }); const data = await response.json(); if (!response.ok) { throw { message: data.message || 'An error occurred', details: data.details }; } setResults(data); } catch (err: any) { setError({ message: err.message || 'Failed to process request', details: err.details }); } finally { setLoading(false); } }; return (

Text to SQL Converter

Transform natural language into SQL queries using AI

{error && (

{error.message}

{error.details && (

{typeof error.details === 'string' ? error.details : Object.entries(error.details) .filter(([_, value]) => value) .map(([_, value]) => value) .join(', ')}

)}
)}
{showDbConfig && (
setDbConfig(prev => ({ ...prev, host: e.target.value }))} className="w-full px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent transition-all" placeholder="Server Host" />
setDbConfig(prev => ({ ...prev, port: e.target.value }))} className="w-full px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent transition-all" placeholder="Port" />
setDbConfig(prev => ({ ...prev, database: e.target.value }))} className="w-full px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent transition-all" placeholder="Database Name" />
setDbConfig(prev => ({ ...prev, username: e.target.value }))} className="w-full px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent transition-all" placeholder="Username" />
setDbConfig(prev => ({ ...prev, password: e.target.value }))} className="w-full px-4 py-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 focus:ring-2 focus:ring-blue-500 dark:focus:ring-blue-400 focus:border-transparent transition-all" placeholder="Password" />
)}