mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-26 13:02:50 +00:00
UI improvements
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
import { Badge, Button, Group, Progress, Text } from '@mantine/core';
|
||||
import { IconArrowRight } from '@tabler/icons-react';
|
||||
import type { TFunction } from 'i18next';
|
||||
import type { AdvancedColumn } from '@ema-platform/ui';
|
||||
import {
|
||||
STATUS_COLORS,
|
||||
STATUS_LABELS,
|
||||
STATUS_PROGRESS,
|
||||
type LicenseApplication,
|
||||
} from '@ema-platform/api';
|
||||
|
||||
/** Columns for the applicant's in-flight vessel registration applications. */
|
||||
export function inFlightColumns(
|
||||
t: TFunction,
|
||||
deps: { onOpen: (app: LicenseApplication) => void },
|
||||
): AdvancedColumn<LicenseApplication>[] {
|
||||
return [
|
||||
{
|
||||
header: t('applications.table.applicationNumber'),
|
||||
cell: ({ row }) => (
|
||||
<Group gap="xs" wrap="nowrap">
|
||||
<Text fw={600} fz="sm">{row.original.applicationNumber}</Text>
|
||||
{row.original.kind === 'RENEWAL' && (
|
||||
<Badge size="sm" variant="light">
|
||||
{t('vesselRegistration.inFlight.renewalBadge')}
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: t('common.status'),
|
||||
cell: ({ row }) => (
|
||||
<Badge color={STATUS_COLORS[row.original.status]} variant="light">
|
||||
{STATUS_LABELS[row.original.status]}
|
||||
</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: t('applications.table.progress'),
|
||||
size: 140,
|
||||
cell: ({ row }) => (
|
||||
<Progress
|
||||
value={STATUS_PROGRESS[row.original.status]}
|
||||
color={STATUS_COLORS[row.original.status]}
|
||||
size="sm"
|
||||
radius="xl"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
header: '',
|
||||
label: t('common.actions'),
|
||||
align: 'right',
|
||||
cell: ({ row }) => {
|
||||
const app = row.original;
|
||||
const needsAction = app.status === 'RESUBMIT_REQUIRED';
|
||||
return (
|
||||
<Button
|
||||
size="compact-sm"
|
||||
variant={needsAction ? 'filled' : 'light'}
|
||||
color={needsAction ? 'orange' : undefined}
|
||||
rightSection={<IconArrowRight size={14} />}
|
||||
onClick={() => deps.onOpen(app)}
|
||||
>
|
||||
{app.status === 'DRAFT'
|
||||
? t('common.continue')
|
||||
: needsAction
|
||||
? t('vesselRegistration.inFlight.fix')
|
||||
: t('vesselRegistration.inFlight.view')}
|
||||
</Button>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -9,7 +9,6 @@ import {
|
||||
Divider,
|
||||
Group,
|
||||
Paper,
|
||||
Progress,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text,
|
||||
@@ -27,12 +26,10 @@ import {
|
||||
IconInfoCircle,
|
||||
IconClockHour4,
|
||||
IconTransferIn,
|
||||
IconArrowRight,
|
||||
} from '@tabler/icons-react';
|
||||
import { AdvancedTable } from '@ema-platform/ui';
|
||||
import { inFlightColumns } from '../inFlightColumns';
|
||||
import {
|
||||
STATUS_COLORS,
|
||||
STATUS_LABELS,
|
||||
STATUS_PROGRESS,
|
||||
TERMINAL_STATUSES,
|
||||
useApiMutation,
|
||||
useGetMyApplicationsQuery,
|
||||
@@ -45,6 +42,8 @@ import { authStorage } from '@ema-platform/auth';
|
||||
/** Registration applications run through the config-driven licensing wizard. */
|
||||
const REGISTRATION_TYPE_KEY = 'VESSEL_REGISTRATION';
|
||||
|
||||
const PAGE_SIZE = 5;
|
||||
|
||||
type VesselRegStatus = 'Pending' | 'Under Review' | 'Approved' | 'Rejected' | 'Correction Required';
|
||||
type VesselCategory = 'Inland Waterway Vessel' | 'Sea-going Vessel (International)';
|
||||
type RenewalStatus = 'Valid' | 'Due Soon' | 'Overdue' | 'Not Applicable';
|
||||
@@ -133,6 +132,7 @@ export function VesselRegistrationPage() {
|
||||
const navigate = useNavigate();
|
||||
const { t } = useTranslation();
|
||||
const { data: applications } = useGetMyApplicationsQuery();
|
||||
const [page, setPage] = useState(0);
|
||||
const [registration, setRegistration] = useState<VesselRegistration | null>(null);
|
||||
const [fetchTrigger] = useApiMutation<VesselRegistration>();
|
||||
const fetched = useRef(false);
|
||||
@@ -155,6 +155,11 @@ export function VesselRegistrationPage() {
|
||||
!TERMINAL_STATUSES.includes(app.status),
|
||||
);
|
||||
|
||||
const columns = inFlightColumns(t, {
|
||||
onOpen: (app) =>
|
||||
navigate(`/licensing/${REGISTRATION_TYPE_KEY}/applications/${app.id}`),
|
||||
});
|
||||
|
||||
const certs = registration?.category === 'Sea-going Vessel (International)'
|
||||
? SEAGOING_CERTIFICATES
|
||||
: INLAND_CERTIFICATES;
|
||||
@@ -175,47 +180,16 @@ export function VesselRegistrationPage() {
|
||||
{inFlight.length > 0 && (
|
||||
<Stack gap="sm">
|
||||
<Text fw={700} fz="md">{t('vesselRegistration.inFlight.title')}</Text>
|
||||
{inFlight.map((app) => {
|
||||
const isDraft = app.status === 'DRAFT';
|
||||
const needsAction = app.status === 'RESUBMIT_REQUIRED';
|
||||
return (
|
||||
<Card key={app.id} withBorder radius="md" p="md">
|
||||
<Group justify="space-between" wrap="nowrap">
|
||||
<div>
|
||||
<Group gap="xs">
|
||||
<Text fw={600}>{app.applicationNumber}</Text>
|
||||
{app.kind === 'RENEWAL' && (
|
||||
<Badge size="sm" variant="light">
|
||||
{t('vesselRegistration.inFlight.renewalBadge')}
|
||||
</Badge>
|
||||
)}
|
||||
</Group>
|
||||
<Progress value={STATUS_PROGRESS[app.status]} mt="xs" w={260} />
|
||||
</div>
|
||||
<Group wrap="nowrap">
|
||||
<Badge color={STATUS_COLORS[app.status]}>
|
||||
{STATUS_LABELS[app.status]}
|
||||
</Badge>
|
||||
<Button
|
||||
size="compact-sm"
|
||||
variant={needsAction ? 'filled' : 'light'}
|
||||
color={needsAction ? 'orange' : undefined}
|
||||
rightSection={<IconArrowRight size={14} />}
|
||||
onClick={() =>
|
||||
navigate(`/licensing/${REGISTRATION_TYPE_KEY}/applications/${app.id}`)
|
||||
}
|
||||
>
|
||||
{isDraft
|
||||
? t('common.continue')
|
||||
: needsAction
|
||||
? t('vesselRegistration.inFlight.fix')
|
||||
: t('vesselRegistration.inFlight.view')}
|
||||
</Button>
|
||||
</Group>
|
||||
</Group>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
<AdvancedTable
|
||||
tableName="vessel-registration-in-flight"
|
||||
columns={columns}
|
||||
// Client-side paging: getMyApplications returns the whole list.
|
||||
data={inFlight.slice(page * PAGE_SIZE, (page + 1) * PAGE_SIZE)}
|
||||
itemCount={inFlight.length}
|
||||
pageIndex={page}
|
||||
pageSize={PAGE_SIZE}
|
||||
onPageChange={setPage}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
|
||||
@@ -208,6 +208,7 @@ export const am: Translations = {
|
||||
licence: 'ፍቃድ',
|
||||
applicant: 'አመልካች',
|
||||
progress: 'ደረጃ',
|
||||
applicationNumber: 'የማመልከቻ ቁጥር',
|
||||
},
|
||||
actions: {
|
||||
continue: 'ቀጥል',
|
||||
|
||||
@@ -207,6 +207,7 @@ export const en = {
|
||||
licence: 'Licence',
|
||||
applicant: 'Applicant',
|
||||
progress: 'Progress',
|
||||
applicationNumber: 'Application №',
|
||||
},
|
||||
actions: {
|
||||
continue: 'Continue',
|
||||
|
||||
Reference in New Issue
Block a user