Files
breakpilot-lehrer/admin-lehrer/app/(admin)/infrastructure/sbom/wizard/page.tsx
Benjamin Admin bd4b956e3c [split-required] Split final 43 files (500-668 LOC) to complete refactoring
klausur-service (11 files):
- cv_gutter_repair, ocr_pipeline_regression, upload_api
- ocr_pipeline_sessions, smart_spell, nru_worksheet_generator
- ocr_pipeline_overlays, mail/aggregator, zeugnis_api
- cv_syllable_detect, self_rag

backend-lehrer (17 files):
- classroom_engine/suggestions, generators/quiz_generator
- worksheets_api, llm_gateway/comparison, state_engine_api
- classroom/models (→ 4 submodules), services/file_processor
- alerts_agent/api/wizard+digests+routes, content_generators/pdf
- classroom/routes/sessions, llm_gateway/inference
- classroom_engine/analytics, auth/keycloak_auth
- alerts_agent/processing/rule_engine, ai_processor/print_versions

agent-core (5 files):
- brain/memory_store, brain/knowledge_graph, brain/context_manager
- orchestrator/supervisor, sessions/session_manager

admin-lehrer (5 components):
- GridOverlay, StepGridReview, DevOpsPipelineSidebar
- DataFlowDiagram, sbom/wizard/page

website (2 files):
- DependencyMap, lehrer/abitur-archiv

Other: nibis_ingestion, grid_detection_service, export-doclayout-onnx

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-25 09:41:42 +02:00

164 lines
5.2 KiB
TypeScript

'use client'
/**
* SBOM (Software Bill of Materials) - Lern-Wizard
*
* Interaktiver Wizard zum Verstehen der SBOM.
*/
import { useState } from 'react'
import Link from 'next/link'
import { STEPS, type WizardStep } from './_components/wizard-content'
import { WizardStepper, EducationCard, CategoryDemo } from './_components/WizardWidgets'
export default function SBOMWizardPage() {
const [currentStep, setCurrentStep] = useState(0)
const [steps, setSteps] = useState<WizardStep[]>(STEPS)
const currentStepData = steps[currentStep]
const isWelcome = currentStepData?.id === 'welcome'
const isSummary = currentStepData?.id === 'summary'
const goToNext = () => {
if (currentStep < steps.length - 1) {
setSteps(prev => prev.map((step, idx) =>
idx === currentStep && step.status === 'pending'
? { ...step, status: 'completed' }
: step
))
setCurrentStep(prev => prev + 1)
}
}
const goToPrev = () => {
if (currentStep > 0) {
setCurrentStep(prev => prev - 1)
}
}
const handleStepClick = (index: number) => {
setCurrentStep(index)
}
return (
<div className="min-h-screen bg-slate-100 py-8">
<div className="max-w-4xl mx-auto px-4">
{/* Header */}
<div className="bg-white rounded-lg shadow-lg p-6 mb-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold text-slate-800">📋 SBOM Lern-Wizard</h1>
<p className="text-slate-600 mt-1">
Software Bill of Materials verstehen
</p>
</div>
<Link
href="/infrastructure/sbom"
className="text-orange-600 hover:text-orange-800 text-sm"
>
Zurueck zur SBOM
</Link>
</div>
</div>
{/* Stepper */}
<div className="bg-white rounded-lg shadow-lg p-6 mb-6">
<WizardStepper
steps={steps}
currentStep={currentStep}
onStepClick={handleStepClick}
/>
</div>
{/* Content */}
<div className="bg-white rounded-lg shadow-lg p-6">
{/* Step Header */}
<div className="flex items-center mb-6">
<span className="text-4xl mr-4">{currentStepData?.icon}</span>
<div>
<h2 className="text-xl font-bold text-slate-800">
Schritt {currentStep + 1}: {currentStepData?.name}
</h2>
<p className="text-slate-500 text-sm">
{currentStep + 1} von {steps.length}
</p>
</div>
</div>
{/* Education Card */}
<EducationCard stepId={currentStepData?.id || ''} />
{/* Category Demo */}
<CategoryDemo stepId={currentStepData?.id || ''} />
{/* Welcome Start Button */}
{isWelcome && (
<div className="text-center py-8">
<button
onClick={goToNext}
className="bg-orange-600 text-white px-8 py-3 rounded-lg font-medium hover:bg-orange-700 transition-colors"
>
🚀 Lern-Tour starten
</button>
</div>
)}
{/* Summary Actions */}
{isSummary && (
<div className="text-center py-6 space-y-4">
<div className="flex justify-center gap-4">
<Link
href="/infrastructure/sbom"
className="px-6 py-3 bg-orange-600 text-white rounded-lg font-medium hover:bg-orange-700 transition-colors"
>
📋 Zur SBOM
</Link>
<button
onClick={() => {
setCurrentStep(0)
setSteps(STEPS.map(s => ({ ...s, status: 'pending' })))
}}
className="px-6 py-3 bg-slate-200 text-slate-700 rounded-lg font-medium hover:bg-slate-300 transition-colors"
>
🔄 Wizard neu starten
</button>
</div>
</div>
)}
{/* Navigation */}
{!isWelcome && (
<div className="flex justify-between mt-8 pt-6 border-t">
<button
onClick={goToPrev}
disabled={currentStep === 0}
className={`px-6 py-2 rounded-lg transition-colors ${
currentStep === 0
? 'bg-slate-200 text-slate-400 cursor-not-allowed'
: 'bg-slate-200 text-slate-700 hover:bg-slate-300'
}`}
>
Zurueck
</button>
{!isSummary && (
<button
onClick={goToNext}
className="bg-orange-600 text-white px-6 py-2 rounded-lg hover:bg-orange-700 transition-colors"
>
Weiter
</button>
)}
</div>
)}
</div>
{/* Footer Info */}
<div className="text-center text-slate-500 text-sm mt-6">
BreakPilot SBOM - 180+ Komponenten dokumentiert
</div>
</div>
</div>
)
}