Extract components and hooks from oversized pages into colocated _components/ and _hooks/ subdirectories to enforce the 500-LOC hard cap. page.tsx files reduced to 205, 121, and 136 LOC respectively. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
102 lines
3.6 KiB
TypeScript
102 lines
3.6 KiB
TypeScript
'use client'
|
|
|
|
import { StatCard } from './_components/StatCard'
|
|
import { ReportTypeGrid } from './_components/ReportTypeGrid'
|
|
import { ScopePanel } from './_components/ScopePanel'
|
|
import { IncludeOptions } from './_components/IncludeOptions'
|
|
import { ExportPanel } from './_components/ExportPanel'
|
|
import { RecentReports } from './_components/RecentReports'
|
|
import { HelpPanel } from './_components/HelpPanel'
|
|
import { useReportExport } from './_hooks/useReportExport'
|
|
|
|
export default function ReportsPage() {
|
|
const {
|
|
processingActivities,
|
|
vendors,
|
|
isLoading,
|
|
selectedReportType,
|
|
selectedFormat,
|
|
setSelectedFormat,
|
|
selectedVendors,
|
|
selectedActivities,
|
|
includeFindings,
|
|
setIncludeFindings,
|
|
includeControls,
|
|
setIncludeControls,
|
|
includeRiskAssessment,
|
|
setIncludeRiskAssessment,
|
|
isGenerating,
|
|
generatedReports,
|
|
stats,
|
|
handleReportTypeChange,
|
|
handleExport,
|
|
toggleVendor,
|
|
toggleActivity,
|
|
selectAllVendors,
|
|
selectAllActivities,
|
|
} = useReportExport()
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex items-center justify-center h-64">
|
|
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Reports & Export</h1>
|
|
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">Berichte erstellen und Daten exportieren</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<StatCard label="Verarbeitungen" value={stats.totalActivities} subtext={`${stats.approvedActivities} freigegeben`} color="blue" />
|
|
<StatCard label="Vendors" value={stats.totalVendors} subtext={`${stats.highRiskVendors} hohes Risiko`} color="purple" />
|
|
<StatCard label="Offene Findings" value={stats.openFindings} subtext={`${stats.criticalFindings} kritisch`} color={stats.criticalFindings > 0 ? 'red' : 'yellow'} />
|
|
<StatCard label="Verträge" value={stats.totalContracts} subtext="dokumentiert" color="green" />
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
<div className="lg:col-span-2 space-y-6">
|
|
<ReportTypeGrid selectedReportType={selectedReportType} onSelect={handleReportTypeChange} />
|
|
<ScopePanel
|
|
selectedReportType={selectedReportType}
|
|
processingActivities={processingActivities}
|
|
vendors={vendors}
|
|
selectedVendors={selectedVendors}
|
|
selectedActivities={selectedActivities}
|
|
onToggleVendor={toggleVendor}
|
|
onToggleActivity={toggleActivity}
|
|
onSelectAllVendors={selectAllVendors}
|
|
onSelectAllActivities={selectAllActivities}
|
|
/>
|
|
<IncludeOptions
|
|
includeFindings={includeFindings}
|
|
includeControls={includeControls}
|
|
includeRiskAssessment={includeRiskAssessment}
|
|
onFindingsChange={setIncludeFindings}
|
|
onControlsChange={setIncludeControls}
|
|
onRiskAssessmentChange={setIncludeRiskAssessment}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-6">
|
|
<ExportPanel
|
|
selectedReportType={selectedReportType}
|
|
selectedFormat={selectedFormat}
|
|
selectedVendors={selectedVendors}
|
|
selectedActivities={selectedActivities}
|
|
isGenerating={isGenerating}
|
|
onFormatChange={setSelectedFormat}
|
|
onExport={handleExport}
|
|
/>
|
|
<RecentReports reports={generatedReports} />
|
|
<HelpPanel />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|