From 6d2c01ae73409b5752f4bfbe7bd74ef89ee8cba3 Mon Sep 17 00:00:00 2001 From: estifanos Date: Fri, 28 Aug 2026 07:32:31 +0000 Subject: [PATCH] feat: allow applicants to view declared personal licenses in the catalogue by expanding the filter to include non-logistics family types present in the user declaration --- .../licensing/components/LicenseCatalogue.tsx | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/portal/src/app/features/licensing/components/LicenseCatalogue.tsx b/apps/portal/src/app/features/licensing/components/LicenseCatalogue.tsx index d6a11871c..b4dedc212 100644 --- a/apps/portal/src/app/features/licensing/components/LicenseCatalogue.tsx +++ b/apps/portal/src/app/features/licensing/components/LicenseCatalogue.tsx @@ -45,9 +45,9 @@ const CATEGORY_ICONS: Record = { CARGO_FREIGHT: IconBuildingWarehouse, SHIPPING_AGENCY: IconShip, INVESTMENT: IconTrendingUp, - // The three below are filtered out of this catalogue today - // (requiresOperatorMode is false for all of them), and are listed only so - // the record stays total if that ever changes. + // The three below appear only when the applicant has declared a licence + // type in them (see the family filter below); listed here so the record + // stays total either way. MARITIME_PERSONNEL: IconShip, VESSEL_SERVICES: IconAnchor, WAIVER_SERVICES: IconShieldOff, @@ -81,15 +81,19 @@ export function LicenseCatalogue() { const { groups, orphans } = useMemo(() => { const active = (types?.items ?? []) .filter((t) => t.isActive) - // Logistics licences only: this is the operator catalogue, not the - // seafarer certificate or vessel/seafarer document catalogue — those - // have their own entry points. `familyKind` is the real data-model - // classification (set on the type at seed time); `requiresOperatorMode` - // was the proxy this used before that column existed and happened to - // agree for every type seeded so far, but a type can only be trusted to - // stay in sync with the catalogue it belongs in if the catalogue reads - // its actual family instead of a flag with a different purpose. - .filter((t) => t.familyKind === 'LOGISTICS_LICENSE') + // The logistics family, plus whatever this applicant actually declared. + // + // `familyKind` is the real data-model classification and is what keeps + // browse-all to the operator catalogue rather than every certificate and + // document type in the system. But it is not what decides eligibility: + // the Operations tab also offers the personal registrations (seafarer, + // vessel) and the seafarer endorsement, which are DOCUMENT/CERTIFICATE + // family, so an applicant who declared one of those was shown an empty + // catalogue — allowed to file, and offered nothing to file. Each of + // those keys already has an entry point at `/licensing//apply` + // (a router redirect for SEAFARER_REGISTRATION and SEAMAN_BOOK, the + // generic wizard for the rest), so the card leads somewhere real. + .filter((t) => t.familyKind === 'LOGISTICS_LICENSE' || declared.has(t.id)) // Only what the applicant operates as. The server enforces the same rule // on create; this is what stops them starting an application they will // be refused at the end of.