Add review status column and enhance action buttons in ResultPage

This commit is contained in:
estifanos
2026-08-08 06:29:28 +00:00
parent 23675005fc
commit c006644166

View File

@@ -334,6 +334,14 @@ export function ResultPage() {
</Badge>
),
},
{
header: t('result.review.column'),
cell: ({ row }) => (
<Badge size="sm" variant="light" color={REVIEW_COLOR[row.original.reviewStatus] ?? 'gray'}>
{t(`result.review.${row.original.reviewStatus}`)}
</Badge>
),
},
{
header: t('result.columns.date'),
cell: ({ row }) => <Text fz="sm">{new Date(row.original.createdAt).toLocaleDateString()}</Text>,
@@ -341,22 +349,40 @@ export function ResultPage() {
{
header: '',
label: t('result.columns.actions', 'Actions'),
cell: ({ row }) => (
<Group gap="xs">
<Button size="xs" variant="subtle" leftSection={<IconEye size={13} />} onClick={() => viewDetail(row.original)}>
{t('result.action.viewEdit')}
</Button>
<Button
size="xs"
variant="subtle"
color="red"
leftSection={<IconTrash size={13} />}
onClick={() => { setDeleteTarget(row.original); openDelete(); }}
>
{t('result.action.delete')}
</Button>
</Group>
),
cell: ({ row }) => {
const r = row.original;
return (
<Group gap="xs">
{(r.reviewStatus === 'MARKED' || r.reviewStatus === 'MODERATED') && (
<>
<Button size="compact-xs" variant="light" color="yellow" onClick={() => openQc(r, 'moderate')}>
{t('result.review.moderate')}
</Button>
<Button size="compact-xs" variant="light" color="blue" onClick={() => openQc(r, 'approve')}>
{t('result.review.approve')}
</Button>
</>
)}
{(r.reviewStatus === 'APPROVED' || r.reviewStatus === 'MODERATED') && (
<Button size="compact-xs" variant="subtle" color="orange" onClick={() => openQc(r, 'return')}>
{t('result.review.return')}
</Button>
)}
<Button size="xs" variant="subtle" leftSection={<IconEye size={13} />} onClick={() => viewDetail(r)}>
{t('result.action.viewEdit')}
</Button>
<Button
size="xs"
variant="subtle"
color="red"
leftSection={<IconTrash size={13} />}
onClick={() => { setDeleteTarget(r); openDelete(); }}
>
{t('result.action.delete')}
</Button>
</Group>
);
},
},
];
@@ -418,113 +444,19 @@ export function ResultPage() {
</Group>
</Group>
<Table striped highlightOnHover>
<Table.Thead bg="var(--mantine-color-default-hover)">
<Table.Tr>
<Table.Th>{t('result.columns.seafarer')}</Table.Th>
<Table.Th>{t('result.columns.exam')}</Table.Th>
<Table.Th>{t('result.columns.totalScore')}</Table.Th>
<Table.Th>{t('result.columns.status')}</Table.Th>
<Table.Th>{t('result.review.column')}</Table.Th>
<Table.Th>{t('result.columns.date')}</Table.Th>
<Table.Th />
</Table.Tr>
</Table.Thead>
<Table.Tbody>
{filtered.map((r) => (
<Table.Tr key={r.id}>
<Table.Td>
<Text fz="sm" fw={500}>
{r.seafarer ? `${r.seafarer.firstName} ${r.seafarer.lastName}` : r.seafarerId.slice(0, 8)}
</Text>
</Table.Td>
<Table.Td><Text fz="sm">{r.exam ? r.exam.title[locale] : getExamTitle(r.examId)}</Text></Table.Td>
<Table.Td><Text fz="sm" fw={600}>{r.totalScore}</Text></Table.Td>
<Table.Td>
<Badge
size="sm"
variant="light"
color={STATUS_COLOR[r.status]}
leftSection={
<Box
w={6}
h={6}
style={{ borderRadius: 999, background: `var(--mantine-color-${STATUS_COLOR[r.status]}-6)` }}
/>
}
>
{t(`result.status.${r.status}`)}
</Badge>
</Table.Td>
<Table.Td>
<Badge size="sm" variant="light" color={REVIEW_COLOR[r.reviewStatus] ?? 'gray'}>
{t(`result.review.${r.reviewStatus}`)}
</Badge>
</Table.Td>
<Table.Td><Text fz="sm">{new Date(r.createdAt).toLocaleDateString()}</Text></Table.Td>
<Table.Td>
<Group gap="xs">
{(r.reviewStatus === 'MARKED' || r.reviewStatus === 'MODERATED') && (
<>
<Button
size="compact-xs"
variant="light"
color="yellow"
onClick={() => openQc(r, 'moderate')}
>
{t('result.review.moderate')}
</Button>
<Button
size="compact-xs"
variant="light"
color="blue"
onClick={() => openQc(r, 'approve')}
>
{t('result.review.approve')}
</Button>
</>
)}
{(r.reviewStatus === 'APPROVED' || r.reviewStatus === 'MODERATED') && (
<Button
size="compact-xs"
variant="subtle"
color="orange"
onClick={() => openQc(r, 'return')}
>
{t('result.review.return')}
</Button>
)}
<Button
size="xs"
variant="subtle"
leftSection={<IconEye size={13} />}
onClick={() => viewDetail(r)}
>
{t('result.action.viewEdit')}
</Button>
<Button
size="xs"
variant="subtle"
color="red"
leftSection={<IconTrash size={13} />}
onClick={() => { setDeleteTarget(r); openDelete(); }}
>
{t('result.action.delete')}
</Button>
</Group>
</Table.Td>
</Table.Tr>
))}
{filtered.length === 0 && (
<Table.Tr>
<Table.Td colSpan={7}>
<Text c="dimmed" ta="center" py="xl">{t('result.noItems')}</Text>
</Table.Td>
</Table.Tr>
)}
</Table.Tbody>
</Table>
</Paper>
<AdvancedTable
columns={columns}
data={page.rows}
tableName={t('result.title')}
itemCount={page.itemCount}
pageIndex={page.pageIndex}
onPageChange={setPageIndex}
pageSize={pageSize}
refresh={refetch}
isLoading={isFetching}
emptyText={t('result.noItems')}
/>
</Card>
<Modal
opened={detailOpened}