Files
breakpilot-compliance/admin-compliance/app/sdk/training/_components/AssignmentsTab.tsx
Sharang Parnerkar 375b34a0d8 refactor(admin): split consent-management, control-library, incidents, training pages
Agent-completed splits committed after agents hit rate limits before
committing their work. All 4 pages now under 500 LOC:

- consent-management: 1303 -> 193 LOC (+ 7 _components, _hooks, _data, _types)
- control-library: 1210 -> 298 LOC (+ _components, _types)
- incidents: 1150 -> 373 LOC (+ _components)
- training: 1127 -> 366 LOC (+ _components)

Verification: next build clean (142 pages generated).

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

86 lines
4.1 KiB
TypeScript

'use client'
import type { TrainingAssignment } from '@/lib/sdk/training/types'
import { STATUS_LABELS, STATUS_COLORS } from '@/lib/sdk/training/types'
interface AssignmentsTabProps {
assignments: TrainingAssignment[]
statusFilter: string
onStatusFilterChange: (value: string) => void
onAssignmentClick: (a: TrainingAssignment) => void
}
export function AssignmentsTab({ assignments, statusFilter, onStatusFilterChange, onAssignmentClick }: AssignmentsTabProps) {
return (
<div className="space-y-4">
<div className="flex gap-3">
<select value={statusFilter} onChange={e => onStatusFilterChange(e.target.value)} className="px-3 py-1.5 text-sm border rounded-lg bg-white">
<option value="">Alle Status</option>
{Object.entries(STATUS_LABELS).map(([key, label]) => (
<option key={key} value={key}>{label}</option>
))}
</select>
</div>
<div className="overflow-x-auto">
<table className="w-full text-sm border-collapse">
<thead>
<tr className="bg-gray-50">
<th className="text-left p-2 border font-medium text-gray-700">Modul</th>
<th className="text-left p-2 border font-medium text-gray-700">Mitarbeiter</th>
<th className="text-left p-2 border font-medium text-gray-700">Rolle</th>
<th className="text-center p-2 border font-medium text-gray-700">Fortschritt</th>
<th className="text-center p-2 border font-medium text-gray-700">Status</th>
<th className="text-center p-2 border font-medium text-gray-700">Quiz</th>
<th className="text-left p-2 border font-medium text-gray-700">Deadline</th>
<th className="text-center p-2 border font-medium text-gray-700">Eskalation</th>
</tr>
</thead>
<tbody>
{assignments.map(a => (
<tr
key={a.id}
onClick={() => onAssignmentClick(a)}
className="border-b hover:bg-gray-50 cursor-pointer"
>
<td className="p-2 border">
<div className="font-medium">{a.module_title || a.module_code}</div>
<div className="text-xs text-gray-500">{a.module_code}</div>
</td>
<td className="p-2 border">
<div>{a.user_name}</div>
<div className="text-xs text-gray-500">{a.user_email}</div>
</td>
<td className="p-2 border text-xs">{a.role_code || '-'}</td>
<td className="p-2 border text-center">
<div className="flex items-center gap-2">
<div className="flex-1 bg-gray-200 rounded-full h-2">
<div className="bg-blue-500 h-2 rounded-full" style={{ width: `${a.progress_percent}%` }} />
</div>
<span className="text-xs w-8">{a.progress_percent}%</span>
</div>
</td>
<td className="p-2 border text-center">
<span className={`px-2 py-0.5 rounded text-xs ${STATUS_COLORS[a.status]?.bg || ''} ${STATUS_COLORS[a.status]?.text || ''}`}>
{STATUS_LABELS[a.status] || a.status}
</span>
</td>
<td className="p-2 border text-center text-xs">
{a.quiz_score != null ? (
<span className={`font-medium ${a.quiz_passed ? 'text-green-600' : 'text-red-600'}`}>{a.quiz_score.toFixed(0)}%</span>
) : '-'}
</td>
<td className="p-2 border text-xs">{new Date(a.deadline).toLocaleDateString('de-DE')}</td>
<td className="p-2 border text-center">
{a.escalation_level > 0 ? <span className="px-2 py-0.5 rounded text-xs bg-red-100 text-red-700">L{a.escalation_level}</span> : '-'}
</td>
</tr>
))}
</tbody>
</table>
</div>
{assignments.length === 0 && <p className="text-center text-gray-500 py-8">Keine Zuweisungen</p>}
</div>
)
}