Some checks failed
Build + Deploy / build-admin-compliance (push) Failing after 34s
Build + Deploy / build-developer-portal (push) Successful in 56s
Build + Deploy / build-tts (push) Successful in 1m8s
CI/CD / go-lint (push) Has been skipped
Build + Deploy / trigger-orca (push) Has been skipped
CI/CD / python-lint (push) Has been skipped
CI/CD / nodejs-lint (push) Has been skipped
CI/CD / test-go-ai-compliance (push) Successful in 38s
CI/CD / test-python-backend-compliance (push) Successful in 32s
Build + Deploy / build-backend-compliance (push) Successful in 7s
Build + Deploy / build-ai-sdk (push) Successful in 7s
Build + Deploy / build-document-crawler (push) Successful in 33s
Build + Deploy / build-dsms-gateway (push) Successful in 20s
CI/CD / test-python-dsms-gateway (push) Has been cancelled
CI/CD / validate-canonical-controls (push) Has been cancelled
CI/CD / test-python-document-crawler (push) Has been cancelled
All 8 components imported by app/sdk/training/page.tsx were missing. Docker build was failing with Module not found errors. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
90 lines
3.7 KiB
TypeScript
90 lines
3.7 KiB
TypeScript
'use client'
|
|
|
|
import type { TrainingStats, DeadlineInfo } from '@/lib/sdk/training/types'
|
|
import { STATUS_COLORS, STATUS_LABELS } from '@/lib/sdk/training/types'
|
|
|
|
export default function OverviewTab({
|
|
stats,
|
|
deadlines,
|
|
escalationResult,
|
|
onDismissEscalation,
|
|
}: {
|
|
stats: TrainingStats
|
|
deadlines: DeadlineInfo[]
|
|
escalationResult: { total_checked: number; escalated: number } | null
|
|
onDismissEscalation: () => void
|
|
}) {
|
|
return (
|
|
<div className="space-y-6">
|
|
{escalationResult && (
|
|
<div className="bg-orange-50 border border-orange-200 rounded-lg p-4 flex items-center justify-between">
|
|
<div>
|
|
<p className="text-sm font-medium text-orange-800">Eskalationspruefung abgeschlossen</p>
|
|
<p className="text-xs text-orange-600 mt-0.5">
|
|
{escalationResult.total_checked} geprueft, {escalationResult.escalated} eskaliert
|
|
</p>
|
|
</div>
|
|
<button onClick={onDismissEscalation} className="text-xs text-orange-600 underline hover:text-orange-800">
|
|
Schliessen
|
|
</button>
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
<StatCard label="Gesamt Module" value={stats.total_modules} color="blue" />
|
|
<StatCard label="Zuweisungen" value={stats.total_assignments} color="gray" />
|
|
<StatCard label="Abschlussrate" value={`${Math.round(stats.completion_rate)}%`} color="green" />
|
|
<StatCard label="Ueberfaellig" value={stats.overdue_count} color="red" />
|
|
<StatCard label="Ausstehend" value={stats.pending_count} color="yellow" />
|
|
<StatCard label="In Bearbeitung" value={stats.in_progress_count} color="blue" />
|
|
<StatCard label="Abgeschlossen" value={stats.completed_count} color="green" />
|
|
<StatCard label="Ø Quiz-Score" value={`${Math.round(stats.avg_quiz_score)}%`} color="purple" />
|
|
</div>
|
|
|
|
{deadlines.length > 0 && (
|
|
<div className="bg-white border rounded-lg p-4">
|
|
<h3 className="text-sm font-medium text-gray-700 mb-3">Bevorstehende Fristen</h3>
|
|
<div className="space-y-2">
|
|
{deadlines.map(d => {
|
|
const colors = STATUS_COLORS[d.status]
|
|
return (
|
|
<div key={d.assignment_id} className="flex items-center justify-between text-sm py-2 border-b last:border-0">
|
|
<div>
|
|
<span className="font-medium text-gray-900">{d.user_name}</span>
|
|
<span className="text-gray-500 ml-2">{d.module_code} — {d.module_title}</span>
|
|
</div>
|
|
<div className="flex items-center gap-3 shrink-0">
|
|
<span className={`text-xs px-2 py-0.5 rounded-full ${colors.bg} ${colors.text}`}>
|
|
{STATUS_LABELS[d.status]}
|
|
</span>
|
|
<span className={`text-xs font-medium ${d.days_left <= 3 ? 'text-red-600' : d.days_left <= 7 ? 'text-orange-600' : 'text-gray-500'}`}>
|
|
{d.days_left <= 0 ? 'Ueberfaellig' : `${d.days_left}d`}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function StatCard({ label, value, color }: { label: string; value: string | number; color: string }) {
|
|
const colorMap: Record<string, string> = {
|
|
blue: 'text-blue-700',
|
|
green: 'text-green-700',
|
|
red: 'text-red-700',
|
|
yellow: 'text-yellow-700',
|
|
purple: 'text-purple-700',
|
|
gray: 'text-gray-700',
|
|
}
|
|
return (
|
|
<div className="bg-white border rounded-lg p-4">
|
|
<p className="text-xs text-gray-500">{label}</p>
|
|
<p className={`text-2xl font-bold mt-1 ${colorMap[color] ?? 'text-gray-700'}`}>{value}</p>
|
|
</div>
|
|
)
|
|
}
|