import { useState, useEffect, useRef } from 'react' import { Loader2, GitFork } from 'lucide-react' import { useStore } from '../store/useStore' import { fetchSchemaGraph } from '../lib/api' import type { SchemaTable, SchemaRelationship } from '../lib/types' // ─── Table card ─────────────────────────────────────────────────── function TableCard({ table, x, y }: { table: SchemaTable; x: number; y: number }) { return ( {/* Card bg */} {/* Header */} {table.name} {/* Columns */} {table.columns.map((col, i) => ( {col.pk ? '🔑 ' : col.fk ? '🔗 ' : ' '} {col.name} {col.type} ))} ) } // ─── Layout helpers ─────────────────────────────────────────────── function layoutTables(tables: SchemaTable[]) { const CARD_W = 180 const CARD_H_BASE = 28 const COL_H = 20 const GAP_X = 40 const GAP_Y = 30 const COLS_PER_ROW = 3 const positions: Record = {} let maxRowH = 0 tables.forEach((t, i) => { const col = i % COLS_PER_ROW const row = Math.floor(i / COLS_PER_ROW) const h = CARD_H_BASE + t.columns.length * COL_H if (row === Math.floor(i / COLS_PER_ROW) && col === 0) maxRowH = 0 maxRowH = Math.max(maxRowH, h) const prevRowsH = tables .slice(0, row * COLS_PER_ROW) .reduce((acc, _, idx) => { if (idx % COLS_PER_ROW === 0) { const rowH = tables.slice(idx, idx + COLS_PER_ROW).reduce( (m, rt) => Math.max(m, CARD_H_BASE + rt.columns.length * COL_H), 0 ) return acc + rowH + GAP_Y } return acc }, 0) positions[t.name] = { x: col * (CARD_W + GAP_X) + 20, y: prevRowsH + 20, w: CARD_W, h, } }) return positions } function RelationshipLine({ from, to, positions, }: { from: string to: string positions: Record }) { const a = positions[from] const b = positions[to] if (!a || !b) return null const x1 = a.x + a.w const y1 = a.y + 14 const x2 = b.x const y2 = b.y + 14 const cx = (x1 + x2) / 2 return ( ) } // ─── ER Diagram component ───────────────────────────────────────── export function ERDiagram() { const { schemaGraph, setSchemaGraph } = useStore() const [loading, setLoading] = useState(false) const svgRef = useRef(null) const load = async () => { setLoading(true) try { const data = await fetchSchemaGraph() setSchemaGraph(data) } catch { // noop } finally { setLoading(false) } } useEffect(() => { if (!schemaGraph) void load() // eslint-disable-next-line react-hooks/exhaustive-deps }, []) if (loading) { return (
Loading schema...
) } if (!schemaGraph || schemaGraph.tables.length === 0) { return (

Schema will appear after database connects

) } const { tables, relationships } = schemaGraph const positions = layoutTables(tables) const allX = Object.values(positions).map((p) => p.x + p.w) const allY = Object.values(positions).map((p) => p.y + p.h) const svgW = Math.max(...allX) + 40 const svgH = Math.max(...allY) + 40 return (
Entity Relationship Diagram · {tables.length} tables
{/* FK lines */} {(relationships as SchemaRelationship[]).map((rel, i) => ( ))} {/* Tables */} {tables.map((t: SchemaTable) => ( ))}
) }