Files
emaui/apps/backoffice/src/app/features/exam/components/ExamCandidatesPanel/columns.tsx
Nati 2af9e60800 feat(vessel-registration): add vessel registration page with incident reporting and certificate download functionality
feat(waiver): implement waiver page with application tracking and letter download feature

feat(ui): introduce AdvancedTable component for enhanced table functionality across the application

chore: update package-lock.json to remove unnecessary dependencies
2026-08-13 09:11:50 +00:00

97 lines
2.6 KiB
TypeScript

import { Badge, Button, Text } from '@mantine/core';
import { IconUserCheck } from '@tabler/icons-react';
import type { TFunction } from 'i18next';
import type { AdvancedTableColumn } from '@ema-platform/ui';
import type { AttendanceStatus, ExamRegistration } from '../../types/exam';
const ATTENDANCE_COLOR: Record<AttendanceStatus, string> = {
REGISTERED: 'gray',
PRESENT: 'teal',
LATE: 'yellow',
ABSENT: 'red',
WITHDRAWN: 'orange',
DISQUALIFIED: 'red',
};
export const candidateName = (registration: ExamRegistration) =>
[
registration.profile?.firstName,
registration.profile?.middleName,
registration.profile?.lastName,
]
.filter(Boolean)
.join(' ') || registration.profileId.slice(0, 8);
export function examCandidateColumns(
t: TFunction,
handlers: { onRecord: (registration: ExamRegistration) => void },
): AdvancedTableColumn<ExamRegistration>[] {
return [
{
key: 'admission',
header: t('exam.candidates.admission'),
render: (registration) => (
<Text fz="sm" ff="monospace" fw={600}>
{registration.admissionNumber}
</Text>
),
},
{
key: 'name',
header: t('exam.candidates.name'),
render: (registration) => <Text fz="sm">{candidateName(registration)}</Text>,
},
{
key: 'attempt',
header: t('exam.candidates.attempt'),
render: (registration) => (
<Badge
size="sm"
variant="light"
color={registration.kind === 'RETAKE' ? 'orange' : 'blue'}
>
{registration.kind === 'RETAKE'
? t('exam.candidates.retake', { n: registration.attemptNumber })
: t('exam.candidates.firstSitting')}
</Badge>
),
},
{
key: 'attendance',
header: t('exam.candidates.attendance'),
render: (registration) => (
<Badge
size="sm"
variant="light"
color={ATTENDANCE_COLOR[registration.attendanceStatus] ?? 'gray'}
>
{t(`exam.attendance.${registration.attendanceStatus}`)}
</Badge>
),
},
{
key: 'remark',
header: t('exam.candidates.remark'),
render: (registration) => (
<Text fz="xs" c="dimmed" maw={220} lineClamp={2}>
{registration.attendanceRemark ?? '—'}
</Text>
),
},
{
key: 'record',
header: '',
render: (registration) => (
<Button
size="compact-xs"
variant="light"
leftSection={<IconUserCheck size={12} />}
onClick={() => handlers.onRecord(registration)}
>
{t('exam.candidates.record')}
</Button>
),
},
];
}