Each page.tsx was >500 LOC (610/602/596). Extracted React components to _components/ and custom hook to _hooks/ per-route, reducing all three page.tsx orchestrators to 107/229/120 LOC respectively. Zero behavior changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
121 lines
4.4 KiB
TypeScript
121 lines
4.4 KiB
TypeScript
'use client'
|
|
|
|
/**
|
|
* UCCA System Documentation Page (SDK Version)
|
|
*
|
|
* Displays architecture documentation, auditor information,
|
|
* and transparency data for the UCCA compliance system.
|
|
*/
|
|
|
|
import { useState, useEffect } from 'react'
|
|
import Link from 'next/link'
|
|
import { DocTab, Rule, Pattern, Control } from './_components/types'
|
|
import { OverviewTab } from './_components/OverviewTab'
|
|
import { ArchitectureTab } from './_components/ArchitectureTab'
|
|
import { AuditorTab } from './_components/AuditorTab'
|
|
import { RulesTab } from './_components/RulesTab'
|
|
import { LegalCorpusTab } from './_components/LegalCorpusTab'
|
|
|
|
const API_BASE = process.env.NEXT_PUBLIC_SDK_API_URL || 'https://macmini:8090'
|
|
|
|
const tabs: { id: DocTab; label: string }[] = [
|
|
{ id: 'overview', label: 'Uebersicht' },
|
|
{ id: 'architecture', label: 'Architektur' },
|
|
{ id: 'auditor', label: 'Fuer Auditoren' },
|
|
{ id: 'rules', label: 'Regel-Katalog' },
|
|
{ id: 'legal-corpus', label: 'Legal RAG' },
|
|
]
|
|
|
|
export default function DocumentationPage() {
|
|
const [activeTab, setActiveTab] = useState<DocTab>('overview')
|
|
const [rules, setRules] = useState<Rule[]>([])
|
|
const [patterns, setPatterns] = useState<Pattern[]>([])
|
|
const [controls, setControls] = useState<Control[]>([])
|
|
const [policyVersion, setPolicyVersion] = useState<string>('')
|
|
const [loading, setLoading] = useState(false)
|
|
|
|
useEffect(() => {
|
|
const fetchData = async () => {
|
|
setLoading(true)
|
|
try {
|
|
const rulesRes = await fetch(`${API_BASE}/sdk/v1/ucca/rules`, {
|
|
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
|
})
|
|
if (rulesRes.ok) {
|
|
const rulesData = await rulesRes.json()
|
|
setRules(rulesData.rules || [])
|
|
setPolicyVersion(rulesData.policy_version || '')
|
|
}
|
|
|
|
const patternsRes = await fetch(`${API_BASE}/sdk/v1/ucca/patterns`, {
|
|
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
|
})
|
|
if (patternsRes.ok) {
|
|
const patternsData = await patternsRes.json()
|
|
setPatterns(patternsData.patterns || [])
|
|
}
|
|
|
|
const controlsRes = await fetch(`${API_BASE}/sdk/v1/ucca/controls`, {
|
|
headers: { 'X-Tenant-ID': '00000000-0000-0000-0000-000000000000' }
|
|
})
|
|
if (controlsRes.ok) {
|
|
const controlsData = await controlsRes.json()
|
|
setControls(controlsData.controls || [])
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to fetch documentation data:', error)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
fetchData()
|
|
}, [])
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div className="flex items-center justify-between">
|
|
<div className="bg-white rounded-xl shadow-sm border p-6 flex-1">
|
|
<h1 className="text-2xl font-bold text-slate-900">UCCA System-Dokumentation</h1>
|
|
<p className="text-slate-500 mt-1">
|
|
Transparente Dokumentation des UCCA-Systems fuer Entwickler, Auditoren und Datenschutzbeauftragte.
|
|
</p>
|
|
</div>
|
|
<Link
|
|
href="/sdk/advisory-board"
|
|
className="ml-4 px-4 py-2 text-sm text-slate-600 hover:text-slate-800 border border-slate-200 rounded-lg hover:bg-slate-50"
|
|
>
|
|
Zurueck zum Advisory Board
|
|
</Link>
|
|
</div>
|
|
|
|
{/* Tab Navigation */}
|
|
<div className="bg-white rounded-xl border border-slate-200 shadow-sm overflow-hidden">
|
|
<div className="flex border-b border-slate-200 overflow-x-auto">
|
|
{tabs.map(tab => (
|
|
<button
|
|
key={tab.id}
|
|
onClick={() => setActiveTab(tab.id)}
|
|
className={`flex items-center gap-2 px-4 py-3 text-sm font-medium whitespace-nowrap transition-colors ${
|
|
activeTab === tab.id
|
|
? 'text-purple-600 border-b-2 border-purple-600 bg-purple-50'
|
|
: 'text-slate-600 hover:text-slate-800 hover:bg-slate-50'
|
|
}`}
|
|
>
|
|
{tab.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<div className="p-6">
|
|
{activeTab === 'overview' && <OverviewTab rules={rules} patterns={patterns} controls={controls} />}
|
|
{activeTab === 'architecture' && <ArchitectureTab />}
|
|
{activeTab === 'auditor' && <AuditorTab />}
|
|
{activeTab === 'rules' && <RulesTab rules={rules} policyVersion={policyVersion} loading={loading} />}
|
|
{activeTab === 'legal-corpus' && <LegalCorpusTab />}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|