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>
This commit is contained in:
313
admin-v2/components/developers/DevPortalLayout.tsx
Normal file
313
admin-v2/components/developers/DevPortalLayout.tsx
Normal file
@@ -0,0 +1,313 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import { Book, Code, FileText, HelpCircle, Zap, Terminal, Database, Shield, ChevronRight, Clock } from 'lucide-react'
|
||||
|
||||
interface NavItem {
|
||||
title: string
|
||||
href: string
|
||||
icon?: React.ReactNode
|
||||
items?: NavItem[]
|
||||
}
|
||||
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
title: 'Getting Started',
|
||||
href: '/developers/getting-started',
|
||||
icon: <Zap className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Quick Start', href: '/developers/getting-started' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'SDK Documentation',
|
||||
href: '/developers/sdk',
|
||||
icon: <Code className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Overview', href: '/developers/sdk' },
|
||||
{ title: 'Installation', href: '/developers/sdk/installation' },
|
||||
{ title: 'Configuration', href: '/developers/sdk/configuration' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Consent SDK',
|
||||
href: '/developers/sdk/consent',
|
||||
icon: <Shield className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Uebersicht', href: '/developers/sdk/consent' },
|
||||
{ title: 'Installation', href: '/developers/sdk/consent/installation' },
|
||||
{ title: 'API Referenz', href: '/developers/sdk/consent/api-reference' },
|
||||
{ title: 'Frameworks', href: '/developers/sdk/consent/frameworks' },
|
||||
{ title: 'Mobile SDKs', href: '/developers/sdk/consent/mobile' },
|
||||
{ title: 'Sicherheit', href: '/developers/sdk/consent/security' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'API Reference',
|
||||
href: '/developers/api',
|
||||
icon: <Terminal className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Overview', href: '/developers/api' },
|
||||
{ title: 'State API', href: '/developers/api/state' },
|
||||
{ title: 'RAG Search API', href: '/developers/api/rag' },
|
||||
{ title: 'Generation API', href: '/developers/api/generate' },
|
||||
{ title: 'Export API', href: '/developers/api/export' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Guides',
|
||||
href: '/developers/guides',
|
||||
icon: <Book className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Overview', href: '/developers/guides' },
|
||||
{ title: 'Phase 1: Assessment', href: '/developers/guides/phase1' },
|
||||
{ title: 'Phase 2: Dokumentation', href: '/developers/guides/phase2' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Changelog',
|
||||
href: '/developers/changelog',
|
||||
icon: <Clock className="w-4 h-4" />,
|
||||
items: [
|
||||
{ title: 'Versionshistorie', href: '/developers/changelog' },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
interface DevPortalLayoutProps {
|
||||
children: React.ReactNode
|
||||
title?: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export function DevPortalLayout({ children, title, description }: DevPortalLayoutProps) {
|
||||
const pathname = usePathname()
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Header */}
|
||||
<header className="sticky top-0 z-50 border-b border-gray-200 bg-white/95 backdrop-blur">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
<div className="flex items-center gap-4">
|
||||
<Link href="/developers" className="flex items-center gap-2">
|
||||
<div className="w-8 h-8 rounded-lg bg-gradient-to-br from-blue-600 to-indigo-600 flex items-center justify-center">
|
||||
<FileText className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<span className="font-semibold text-gray-900">Developer Portal</span>
|
||||
</Link>
|
||||
<span className="text-gray-300">|</span>
|
||||
<span className="text-sm text-gray-500">AI Compliance SDK</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<Link
|
||||
href="/sdk"
|
||||
className="text-sm text-gray-600 hover:text-gray-900 transition-colors"
|
||||
>
|
||||
SDK Dashboard
|
||||
</Link>
|
||||
<a
|
||||
href="https://github.com/breakpilot/compliance-sdk"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-gray-600 hover:text-gray-900 transition-colors"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="max-w-7xl mx-auto flex">
|
||||
{/* Sidebar */}
|
||||
<aside className="w-64 shrink-0 border-r border-gray-200 h-[calc(100vh-64px)] sticky top-16 overflow-y-auto">
|
||||
<nav className="p-4 space-y-6">
|
||||
{navigation.map((section) => (
|
||||
<div key={section.href}>
|
||||
<div className="flex items-center gap-2 text-sm font-medium text-gray-900 mb-2">
|
||||
{section.icon}
|
||||
<span>{section.title}</span>
|
||||
</div>
|
||||
{section.items && (
|
||||
<ul className="ml-6 space-y-1">
|
||||
{section.items.map((item) => (
|
||||
<li key={item.href}>
|
||||
<Link
|
||||
href={item.href}
|
||||
className={`block py-1.5 text-sm transition-colors ${
|
||||
pathname === item.href
|
||||
? 'text-blue-600 font-medium'
|
||||
: 'text-gray-600 hover:text-gray-900'
|
||||
}`}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
{/* Main Content */}
|
||||
<main className="flex-1 min-w-0">
|
||||
<div className="max-w-3xl mx-auto px-8 py-12">
|
||||
{(title || description) && (
|
||||
<div className="mb-8">
|
||||
{title && (
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">{title}</h1>
|
||||
)}
|
||||
{description && (
|
||||
<p className="text-lg text-gray-600">{description}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="prose prose-gray prose-blue max-w-none">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Re-usable components for documentation
|
||||
export function ApiEndpoint({
|
||||
method,
|
||||
path,
|
||||
description,
|
||||
}: {
|
||||
method: 'GET' | 'POST' | 'PUT' | 'DELETE'
|
||||
path: string
|
||||
description: string
|
||||
}) {
|
||||
const methodColors = {
|
||||
GET: 'bg-green-100 text-green-800',
|
||||
POST: 'bg-blue-100 text-blue-800',
|
||||
PUT: 'bg-yellow-100 text-yellow-800',
|
||||
DELETE: 'bg-red-100 text-red-800',
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border border-gray-200 rounded-lg p-4 my-4 not-prose">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<span className={`px-2 py-1 text-xs font-bold rounded ${methodColors[method]}`}>
|
||||
{method}
|
||||
</span>
|
||||
<code className="text-sm font-mono text-gray-800">{path}</code>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600">{description}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function CodeBlock({
|
||||
language,
|
||||
children,
|
||||
filename,
|
||||
}: {
|
||||
language: string
|
||||
children: string
|
||||
filename?: string
|
||||
}) {
|
||||
return (
|
||||
<div className="my-4 not-prose">
|
||||
{filename && (
|
||||
<div className="bg-gray-800 text-gray-300 text-xs px-4 py-2 rounded-t-lg border-b border-gray-700">
|
||||
{filename}
|
||||
</div>
|
||||
)}
|
||||
<pre className={`bg-gray-900 text-gray-100 p-4 overflow-x-auto text-sm ${filename ? 'rounded-b-lg' : 'rounded-lg'}`}>
|
||||
<code className={`language-${language}`}>{children}</code>
|
||||
</pre>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function ParameterTable({
|
||||
parameters,
|
||||
}: {
|
||||
parameters: Array<{
|
||||
name: string
|
||||
type: string
|
||||
required?: boolean
|
||||
description: string
|
||||
}>
|
||||
}) {
|
||||
return (
|
||||
<div className="my-4 overflow-x-auto not-prose">
|
||||
<table className="min-w-full divide-y divide-gray-200">
|
||||
<thead className="bg-gray-50">
|
||||
<tr>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Parameter</th>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Type</th>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Required</th>
|
||||
<th className="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="bg-white divide-y divide-gray-200">
|
||||
{parameters.map((param) => (
|
||||
<tr key={param.name}>
|
||||
<td className="px-4 py-3">
|
||||
<code className="text-sm text-blue-600">{param.name}</code>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
<code className="text-sm text-gray-600">{param.type}</code>
|
||||
</td>
|
||||
<td className="px-4 py-3">
|
||||
{param.required ? (
|
||||
<span className="text-red-600 text-sm">Yes</span>
|
||||
) : (
|
||||
<span className="text-gray-400 text-sm">No</span>
|
||||
)}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-gray-600">{param.description}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function InfoBox({
|
||||
type = 'info',
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
type?: 'info' | 'warning' | 'success' | 'error'
|
||||
title?: string
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const styles = {
|
||||
info: 'bg-blue-50 border-blue-200 text-blue-800',
|
||||
warning: 'bg-yellow-50 border-yellow-200 text-yellow-800',
|
||||
success: 'bg-green-50 border-green-200 text-green-800',
|
||||
error: 'bg-red-50 border-red-200 text-red-800',
|
||||
}
|
||||
|
||||
const icons = {
|
||||
info: <HelpCircle className="w-5 h-5" />,
|
||||
warning: <Shield className="w-5 h-5" />,
|
||||
success: <Zap className="w-5 h-5" />,
|
||||
error: <Shield className="w-5 h-5" />,
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`my-4 p-4 border rounded-lg ${styles[type]} not-prose`}>
|
||||
<div className="flex items-start gap-3">
|
||||
<div className="shrink-0 mt-0.5">{icons[type]}</div>
|
||||
<div>
|
||||
{title && <p className="font-medium mb-1">{title}</p>}
|
||||
<div className="text-sm">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
165
admin-v2/components/developers/SDKDocsSidebar.tsx
Normal file
165
admin-v2/components/developers/SDKDocsSidebar.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
'use client'
|
||||
|
||||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
import {
|
||||
Shield, Download, FileCode, Layers, Smartphone, Lock,
|
||||
ChevronDown, ChevronRight, Home, BookOpen,
|
||||
Code2
|
||||
} from 'lucide-react'
|
||||
|
||||
interface NavItem {
|
||||
title: string
|
||||
href: string
|
||||
icon?: React.ReactNode
|
||||
children?: NavItem[]
|
||||
}
|
||||
|
||||
const navigation: NavItem[] = [
|
||||
{
|
||||
title: 'Uebersicht',
|
||||
href: '/developers/sdk/consent',
|
||||
icon: <Home className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
title: 'Installation',
|
||||
href: '/developers/sdk/consent/installation',
|
||||
icon: <Download className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
title: 'API Referenz',
|
||||
href: '/developers/sdk/consent/api-reference',
|
||||
icon: <FileCode className="w-4 h-4" />,
|
||||
},
|
||||
{
|
||||
title: 'Frameworks',
|
||||
href: '/developers/sdk/consent/frameworks',
|
||||
icon: <Layers className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'React', href: '/developers/sdk/consent/frameworks/react' },
|
||||
{ title: 'Vue', href: '/developers/sdk/consent/frameworks/vue' },
|
||||
{ title: 'Angular', href: '/developers/sdk/consent/frameworks/angular' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Mobile SDKs',
|
||||
href: '/developers/sdk/consent/mobile',
|
||||
icon: <Smartphone className="w-4 h-4" />,
|
||||
children: [
|
||||
{ title: 'iOS (Swift)', href: '/developers/sdk/consent/mobile/ios' },
|
||||
{ title: 'Android (Kotlin)', href: '/developers/sdk/consent/mobile/android' },
|
||||
{ title: 'Flutter', href: '/developers/sdk/consent/mobile/flutter' },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Sicherheit',
|
||||
href: '/developers/sdk/consent/security',
|
||||
icon: <Lock className="w-4 h-4" />,
|
||||
},
|
||||
]
|
||||
|
||||
function NavLink({ item, depth = 0 }: { item: NavItem; depth?: number }) {
|
||||
const pathname = usePathname()
|
||||
const isActive = pathname === item.href
|
||||
const isParentActive = item.children?.some((child) => pathname === child.href)
|
||||
const [isOpen, setIsOpen] = React.useState(isActive || isParentActive)
|
||||
|
||||
const hasChildren = item.children && item.children.length > 0
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-center">
|
||||
<Link
|
||||
href={item.href}
|
||||
className={`flex-1 flex items-center gap-2 px-3 py-2 text-sm rounded-lg transition-colors ${
|
||||
isActive
|
||||
? 'bg-violet-100 text-violet-900 font-medium'
|
||||
: 'text-gray-600 hover:bg-gray-100 hover:text-gray-900'
|
||||
}`}
|
||||
style={{ paddingLeft: `${12 + depth * 12}px` }}
|
||||
>
|
||||
{item.icon && <span className="shrink-0">{item.icon}</span>}
|
||||
<span>{item.title}</span>
|
||||
</Link>
|
||||
{hasChildren && (
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="p-2 hover:bg-gray-100 rounded-lg transition-colors"
|
||||
>
|
||||
{isOpen ? (
|
||||
<ChevronDown className="w-4 h-4 text-gray-400" />
|
||||
) : (
|
||||
<ChevronRight className="w-4 h-4 text-gray-400" />
|
||||
)}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
{hasChildren && isOpen && (
|
||||
<div className="mt-1 space-y-1">
|
||||
{item.children?.map((child) => (
|
||||
<NavLink key={child.href} item={child} depth={depth + 1} />
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function SDKDocsSidebar() {
|
||||
return (
|
||||
<aside className="w-64 h-[calc(100vh-64px)] fixed top-16 left-0 border-r border-gray-200 bg-white overflow-y-auto">
|
||||
<div className="p-4">
|
||||
{/* Header */}
|
||||
<div className="mb-6">
|
||||
<Link
|
||||
href="/developers/sdk/consent"
|
||||
className="flex items-center gap-3 p-3 rounded-xl bg-gradient-to-r from-violet-50 to-purple-50 border border-violet-100"
|
||||
>
|
||||
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-violet-600 to-purple-600 flex items-center justify-center">
|
||||
<Shield className="w-5 h-5 text-white" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="font-semibold text-gray-900">Consent SDK</div>
|
||||
<div className="text-xs text-gray-500">v1.0.0</div>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Navigation */}
|
||||
<nav className="space-y-1">
|
||||
{navigation.map((item) => (
|
||||
<NavLink key={item.href} item={item} />
|
||||
))}
|
||||
</nav>
|
||||
|
||||
{/* Resources */}
|
||||
<div className="mt-8 pt-6 border-t border-gray-200">
|
||||
<div className="text-xs font-medium text-gray-400 uppercase tracking-wider mb-3 px-3">
|
||||
Ressourcen
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<a
|
||||
href="https://github.com/breakpilot/consent-sdk"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-2 px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900 rounded-lg transition-colors"
|
||||
>
|
||||
<Code2 className="w-4 h-4" />
|
||||
<span>GitHub</span>
|
||||
</a>
|
||||
<Link
|
||||
href="/developers"
|
||||
className="flex items-center gap-2 px-3 py-2 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-900 rounded-lg transition-colors"
|
||||
>
|
||||
<BookOpen className="w-4 h-4" />
|
||||
<span>Developer Portal</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
)
|
||||
}
|
||||
|
||||
export default SDKDocsSidebar
|
||||
Reference in New Issue
Block a user