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>
172 lines
5.7 KiB
TypeScript
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>
|
|
)
|
|
}
|