Files
breakpilot-compliance/admin-compliance/app/sdk/sdk-flow/_components/DetailPanel.tsx
Sharang Parnerkar 2b818c6fb3 refactor(admin): split sdk-flow page.tsx into colocated components
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>
2026-04-14 22:49:33 +02:00

258 lines
8.7 KiB
TypeScript

'use client'
import { SDK_FLOW_STEPS, FLOW_PACKAGES, findProducerStep, type SDKFlowStep } from '../flow-data'
import { completionColor, completionLabel } from './helpers'
export function DetailPanel({
step,
onClose,
}: {
step: SDKFlowStep
onClose: () => void
}) {
const pkg = FLOW_PACKAGES[step.package]
const baseUrl = 'https://macmini:3007'
return (
<div className="w-80 bg-white border-l border-slate-200 overflow-y-auto">
<div className="sticky top-0 bg-white z-10 border-b border-slate-200">
<div className="flex items-center justify-between p-4">
<h3 className="font-bold text-slate-900">{step.name}</h3>
<button
onClick={onClose}
className="text-slate-400 hover:text-slate-600 text-lg leading-none"
>
x
</button>
</div>
<div className="px-4 pb-3 flex items-center gap-2">
<span
className="px-2 py-0.5 rounded text-xs font-medium"
style={{ background: pkg.color.bg, color: pkg.color.text }}
>
{pkg.icon} {pkg.name}
</span>
<span className="text-xs text-slate-400">seq {step.seq}</span>
{step.isOptional && (
<span className="px-2 py-0.5 rounded text-xs bg-slate-100 text-slate-500">
Optional
</span>
)}
</div>
</div>
<div className="p-4 space-y-4">
{/* Fertigstellungsgrad */}
{step.completion !== undefined && (
<div className="bg-slate-50 rounded-lg p-3">
<div className="flex items-center justify-between mb-1.5">
<span className="text-xs font-semibold text-slate-500 uppercase">
Fertigstellungsgrad
</span>
<span
className="text-lg font-bold"
style={{ color: completionColor(step.completion) }}
>
{step.completion}%
</span>
</div>
<div className="h-2.5 bg-slate-200 rounded-full overflow-hidden">
<div
className="h-full rounded-full"
style={{
width: `${step.completion}%`,
background: completionColor(step.completion),
}}
/>
</div>
<div
className="text-xs mt-1.5 font-medium"
style={{ color: completionColor(step.completion) }}
>
{completionLabel(step.completion)}
</div>
</div>
)}
{/* Beschreibung */}
<div>
<p className="text-sm text-slate-700 leading-relaxed">{step.description}</p>
<p className="text-xs text-slate-500 leading-relaxed mt-2">{step.descriptionLong}</p>
{step.legalBasis && (
<div className="mt-2 px-2 py-1.5 bg-blue-50 rounded text-xs text-blue-700">
<span className="font-medium">Rechtsgrundlage:</span> {step.legalBasis}
</div>
)}
</div>
{/* Inputs */}
{step.inputs.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
Inputs (SDKState)
</h4>
<div className="space-y-1">
{step.inputs.map(input => {
const producer = findProducerStep(input)
return (
<div
key={input}
className="flex items-center justify-between text-sm bg-blue-50 rounded px-2 py-1"
>
<code className="text-blue-700 text-xs">{input}</code>
{producer && (
<span className="text-xs text-slate-400">
{producer.nameShort}
</span>
)}
</div>
)
})}
</div>
</div>
)}
{/* Outputs */}
{step.outputs.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
Outputs (SDKState)
</h4>
<div className="space-y-1">
{step.outputs.map(output => (
<div
key={output}
className="text-sm bg-emerald-50 rounded px-2 py-1"
>
<code className="text-emerald-700 text-xs">{output}</code>
</div>
))}
</div>
</div>
)}
{/* DB Tables */}
{step.dbTables.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
DB-Tabellen
</h4>
<div className="space-y-1">
{step.dbTables.map(table => (
<div
key={table}
className="flex items-center justify-between text-sm bg-slate-100 rounded px-2 py-1"
>
<code className="text-slate-700 text-xs">{table}</code>
<span className="text-xs text-slate-400">{step.dbMode}</span>
</div>
))}
</div>
</div>
)}
{/* RAG Collections */}
{step.ragCollections.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
RAG-Collections
</h4>
<div className="space-y-1">
{step.ragCollections.map(rag => (
<div
key={rag}
className="text-sm bg-green-50 rounded px-2 py-1"
>
<code className="text-green-700 text-xs">{rag}</code>
</div>
))}
{step.ragPurpose && (
<p className="text-xs text-slate-500 mt-1">{step.ragPurpose}</p>
)}
</div>
</div>
)}
{/* Checkpoint */}
{step.checkpointId && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
Checkpoint
</h4>
<div className="bg-amber-50 rounded p-2 space-y-1">
<div className="flex items-center gap-2">
<code className="text-xs font-bold text-amber-800">
{step.checkpointId}
</code>
<span
className={`px-1.5 py-0.5 rounded text-xs font-medium ${
step.checkpointType === 'REQUIRED'
? 'bg-red-100 text-red-700'
: 'bg-yellow-100 text-yellow-700'
}`}
>
{step.checkpointType}
</span>
</div>
{step.checkpointReviewer && step.checkpointReviewer !== 'NONE' && (
<div className="text-xs text-slate-600">
Reviewer: <span className="font-medium">{step.checkpointReviewer}</span>
</div>
)}
</div>
</div>
)}
{/* Generated Docs */}
{step.generates && step.generates.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
Generierte Dokumente
</h4>
<div className="space-y-1">
{step.generates.map(doc => (
<div
key={doc}
className="text-sm bg-violet-50 rounded px-2 py-1 text-violet-700"
>
{doc}
</div>
))}
</div>
</div>
)}
{/* Prerequisites */}
{step.prerequisiteSteps.length > 0 && (
<div>
<h4 className="text-xs font-semibold text-slate-500 uppercase mb-1.5">
Voraussetzungen
</h4>
<div className="space-y-1">
{step.prerequisiteSteps.map(preId => {
const preStep = SDK_FLOW_STEPS.find(s => s.id === preId)
return (
<div
key={preId}
className="text-sm text-slate-600 bg-slate-50 rounded px-2 py-1"
>
{preStep?.name || preId}
</div>
)
})}
</div>
</div>
)}
{/* Open in SDK */}
<button
onClick={() => window.open(`${baseUrl}${step.url}`, '_blank')}
className="w-full mt-2 px-4 py-2 bg-purple-600 text-white rounded-lg text-sm font-medium hover:bg-purple-700 transition-colors"
>
Im SDK oeffnen
</button>
</div>
</div>
)
}