import { useState, useEffect } from 'react'; import { supabase } from '../supabaseClient'; interface MySQLStatusData { active?: boolean; title: string; objective: string; points: number; challenge_type: string; schema: Record>; completed: boolean; total_score: number; } export default function MySQLPlayground() { const [status, setStatus] = useState(null); const [query, setQuery] = useState(''); const [running, setRunning] = useState(false); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [results, setResults] = useState<{ columns: string[]; rows: any[]; rowsAffected: number; isCorrect?: boolean; } | null>(null); const fetchStatus = async () => { setLoading(true); setError(''); try { const { data: { session } } = await supabase.auth.getSession(); if (!session) { setError('Unauthenticated session'); return; } const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/status`, { headers: { 'Authorization': `Bearer ${session.access_token}` } }); if (res.ok) { const data = await res.json(); if (data.active) { setStatus(data); } else { setStatus(null); } } else { setError('Failed to fetch playground status.'); } } catch { setError('Connection timed out.'); } finally { setLoading(false); } }; const handleInit = async () => { setLoading(true); setError(''); setResults(null); try { const { data: { session } } = await supabase.auth.getSession(); if (!session) { setError('Unauthenticated session'); return; } const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/init`, { method: 'POST', headers: { 'Authorization': `Bearer ${session.access_token}` } }); if (res.ok) { const data = await res.json(); setStatus({ active: true, title: data.title, objective: data.objective, points: data.points, schema: data.schema, challenge_type: data.challenge_type, completed: false, total_score: data.total_score }); } else { setError('Failed to initialize mock database playground.'); } } catch { setError('Server connection error.'); } finally { setLoading(false); } }; const handleRunQuery = async () => { if (!query.trim()) return; setRunning(true); setError(''); setResults(null); try { const { data: { session } } = await supabase.auth.getSession(); if (!session) { setError('Unauthenticated session'); return; } const res = await fetch(`${import.meta.env.VITE_API_BASE_URL}/api/challenges/mysql/query`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${session.access_token}` }, body: JSON.stringify({ query }) }); if (res.ok) { const data = await res.json(); if (data.success) { setResults({ columns: data.columns, rows: data.rows, rowsAffected: data.rows_affected, isCorrect: data.is_correct }); if (data.is_correct) { setStatus(prev => prev ? { ...prev, completed: true, total_score: data.total_score } : null); } if (data.schema) { setStatus(prev => prev ? { ...prev, schema: data.schema } : null); } } else { setError(data.error); } } else { setError('Database server query failure.'); } } catch { setError('Query connection lost.'); } finally { setRunning(false); } }; useEffect(() => { fetchStatus(); }, []); if (loading) { return (
INITIALIZING SQL PLAYGROUND...
); } // Dashboard state: no active database initialized if (!status) { return (
database

Interactive MySQL Playground

Test and run relational queries against isolated schemas dynamically built by the AI generator. Includes full support for:

SELECT / JOIN UPDATE / DELETE WINDOW FUNCTIONS
); } return (
{/* Play Workspace Scrollable Body */}
{/* Objectives Badge Header */}
{status.challenge_type} +{status.points} PTS {status.completed ? ( SOLVED ) : ( UNSOLVED )}
SCORE: {status.total_score}
{/* Objective banner */}

MISSION OBJECTIVE

{status.objective}

{/* Schema Tree */}
schema SCHEMA EXPLORER (MOCK INSTANCE)
{Object.entries(status.schema).map(([tableName, cols]) => (
table_chart {tableName}
    {cols.map((col, cIdx) => (
  • {col.name} {col.type}
  • ))}
))}
{/* Query Input Editor */}
terminal Enter SQL Query: