import { useState } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { useDataGenerator } from "@/hooks/use-data-generator"; import { toast } from "sonner"; import { Loader2, CheckCircle2, XCircle, Wand2, Table2, } from "lucide-react"; interface Props { open: boolean; onOpenChange: (open: boolean) => void; connectionId: string; schema: string; table: string; } type Step = "config" | "preview" | "done"; export function GenerateDataDialog({ open, onOpenChange, connectionId, schema, table, }: Props) { const [step, setStep] = useState("config"); const [rowCount, setRowCount] = useState(10); const [includeRelated, setIncludeRelated] = useState(true); const [customInstructions, setCustomInstructions] = useState(""); const { generatePreview, preview, isGenerating, generateError, insertData, insertedRows, isInserting, insertError, progress, reset, } = useDataGenerator(); const [prevOpen, setPrevOpen] = useState(false); if (open !== prevOpen) { setPrevOpen(open); if (open) { setStep("config"); setRowCount(10); setIncludeRelated(true); setCustomInstructions(""); reset(); } } const handleGenerate = () => { const genId = crypto.randomUUID(); generatePreview( { params: { connection_id: connectionId, schema, table, row_count: rowCount, include_related: includeRelated, custom_instructions: customInstructions || undefined, }, genId, }, { onSuccess: () => setStep("preview"), onError: (err) => toast.error("Generation failed", { description: String(err) }), } ); }; const handleInsert = () => { if (!preview) return; insertData( { connectionId, preview }, { onSuccess: (rows) => { setStep("done"); toast.success(`Inserted ${rows} rows`); }, onError: (err) => toast.error("Insert failed", { description: String(err) }), } ); }; return ( Generate Test Data {step === "config" && ( <>
{schema}.{table}
setRowCount(Math.min(1000, Math.max(1, parseInt(e.target.value) || 1)))} min={1} max={1000} />
setIncludeRelated(e.target.checked)} className="rounded" /> Include parent tables (via foreign keys)
setCustomInstructions(e.target.value)} />
{isGenerating && progress && (
{progress.message} {progress.percent}%
)} )} {step === "preview" && preview && ( <>
Preview: {preview.total_rows} rows across {preview.tables.length} tables
{preview.tables.map((tbl) => (
{tbl.schema}.{tbl.table} {tbl.row_count} rows
{tbl.columns.map((col) => ( ))} {tbl.rows.slice(0, 5).map((row, i) => ( {(row as unknown[]).map((val, j) => ( ))} ))} {tbl.rows.length > 5 && ( )}
{col}
{val === null ? ( NULL ) : ( String(val).substring(0, 50) )}
...and {tbl.rows.length - 5} more rows
))}
)} {step === "done" && (
{insertError ? (

Insert Failed

{insertError}

) : (

Data Generated Successfully

{insertedRows} rows inserted across {preview?.tables.length ?? 0} tables.

)} {insertError && ( )}
)} {generateError && step === "config" && (

{generateError}

)}
); }