fix: add missing training page components to fix admin-compliance Docker build
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
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>
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { updateAssignment, completeAssignment } from '@/lib/sdk/training/api'
|
||||
import type { TrainingAssignment } from '@/lib/sdk/training/types'
|
||||
import { STATUS_LABELS, STATUS_COLORS } from '@/lib/sdk/training/types'
|
||||
|
||||
export default function AssignmentDetailDrawer({
|
||||
assignment,
|
||||
onClose,
|
||||
onSaved,
|
||||
}: {
|
||||
assignment: TrainingAssignment
|
||||
onClose: () => void
|
||||
onSaved: () => void
|
||||
}) {
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const colors = STATUS_COLORS[assignment.status]
|
||||
|
||||
async function handleComplete() {
|
||||
if (!window.confirm('Zuweisung als abgeschlossen markieren?')) return
|
||||
setSaving(true)
|
||||
try {
|
||||
await completeAssignment(assignment.id)
|
||||
onSaved()
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Fehler')
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleExtend(e: React.FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault()
|
||||
setSaving(true)
|
||||
setError(null)
|
||||
const fd = new FormData(e.currentTarget)
|
||||
try {
|
||||
await updateAssignment(assignment.id, { deadline: fd.get('deadline') as string })
|
||||
onSaved()
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Fehler beim Aktualisieren')
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex justify-end">
|
||||
<div className="absolute inset-0 bg-black/30" onClick={onClose} />
|
||||
<div className="relative bg-white w-full max-w-md shadow-xl flex flex-col overflow-y-auto">
|
||||
<div className="flex items-center justify-between px-6 py-4 border-b">
|
||||
<h3 className="text-base font-semibold">Zuweisung</h3>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 text-xl">×</button>
|
||||
</div>
|
||||
|
||||
<div className="px-6 py-4 space-y-4 flex-1">
|
||||
{error && (
|
||||
<div className="text-sm text-red-600 bg-red-50 border border-red-200 rounded p-3">{error}</div>
|
||||
)}
|
||||
|
||||
<div className="space-y-2">
|
||||
<Row label="Nutzer" value={`${assignment.user_name} (${assignment.user_email})`} />
|
||||
<Row label="Modul" value={`${assignment.module_code ?? ''} ${assignment.module_title ?? assignment.module_id.slice(0, 8)}`} />
|
||||
<Row label="Status">
|
||||
<span className={`text-xs px-2 py-0.5 rounded-full ${colors.bg} ${colors.text}`}>
|
||||
{STATUS_LABELS[assignment.status]}
|
||||
</span>
|
||||
</Row>
|
||||
<Row label="Fortschritt" value={`${assignment.progress_percent}%`} />
|
||||
<Row label="Frist" value={new Date(assignment.deadline).toLocaleDateString('de-DE')} />
|
||||
{assignment.started_at && <Row label="Gestartet" value={new Date(assignment.started_at).toLocaleString('de-DE')} />}
|
||||
{assignment.completed_at && <Row label="Abgeschlossen" value={new Date(assignment.completed_at).toLocaleString('de-DE')} />}
|
||||
{assignment.quiz_score != null && (
|
||||
<Row label="Quiz-Score" value={`${Math.round(assignment.quiz_score)}% (${assignment.quiz_passed ? 'Bestanden' : 'Nicht bestanden'})`} />
|
||||
)}
|
||||
<Row label="Quiz-Versuche" value={String(assignment.quiz_attempts)} />
|
||||
{assignment.escalation_level > 0 && (
|
||||
<Row label="Eskalationsstufe" value={String(assignment.escalation_level)} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{assignment.status !== 'completed' && (
|
||||
<div className="border rounded-lg p-4 space-y-3">
|
||||
<h4 className="text-sm font-medium text-gray-700">Frist verlaengern</h4>
|
||||
<form onSubmit={handleExtend} className="flex gap-2">
|
||||
<input
|
||||
name="deadline"
|
||||
type="date"
|
||||
defaultValue={assignment.deadline.slice(0, 10)}
|
||||
className="flex-1 px-3 py-2 text-sm border rounded-lg"
|
||||
/>
|
||||
<button type="submit" disabled={saving} className="px-3 py-2 text-sm bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50">
|
||||
Speichern
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{assignment.status !== 'completed' && (
|
||||
<div className="px-6 py-4 border-t">
|
||||
<button
|
||||
onClick={handleComplete}
|
||||
disabled={saving}
|
||||
className="w-full px-4 py-2 text-sm bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50"
|
||||
>
|
||||
Als abgeschlossen markieren
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Row({ label, value, children }: { label: string; value?: string; children?: React.ReactNode }) {
|
||||
return (
|
||||
<div className="flex gap-2 text-sm">
|
||||
<span className="text-gray-500 w-36 shrink-0">{label}:</span>
|
||||
{children ?? <span className="text-gray-900">{value}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user