This repository has been archived on 2026-02-15. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BreakPilot Dev 660295e218 fix(admin-v2): Restore complete admin-v2 application
The admin-v2 application was incomplete in the repository. This commit
restores all missing components:

- Admin pages (76 pages): dashboard, ai, compliance, dsgvo, education,
  infrastructure, communication, development, onboarding, rbac
- SDK pages (45 pages): tom, dsfa, vvt, loeschfristen, einwilligungen,
  vendor-compliance, tom-generator, dsr, and more
- Developer portal (25 pages): API docs, SDK guides, frameworks
- All components, lib files, hooks, and types
- Updated package.json with all dependencies

The issue was caused by incomplete initial repository state - the full
admin-v2 codebase existed in backend/admin-v2 and docs-src/admin-v2
but was never fully synced to the main admin-v2 directory.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-08 23:40:15 -08:00

216 lines
7.7 KiB
TypeScript

'use client'
import React from 'react'
import { useSDK } from '@/lib/sdk'
import { SDKSidebar } from '../Sidebar'
import { CommandBar } from '../CommandBar'
import { SDKPipelineSidebar } from '../SDKPipelineSidebar'
// =============================================================================
// SDK HEADER
// =============================================================================
function SDKHeader() {
const { currentStep, setCommandBarOpen, completionPercentage } = useSDK()
return (
<header className="sticky top-0 z-30 bg-white border-b border-gray-200">
<div className="flex items-center justify-between px-6 py-3">
{/* Breadcrumb / Current Step */}
<div className="flex items-center gap-3">
<nav className="flex items-center text-sm text-gray-500">
<span>SDK</span>
<svg className="w-4 h-4 mx-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
<span className="text-gray-900 font-medium">
{currentStep?.name || 'Dashboard'}
</span>
</nav>
</div>
{/* Actions */}
<div className="flex items-center gap-4">
{/* Command Bar Trigger */}
<button
onClick={() => setCommandBarOpen(true)}
className="flex items-center gap-2 px-3 py-1.5 text-sm text-gray-500 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
/>
</svg>
<span>Suchen...</span>
<kbd className="ml-2 px-1.5 py-0.5 text-xs bg-gray-200 rounded">K</kbd>
</button>
{/* Progress Indicator */}
<div className="flex items-center gap-2">
<div className="w-24 h-2 bg-gray-200 rounded-full overflow-hidden">
<div
className="h-full bg-gradient-to-r from-purple-500 to-indigo-500 rounded-full transition-all duration-500"
style={{ width: `${completionPercentage}%` }}
/>
</div>
<span className="text-sm font-medium text-gray-600">{completionPercentage}%</span>
</div>
{/* Help Button */}
<button className="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</button>
</div>
</div>
</header>
)
}
// =============================================================================
// NAVIGATION FOOTER
// =============================================================================
function NavigationFooter() {
const { goToNextStep, goToPreviousStep, canGoNext, canGoPrevious, currentStep, validateCheckpoint } = useSDK()
const [isValidating, setIsValidating] = React.useState(false)
const handleNext = async () => {
if (!currentStep) return
setIsValidating(true)
try {
const status = await validateCheckpoint(currentStep.checkpointId)
if (status.passed) {
goToNextStep()
} else {
// Show error notification (in production, use toast)
console.error('Checkpoint validation failed:', status.errors)
}
} finally {
setIsValidating(false)
}
}
return (
<footer className="sticky bottom-0 bg-white border-t border-gray-200 px-6 py-4">
<div className="flex items-center justify-between">
{/* Previous Button */}
<button
onClick={goToPreviousStep}
disabled={!canGoPrevious}
className={`flex items-center gap-2 px-4 py-2 rounded-lg transition-colors ${
canGoPrevious
? 'text-gray-700 hover:bg-gray-100'
: 'text-gray-300 cursor-not-allowed'
}`}
>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
<span>Zurück</span>
</button>
{/* Current Step Info */}
<div className="text-sm text-gray-500">
Schritt {currentStep?.order || 1} von {currentStep?.phase === 1 ? 8 : 11}
</div>
{/* Next / Complete Button */}
<div className="flex items-center gap-3">
<button
onClick={goToNextStep}
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
>
Überspringen
</button>
<button
onClick={handleNext}
disabled={!canGoNext || isValidating}
className={`flex items-center gap-2 px-6 py-2 rounded-lg font-medium transition-colors ${
canGoNext && !isValidating
? 'bg-purple-600 text-white hover:bg-purple-700'
: 'bg-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
{isValidating ? (
<>
<svg className="animate-spin w-4 h-4" fill="none" viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
<span>Validiere...</span>
</>
) : (
<>
<span>Weiter</span>
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</>
)}
</button>
</div>
</div>
</footer>
)
}
// =============================================================================
// MAIN LAYOUT
// =============================================================================
interface SDKLayoutProps {
children: React.ReactNode
showNavigation?: boolean
}
export function SDKLayout({ children, showNavigation = true }: SDKLayoutProps) {
const { isCommandBarOpen, setCommandBarOpen } = useSDK()
return (
<div className="min-h-screen bg-gray-50">
{/* Sidebar */}
<SDKSidebar />
{/* Main Content */}
<div className="ml-64 flex flex-col min-h-screen">
{/* Header */}
<SDKHeader />
{/* Page Content */}
<main className="flex-1 p-6">{children}</main>
{/* Navigation Footer */}
{showNavigation && <NavigationFooter />}
</div>
{/* Command Bar Modal */}
{isCommandBarOpen && <CommandBar onClose={() => setCommandBarOpen(false)} />}
{/* Pipeline Sidebar (FAB on mobile, fixed on desktop) */}
<SDKPipelineSidebar />
</div>
)
}