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

This commit is contained in:
estifanos
2026-08-28 07:32:31 +00:00
parent 51627f9918
commit 6d2c01ae73

View File

@@ -45,9 +45,9 @@ const CATEGORY_ICONS: Record<LicenseCategory, typeof IconShip> = {
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/<key>/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.