From de780524297fcc6475b9330e9bde0acd1b1f585c Mon Sep 17 00:00:00 2001 From: estifanos Date: Tue, 18 Aug 2026 11:43:11 +0000 Subject: [PATCH] feat: add in-flight registration application tracking and status dashboard to vessel registration page --- .../pages/VesselRegistrationPage.tsx | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/apps/portal/src/app/features/vessel-registration/pages/VesselRegistrationPage.tsx b/apps/portal/src/app/features/vessel-registration/pages/VesselRegistrationPage.tsx index b20f20629..3b752cc68 100644 --- a/apps/portal/src/app/features/vessel-registration/pages/VesselRegistrationPage.tsx +++ b/apps/portal/src/app/features/vessel-registration/pages/VesselRegistrationPage.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; import { Alert, Badge, @@ -8,6 +9,7 @@ import { Divider, Group, Paper, + Progress, SimpleGrid, Stack, Text, @@ -25,13 +27,24 @@ import { IconInfoCircle, IconClockHour4, IconTransferIn, + IconArrowRight, } from '@tabler/icons-react'; -import { useApiMutation } from '@ema-platform/api'; +import { + STATUS_COLORS, + STATUS_LABELS, + STATUS_PROGRESS, + TERMINAL_STATUSES, + useApiMutation, + useGetMyApplicationsQuery, +} from '@ema-platform/api'; import { authStorage } from '@ema-platform/auth'; // --------------------------------------------------------------------------- // Types // --------------------------------------------------------------------------- +/** Registration applications run through the config-driven licensing wizard. */ +const REGISTRATION_TYPE_KEY = 'VESSEL_REGISTRATION'; + 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'; @@ -118,6 +131,8 @@ function CertificateCard({ label, description }: { label: string; description: s // --------------------------------------------------------------------------- export function VesselRegistrationPage() { const navigate = useNavigate(); + const { t } = useTranslation(); + const { data: applications } = useGetMyApplicationsQuery(); const [registration, setRegistration] = useState(null); const [fetchTrigger] = useApiMutation(); const fetched = useRef(false); @@ -132,6 +147,14 @@ export function VesselRegistrationPage() { .catch(() => {/* no registration yet */}); }, [fetchTrigger]); + // Drafts and anything still moving through review — the applicant's own + // registration applications, straight from the licensing queue. + const inFlight = (applications?.items ?? []).filter( + (app) => + app.licenseType?.key === REGISTRATION_TYPE_KEY && + !TERMINAL_STATUSES.includes(app.status), + ); + const certs = registration?.category === 'Sea-going Vessel (International)' ? SEAGOING_CERTIFICATES : INLAND_CERTIFICATES; @@ -148,6 +171,54 @@ export function VesselRegistrationPage() { + {/* ── Drafts / submitted applications ───────────────────────────── */} + {inFlight.length > 0 && ( + + {t('vesselRegistration.inFlight.title')} + {inFlight.map((app) => { + const isDraft = app.status === 'DRAFT'; + const needsAction = app.status === 'RESUBMIT_REQUIRED'; + return ( + + +
+ + {app.applicationNumber} + {app.kind === 'RENEWAL' && ( + + {t('vesselRegistration.inFlight.renewalBadge')} + + )} + + +
+ + + {STATUS_LABELS[app.status]} + + + +
+
+ ); + })} +
+ )} + {/* ── No registration yet ───────────────────────────────────────── */} {!registration && ( <>