From 5897e7344213f0ac46cf839a27e411774abf97fd Mon Sep 17 00:00:00 2001 From: estifanos Date: Tue, 18 Aug 2026 10:37:57 +0000 Subject: [PATCH] feat: add status filtering and display to medical and sea service verification queues --- .../pages/MedicalVerificationPage/actions.tsx | 80 ++++++++++--------- .../pages/MedicalVerificationPage/columns.tsx | 25 ++++++ .../pages/MedicalVerificationPage/index.tsx | 48 +++++++++-- .../src/lib/features/seafarer/seafarer-api.ts | 21 ++++- .../lib/features/seafarer/seafarer.types.ts | 3 + 5 files changed, 132 insertions(+), 45 deletions(-) diff --git a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/actions.tsx b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/actions.tsx index 6c1ce955a..59f9045a8 100644 --- a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/actions.tsx +++ b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/actions.tsx @@ -33,24 +33,28 @@ export function medicalActionsColumn( anyOf={[LICENSE_PERMISSIONS.VERIFY_SEAFARER_RECORDS]} hideOnly > - - + {row.original.status === 'SUBMITTED' && ( + <> + + + + )} ), @@ -85,24 +89,28 @@ export function seaServiceActionsColumn( anyOf={[LICENSE_PERMISSIONS.VERIFY_SEAFARER_RECORDS]} hideOnly > - - + {row.original.status === 'SUBMITTED' && ( + <> + + + + )} ), diff --git a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/columns.tsx b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/columns.tsx index 9712b6719..d76514579 100644 --- a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/columns.tsx +++ b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/columns.tsx @@ -5,6 +5,7 @@ import type { MedicalCertificate, SeaServiceRecord, SeafarerProfileSummary, + SeafarerRecordStatus, } from '@ema-platform/api'; export function ownerName(profile?: SeafarerProfileSummary): string { @@ -16,6 +17,28 @@ export function ownerName(profile?: SeafarerProfileSummary): string { ); } +const STATUS_COLOR: Record = { + SUBMITTED: 'yellow', + VERIFIED: 'teal', + REJECTED: 'red', +}; + +/** Only meaningful now the queue can show ruled records too. */ +function statusColumn( + t: TFunction, +): AdvancedColumn { + return { + header: t('recordVerification.columns.status', 'Status'), + label: t('recordVerification.columns.status', 'Status'), + accessorKey: 'status', + cell: ({ row }) => ( + + {t(`recordVerification.status.${row.original.status}`, row.original.status)} + + ), + }; +} + export function medicalColumns( t: TFunction, showDate: (date: string) => string, @@ -72,6 +95,7 @@ export function medicalColumns( ), }, + statusColumn(t), ]; } @@ -127,5 +151,6 @@ export function seaServiceColumns( ), }, + statusColumn(t), ]; } diff --git a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/index.tsx b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/index.tsx index 018208283..28cc3e63d 100644 --- a/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/index.tsx +++ b/apps/backoffice/src/app/features/medical-verification/pages/MedicalVerificationPage/index.tsx @@ -9,6 +9,7 @@ import { Loader, Modal, Paper, + SegmentedControl, Stack, Tabs, Text, @@ -32,7 +33,11 @@ import { useVerifyMedicalCertificateMutation, useVerifySeaServiceRecordMutation, } from '@ema-platform/api'; -import type { MedicalCertificate, SeaServiceRecord } from '@ema-platform/api'; +import type { + MedicalCertificate, + RecordQueueFilter, + SeaServiceRecord, +} from '@ema-platform/api'; import { medicalColumns, seaServiceColumns, ownerName } from './columns'; import { medicalActionsColumn, seaServiceActionsColumn } from './actions'; @@ -180,19 +185,20 @@ function AttachmentsModal({ */ export function MedicalVerificationPage() { const { t } = useTranslation(); + const [filter, setFilter] = useState('SUBMITTED'); const { data: pendingMedical, isLoading: loadingMedical, isFetching: fetchingMedical, refetch: refetchMedical, - } = useGetPendingMedicalQuery(); + } = useGetPendingMedicalQuery(filter); const { data: pendingSeaService, isLoading: loadingSeaService, isFetching: fetchingSeaService, refetch: refetchSeaService, - } = useGetPendingSeaServiceQuery(); + } = useGetPendingSeaServiceQuery(filter); const [verifyMedical, { isLoading: rulingMedical }] = useVerifyMedicalCertificateMutation(); @@ -251,6 +257,12 @@ export function MedicalVerificationPage() { return pendingSeaServiceList.slice(start, start + seaServicePageSize); }, [pendingSeaServiceList, seaServicePage, seaServicePageSize]); + const changeFilter = useCallback((value: string) => { + setFilter(value as RecordQueueFilter); + setMedicalPage(0); + setSeaServicePage(0); + }, []); + const handleMedicalPageSizeChange = useCallback((size: number) => { setMedicalPageSize(size); setMedicalPage(0); @@ -261,6 +273,11 @@ export function MedicalVerificationPage() { setSeaServicePage(0); }, []); + const emptyText = + filter === 'SUBMITTED' + ? t('recordVerification.emptyText', 'Nothing awaiting verification.') + : t('recordVerification.emptyTextFiltered', 'No records match this filter.'); + const medicalTableColumns: AdvancedColumn[] = useMemo( () => [ ...medicalColumns(t, showDate), @@ -331,6 +348,27 @@ export function MedicalVerificationPage() { )} + + }> @@ -362,7 +400,7 @@ export function MedicalVerificationPage() { onPageSizeChange={handleMedicalPageSizeChange} refresh={refetchMedical} isLoading={loadingMedical || fetchingMedical} - emptyText={t('recordVerification.emptyText', 'Nothing awaiting verification.')} + emptyText={emptyText} /> @@ -381,7 +419,7 @@ export function MedicalVerificationPage() { onPageSizeChange={handleSeaServicePageSizeChange} refresh={refetchSeaService} isLoading={loadingSeaService || fetchingSeaService} - emptyText={t('recordVerification.emptyText', 'Nothing awaiting verification.')} + emptyText={emptyText} /> diff --git a/libs/api/src/lib/features/seafarer/seafarer-api.ts b/libs/api/src/lib/features/seafarer/seafarer-api.ts index 98c2a8bc9..23c1e5f0f 100644 --- a/libs/api/src/lib/features/seafarer/seafarer-api.ts +++ b/libs/api/src/lib/features/seafarer/seafarer-api.ts @@ -3,6 +3,7 @@ import type { CreateMedicalCertificate, CreateSeaServiceRecord, MedicalCertificate, + RecordQueueFilter, SeaServiceRecord, SeaTimeSummary, SeafarerStatus, @@ -104,13 +105,25 @@ export const seafarerApi = baseApi }), // -------------------------------------------------------- verification - getPendingSeaService: builder.query({ - query: () => ({ url: '/sea-service-records/pending' }), + getPendingSeaService: builder.query< + SeaServiceRecord[], + RecordQueueFilter | void + >({ + query: (status) => ({ + url: '/sea-service-records/pending', + params: { status: status || 'SUBMITTED' }, + }), providesTags: () => [listTag('SeaServiceRecord')], }), - getPendingMedical: builder.query({ - query: () => ({ url: '/medical-certificates/pending' }), + getPendingMedical: builder.query< + MedicalCertificate[], + RecordQueueFilter | void + >({ + query: (status) => ({ + url: '/medical-certificates/pending', + params: { status: status || 'SUBMITTED' }, + }), providesTags: () => [listTag('MedicalCertificate')], }), diff --git a/libs/api/src/lib/features/seafarer/seafarer.types.ts b/libs/api/src/lib/features/seafarer/seafarer.types.ts index 140159fab..a53706efe 100644 --- a/libs/api/src/lib/features/seafarer/seafarer.types.ts +++ b/libs/api/src/lib/features/seafarer/seafarer.types.ts @@ -1,4 +1,7 @@ export type SeafarerRecordStatus = 'SUBMITTED' | 'VERIFIED' | 'REJECTED'; + +/** Verification-queue filter: a record status, or ALL for no filter. */ +export type RecordQueueFilter = SeafarerRecordStatus | 'ALL'; export type MedicalFitness = 'FIT' | 'FIT_WITH_RESTRICTIONS' | 'UNFIT'; export type SeafarerDepartment = 'DECK' | 'ENGINE' | 'CATERING'; export type SeafarerStatus = 'ACTIVE' | 'INACTIVE' | 'PENDING' | 'SUSPENDED';