Files
breakpilot-lehrer/website/app/admin/quality/page.tsx
Benjamin Admin 0b37c5e692 [split-required] Split website + studio-v2 monoliths (Phase 3 continued)
Website (14 monoliths split):
- compliance/page.tsx (1,519 → 9), docs/audit (1,262 → 20)
- quality (1,231 → 16), alerts (1,203 → 10), docs (1,202 → 11)
- i18n.ts (1,173 → 8 language files)
- unity-bridge (1,094 → 12), backlog (1,087 → 6)
- training (1,066 → 8), rag (1,063 → 8)
- Deleted index_original.ts (4,899 LOC dead backup)

Studio-v2 (5 monoliths split):
- meet/page.tsx (1,481 → 9), messages (1,166 → 9)
- AlertsB2BContext.tsx (1,165 → 5 modules)
- alerts-b2b/page.tsx (1,019 → 6), korrektur/archiv (1,001 → 6)

All existing imports preserved. Zero new TypeScript errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-24 17:52:36 +02:00

172 lines
5.7 KiB
TypeScript

'use client'
/**
* Quality Dashboard - BQAS (Breakpilot Quality Assurance System)
*
* Umfassendes Qualitaetssicherungs-Dashboard mit:
* - Golden Test Suite Ergebnisse
* - Synthetic Test Generierung
* - Regression Tracking
* - Test Run Historie
* - RAG Correction Tests
*/
import AdminLayout from '@/components/admin/AdminLayout'
import { useQualityDashboard } from './useQualityDashboard'
import { VOICE_SERVICE_URL, TabId } from './types'
import { OverviewTab } from './_components/OverviewTab'
import { GoldenTab } from './_components/GoldenTab'
import { RagTab } from './_components/RagTab'
import { SyntheticTab } from './_components/SyntheticTab'
import { TestRunsTable } from './_components/TestRunsTable'
import { SchedulerTab } from './_components/SchedulerTab'
const TABS: { id: TabId; label: string }[] = [
{ id: 'overview', label: 'Uebersicht' },
{ id: 'golden', label: 'Golden Suite' },
{ id: 'rag', label: 'RAG/Korrektur' },
{ id: 'synthetic', label: 'Synthetic' },
{ id: 'history', label: 'Historie' },
{ id: 'scheduler', label: 'Lokaler Scheduler' },
]
export default function QualityDashboard() {
const state = useQualityDashboard()
const renderTabContent = () => {
switch (state.activeTab) {
case 'overview':
return (
<OverviewTab
goldenMetrics={state.goldenMetrics}
ragMetrics={state.ragMetrics}
syntheticMetrics={state.syntheticMetrics}
trendData={state.trendData}
testRuns={state.testRuns}
isRunningGolden={state.isRunningGolden}
isRunningRag={state.isRunningRag}
isRunningSynthetic={state.isRunningSynthetic}
runGoldenTests={state.runGoldenTests}
runRagTests={state.runRagTests}
runSyntheticTests={state.runSyntheticTests}
/>
)
case 'golden':
return (
<GoldenTab
goldenMetrics={state.goldenMetrics}
isRunningGolden={state.isRunningGolden}
runGoldenTests={state.runGoldenTests}
/>
)
case 'rag':
return (
<RagTab
ragMetrics={state.ragMetrics}
isRunningRag={state.isRunningRag}
runRagTests={state.runRagTests}
/>
)
case 'synthetic':
return (
<SyntheticTab
syntheticMetrics={state.syntheticMetrics}
isRunningSynthetic={state.isRunningSynthetic}
runSyntheticTests={state.runSyntheticTests}
/>
)
case 'history':
return (
<div className="bg-white rounded-xl border border-slate-200 p-6">
<h3 className="text-lg font-semibold text-slate-900 mb-6">Test Run Historie</h3>
<TestRunsTable runs={state.testRuns} />
</div>
)
case 'scheduler':
return (
<SchedulerTab
isRunningGolden={state.isRunningGolden}
isRunningRag={state.isRunningRag}
isRunningSynthetic={state.isRunningSynthetic}
runGoldenTests={state.runGoldenTests}
runRagTests={state.runRagTests}
runSyntheticTests={state.runSyntheticTests}
/>
)
default:
return null
}
}
return (
<AdminLayout
title="Qualitaetssicherung"
description="BQAS - Breakpilot Quality Assurance System"
>
{/* Error Banner */}
{state.error && (
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700 flex items-center gap-3">
<svg className="w-5 h-5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>{state.error}</span>
<button onClick={state.fetchData} className="ml-auto text-red-600 hover:text-red-800 text-sm font-medium">
Erneut versuchen
</button>
</div>
)}
{/* Loading State */}
{state.isLoading && (
<div className="flex items-center justify-center py-12">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600"></div>
</div>
)}
{/* Main Content */}
{!state.isLoading && (
<>
{/* Tabs */}
<div className="mb-6 border-b border-slate-200">
<nav className="flex gap-6">
{TABS.map((tab) => (
<button
key={tab.id}
onClick={() => state.setActiveTab(tab.id)}
className={`pb-3 text-sm font-medium border-b-2 transition-colors ${
state.activeTab === tab.id
? 'border-primary-600 text-primary-600'
: 'border-transparent text-slate-500 hover:text-slate-700'
}`}
>
{tab.label}
</button>
))}
</nav>
</div>
{/* Tab Content */}
{renderTabContent()}
</>
)}
{/* Footer Info */}
<div className="mt-8 pt-6 border-t border-slate-200">
<div className="flex items-center justify-between text-sm text-slate-500">
<div>
<span className="font-medium">Voice Service:</span> {VOICE_SERVICE_URL}
</div>
<div className="flex items-center gap-4">
<a href="/admin/voice" className="text-primary-600 hover:text-primary-700">
Voice Dashboard
</a>
<a href="/admin/docs" className="text-primary-600 hover:text-primary-700">
Dokumentation
</a>
</div>
</div>
</div>
</AdminLayout>
)
}