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>
98 lines
3.4 KiB
TypeScript
98 lines
3.4 KiB
TypeScript
import { BQASMetrics } from '../types'
|
|
|
|
export function TestSuiteCard({
|
|
title,
|
|
description,
|
|
metrics,
|
|
onRun,
|
|
isRunning,
|
|
lastRun,
|
|
}: {
|
|
title: string
|
|
description: string
|
|
metrics?: BQASMetrics
|
|
onRun: () => void
|
|
isRunning: boolean
|
|
lastRun?: string
|
|
}) {
|
|
const passRate = metrics ? (metrics.passed_tests / metrics.total_tests) * 100 : 0
|
|
|
|
return (
|
|
<div className="bg-white rounded-xl border border-slate-200 p-6">
|
|
<div className="flex items-start justify-between">
|
|
<div>
|
|
<h3 className="text-lg font-semibold text-slate-900">{title}</h3>
|
|
<p className="mt-1 text-sm text-slate-500">{description}</p>
|
|
</div>
|
|
<button
|
|
onClick={onRun}
|
|
disabled={isRunning}
|
|
className={`px-4 py-2 rounded-lg text-sm font-medium transition-colors ${
|
|
isRunning
|
|
? 'bg-slate-100 text-slate-400 cursor-not-allowed'
|
|
: 'bg-primary-600 text-white hover:bg-primary-700'
|
|
}`}
|
|
>
|
|
{isRunning ? (
|
|
<span className="flex items-center gap-2">
|
|
<svg className="animate-spin h-4 w-4" fill="none" viewBox="0 0 24 24">
|
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
<path
|
|
className="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
/>
|
|
</svg>
|
|
Laeuft...
|
|
</span>
|
|
) : (
|
|
'Tests starten'
|
|
)}
|
|
</button>
|
|
</div>
|
|
|
|
{metrics && (
|
|
<div className="mt-6">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="text-slate-600">Pass Rate</span>
|
|
<span className="font-medium text-slate-900">{passRate.toFixed(1)}%</span>
|
|
</div>
|
|
<div className="mt-2 h-2 bg-slate-100 rounded-full overflow-hidden">
|
|
<div
|
|
className={`h-full rounded-full transition-all ${
|
|
passRate >= 80 ? 'bg-emerald-500' : passRate >= 60 ? 'bg-amber-500' : 'bg-red-500'
|
|
}`}
|
|
style={{ width: `${passRate}%` }}
|
|
/>
|
|
</div>
|
|
|
|
<div className="mt-4 grid grid-cols-3 gap-4">
|
|
<div className="text-center">
|
|
<p className="text-2xl font-bold text-slate-900">{metrics.total_tests}</p>
|
|
<p className="text-xs text-slate-500">Tests</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className="text-2xl font-bold text-emerald-600">{metrics.passed_tests}</p>
|
|
<p className="text-xs text-slate-500">Bestanden</p>
|
|
</div>
|
|
<div className="text-center">
|
|
<p className="text-2xl font-bold text-red-600">{metrics.failed_tests}</p>
|
|
<p className="text-xs text-slate-500">Fehlgeschlagen</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-4 pt-4 border-t border-slate-100">
|
|
<p className="text-xs text-slate-500">
|
|
Durchschnittlicher Score: <span className="font-medium">{metrics.avg_composite_score.toFixed(2)}</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{lastRun && (
|
|
<p className="mt-4 text-xs text-slate-400">Letzter Lauf: {new Date(lastRun).toLocaleString('de-DE')}</p>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|