feat: add SQL editor, query results, and workspace panels

Add CodeMirror 6 SQL editor with Ctrl+Enter execution, ResultsTable
with virtual scrolling and resizable columns, ResultsPanel, EditableCell,
WorkspacePanel (editor + results split), and TabContent router.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-11 19:06:48 +03:00
parent d333732346
commit 13a8535b5c
6 changed files with 520 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
import { ResultsTable } from "./ResultsTable";
import type { QueryResult } from "@/types";
import { Loader2, AlertCircle } from "lucide-react";
interface Props {
result?: QueryResult | null;
error?: string | null;
isLoading?: boolean;
onCellDoubleClick?: (
rowIndex: number,
colIndex: number,
value: unknown
) => void;
highlightedCells?: Set<string>;
}
export function ResultsPanel({
result,
error,
isLoading,
onCellDoubleClick,
highlightedCells,
}: Props) {
if (isLoading) {
return (
<div className="flex h-full items-center justify-center text-muted-foreground">
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
Executing query...
</div>
);
}
if (error) {
return (
<div className="flex h-full items-center justify-center p-4">
<div className="flex items-start gap-2 rounded-md border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive">
<AlertCircle className="mt-0.5 h-4 w-4 shrink-0" />
<pre className="whitespace-pre-wrap font-mono text-xs">{error}</pre>
</div>
</div>
);
}
if (!result) {
return (
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
Press Ctrl+Enter to execute query
</div>
);
}
if (result.columns.length === 0) {
return (
<div className="flex h-full items-center justify-center text-sm text-muted-foreground">
Query executed successfully. {result.row_count} rows affected.
</div>
);
}
return (
<ResultsTable
columns={result.columns}
types={result.types}
rows={result.rows}
onCellDoubleClick={onCellDoubleClick}
highlightedCells={highlightedCells}
/>
);
}