Extract BetriebOverviewPanel, DetailPanel, FlowCanvas, FlowToolbar, StepTable, useFlowGraph hook and helpers into _components/ so page.tsx drops from 1019 to 156 LOC (under the 300 soft target). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
157 lines
4.9 KiB
TypeScript
157 lines
4.9 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* SDK Flow Visualization
|
|
*
|
|
* Interaktive React Flow Darstellung aller SDK-Steps:
|
|
* - Farblich nach Package gruppiert (5 Packages)
|
|
* - Prerequisite-Edges zeigen den sequenziellen Flow
|
|
* - DB-Tabellen und RAG-Collections als optionale Nodes
|
|
* - Detail-Panel bei Klick auf einen Step
|
|
*/
|
|
|
|
import { useCallback, useState, useMemo, useEffect } from 'react'
|
|
import {
|
|
Node,
|
|
useNodesState,
|
|
useEdgesState,
|
|
} from 'reactflow'
|
|
import 'reactflow/dist/style.css'
|
|
|
|
import {
|
|
SDK_FLOW_STEPS,
|
|
getAllDbTables,
|
|
getAllRagCollections,
|
|
type SDKFlowStep,
|
|
} from './flow-data'
|
|
import { BetriebOverviewPanel } from './_components/BetriebOverviewPanel'
|
|
import { FlowToolbar } from './_components/FlowToolbar'
|
|
import { FlowCanvas } from './_components/FlowCanvas'
|
|
import { StepTable } from './_components/StepTable'
|
|
import { useFlowGraph } from './_components/useFlowGraph'
|
|
import { type PackageFilter } from './_components/helpers'
|
|
|
|
export default function SDKFlowPage() {
|
|
const [selectedStep, setSelectedStep] = useState<SDKFlowStep | null>(null)
|
|
const [packageFilter, setPackageFilter] = useState<PackageFilter>('alle')
|
|
const [showDb, setShowDb] = useState(false)
|
|
const [showRag, setShowRag] = useState(false)
|
|
|
|
const allDbTables = useMemo(() => getAllDbTables(), [])
|
|
const allRagCollections = useMemo(() => getAllRagCollections(), [])
|
|
|
|
// =========================================================================
|
|
// Build Nodes
|
|
// =========================================================================
|
|
|
|
const { nodes: initialNodes, edges: initialEdges } = useFlowGraph(
|
|
packageFilter,
|
|
showDb,
|
|
showRag,
|
|
selectedStep,
|
|
)
|
|
|
|
// =========================================================================
|
|
// React Flow State
|
|
// =========================================================================
|
|
|
|
const [nodes, setNodes, onNodesChange] = useNodesState([])
|
|
const [edges, setEdges, onEdgesChange] = useEdgesState([])
|
|
|
|
useEffect(() => {
|
|
setNodes(initialNodes)
|
|
setEdges(initialEdges)
|
|
}, [initialNodes, initialEdges, setNodes, setEdges])
|
|
|
|
const onNodeClick = useCallback((_event: React.MouseEvent, node: Node) => {
|
|
const step = SDK_FLOW_STEPS.find(s => s.id === node.id)
|
|
if (step) {
|
|
setSelectedStep(prev => (prev?.id === step.id ? null : step))
|
|
}
|
|
}, [])
|
|
|
|
const onPaneClick = useCallback(() => {
|
|
setSelectedStep(null)
|
|
}, [])
|
|
|
|
// =========================================================================
|
|
// Stats
|
|
// =========================================================================
|
|
|
|
const stats = useMemo(() => {
|
|
const visible =
|
|
packageFilter === 'alle'
|
|
? SDK_FLOW_STEPS
|
|
: SDK_FLOW_STEPS.filter(s => s.package === packageFilter)
|
|
return {
|
|
total: SDK_FLOW_STEPS.length,
|
|
visible: visible.length,
|
|
checkpoints: visible.filter(s => s.checkpointId).length,
|
|
dbTables: allDbTables.length,
|
|
ragCollections: allRagCollections.length,
|
|
}
|
|
}, [packageFilter, allDbTables, allRagCollections])
|
|
|
|
// =========================================================================
|
|
// Render
|
|
// =========================================================================
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
{/* Header */}
|
|
<div className="bg-white rounded-xl border border-slate-200 p-5 shadow-sm">
|
|
<div className="flex items-center gap-4">
|
|
<div className="w-12 h-12 rounded-xl bg-purple-600 flex items-center justify-center text-xl text-white">
|
|
SDK
|
|
</div>
|
|
<div>
|
|
<h2 className="text-xl font-bold text-slate-900">
|
|
SDK Flow Visualization
|
|
</h2>
|
|
<p className="text-sm text-slate-500">
|
|
{stats.total} Steps in 5 Packages | {stats.checkpoints} Checkpoints |{' '}
|
|
{stats.dbTables} DB-Tabellen | {stats.ragCollections} RAG-Collections
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Toolbar */}
|
|
<FlowToolbar
|
|
packageFilter={packageFilter}
|
|
setPackageFilter={setPackageFilter}
|
|
setSelectedStep={setSelectedStep}
|
|
showDb={showDb}
|
|
setShowDb={setShowDb}
|
|
showRag={showRag}
|
|
setShowRag={setShowRag}
|
|
/>
|
|
|
|
{/* Flow Canvas + Detail Panel */}
|
|
<FlowCanvas
|
|
nodes={nodes}
|
|
edges={edges}
|
|
onNodesChange={onNodesChange}
|
|
onEdgesChange={onEdgesChange}
|
|
onNodeClick={onNodeClick}
|
|
onPaneClick={onPaneClick}
|
|
packageFilter={packageFilter}
|
|
selectedStep={selectedStep}
|
|
setSelectedStep={setSelectedStep}
|
|
/>
|
|
|
|
{/* Betrieb Fertigstellungsgrad Übersicht */}
|
|
{packageFilter === 'betrieb' && <BetriebOverviewPanel />}
|
|
|
|
{/* Step Table (below flow) */}
|
|
<StepTable
|
|
packageFilter={packageFilter}
|
|
selectedStep={selectedStep}
|
|
setSelectedStep={setSelectedStep}
|
|
visibleCount={stats.visible}
|
|
totalCount={stats.total}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|