Files
emaui/apps/backoffice/src/app/layouts/nav-config.ts
Nati 357dc3e4d5 feat: add document requirements and form schema management for license types
- Implement DocumentRequirementsTab for managing document upload requirements.
- Create FieldEditorDrawer and SectionEditorDrawer for editing fields and sections in the form schema.
- Develop FormSchemaTab to handle sections and fields for a license type's form schema.
- Introduce CertificateRequirementsPage to serve as the main interface for configuring license type requirements.
- Add hooks for requirement actions to streamline mutation handling and notifications.
- Implement condition handling for fields and sections to manage visibility based on user input.
- Create schema-paths configuration to facilitate condition target collection.
2026-08-20 13:37:26 +00:00

181 lines
7.5 KiB
TypeScript

import {
IconAnchor,
IconArrowsExchange,
IconBook2,
IconChartBar,
IconClipboardList,
IconClipboardText,
IconCreditCard,
IconFileDescription,
IconFilePlus,
IconGauge,
IconGavel,
IconHeart,
IconId,
IconLayoutDashboard,
IconListCheck,
IconQuestionMark,
IconReport,
IconRosetteDiscountCheck,
IconRubberStamp,
IconSettings,
IconShieldCheck,
IconShieldOff,
IconShip,
IconTruck,
IconUsers,
IconUserShield,
} from '@tabler/icons-react';
import type { NavSection } from '@ema-platform/ui';
import { LICENSE_PERMISSIONS as P } from '@ema-platform/auth';
/**
* Every licence-type queue and its review workspace share one gate: the
* licence application queue permissions, granted as any-of.
*/
const APPLICATION_QUEUE = [P.VIEW_APPLICATION_QUEUE, P.VIEW_APPLICATIONS];
/**
* The backoffice information architecture.
*
* Seven top-level groups, none deeper than one level of nesting. `soon` marks
* screens with no backend behind them, so a reviewer can tell at a glance what
* actually works.
*
* `groupLicensing` is scoped strictly to logistics-operator licences (the
* permission a company holds to trade) — Certificate Designer and Payment
* Config serve every family (logistics licences, seafarer certificates,
* seafarer/vessel documents alike), so they sit in `groupShared` instead of
* implying they're licensing-only.
*/
export const NAV_SECTIONS: NavSection[] = [
{
items: [{ to: '/dashboard', label: 'nav.dashboard', icon: IconLayoutDashboard }],
},
{
label: 'nav.groupLicensing',
items: [
{
to: '/licence-review',
label: 'nav.allApplications',
icon: IconListCheck,
permissions: APPLICATION_QUEUE,
},
{
// A disclosure, not a destination — each child deep-links the grid to
// one type, which is a facet of the same workspace.
label: 'nav.byType',
icon: IconTruck,
permissions: APPLICATION_QUEUE,
children: [
{ to: '/licence-review/type/FREIGHT_FORWARDER', label: 'nav.typeFreightForwarder', icon: IconTruck, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/SHIPPING_AGENT', label: 'nav.typeShippingAgent', icon: IconShip, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/COMBINED_SA_FF', label: 'nav.typeCombined', icon: IconFileDescription, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/JOINT_INVESTOR', label: 'nav.typeJointInvestment', icon: IconUsers, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/MULTIMODAL_TRANSPORT_OPERATOR', label: 'nav.typeMto', icon: IconAnchor, permissions: APPLICATION_QUEUE },
],
},
{
to: '/licence-register',
label: 'nav.licenceRegister',
icon: IconListCheck,
permissions: [P.VIEW_LICENSES],
},
{ to: '/licence-review/type/PRE_WAIVER', label: 'nav.preWaiverQueue', icon: IconShieldOff, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/POST_WAIVER', label: 'nav.postWaiverQueue', icon: IconShieldOff, permissions: APPLICATION_QUEUE },
{
// Every figure on it is derived from the licence application queue.
to: '/logistics-head-dashboard',
label: 'nav.logisticsHeadDashboard',
icon: IconGauge,
permissions: APPLICATION_QUEUE,
},
],
},
{
label: 'nav.groupSeafarer',
items: [
{ to: '/seafarer-registry', label: 'nav.seafarerRegistry', icon: IconUsers, permissions: [P.VIEW_SEAFARER_REGISTRY] },
{ to: '/seafarer-registrations', label: 'nav.seafarerRegistrationQueue', icon: IconId, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/CERTIFICATE_OF_COMPETENCY', label: 'nav.cocQueue', icon: IconShieldCheck, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/CERTIFICATE_OF_PROFICIENCY', label: 'nav.copQueue', icon: IconShieldCheck, permissions: APPLICATION_QUEUE },
{ to: '/seaman-book-queue', label: 'nav.seamanBookQueue', icon: IconBook2, permissions: APPLICATION_QUEUE },
{ to: '/btc-queue', label: 'nav.btcQueue', icon: IconShieldCheck, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/ENDORSEMENT_COC', label: 'nav.endorsementCocQueue', icon: IconRubberStamp, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/ENDORSEMENT_GOC', label: 'nav.endorsementGocQueue', icon: IconRubberStamp, permissions: APPLICATION_QUEUE },
{ to: '/sea-service-verification', label: 'nav.seaServiceVerification', icon: IconAnchor, permissions: [P.VERIFY_SEAFARER_RECORDS] },
{ to: '/medical-verification', label: 'nav.medicalVerification', icon: IconHeart, permissions: [P.VERIFY_SEAFARER_RECORDS] },
],
},
{
label: 'nav.groupVessels',
items: [
{ to: '/vessel-registration-report', label: 'nav.vesselRegistrationReport', icon: IconChartBar, permissions: [P.VIEW_VESSEL_REGISTRY] },
{ to: '/vessel-registration-queue', label: 'nav.vesselRegistrationQueue', icon: IconAnchor, permissions: [P.VIEW_VESSEL_REGISTRY] },
{ to: '/licence-review/type/VESSEL_REGISTRATION', label: 'nav.vesselRegistrationApplicationQueue', icon: IconAnchor, permissions: APPLICATION_QUEUE },
{ to: '/licence-review/type/VESSEL_OWNERSHIP_TRANSFER', label: 'nav.ownershipTransferQueue', icon: IconArrowsExchange, permissions: APPLICATION_QUEUE },
{ to: '/vessel-registration-queue/new', label: 'nav.vesselFormBuilder', icon: IconFilePlus, soon: true, permissions: [P.VIEW_VESSEL_REGISTRY] },
],
},
{
label: 'nav.groupExaminations',
items: [
{ to: '/questions', label: 'nav.questions', icon: IconQuestionMark, permissions: [P.APPROVE_QUESTION, P.AUTHOR_QUESTION] },
{
to: '/exams',
label: 'nav.exams',
icon: IconClipboardList,
permissions: [P.MANAGE_EXAMS, P.RECORD_EXAM_ATTENDANCE, P.MANAGE_EXAM_INCIDENTS, P.PUBLISH_EXAM_RESULT],
},
{
to: '/exam-results',
label: 'nav.examResults',
icon: IconReport,
permissions: [P.RECORD_EXAM_RESULT, P.MODERATE_EXAM_RESULT, P.APPROVE_EXAM_RESULT, P.PUBLISH_EXAM_RESULT],
},
{ to: '/exam-appeals', label: 'nav.examAppeals', icon: IconGavel, permissions: [P.DECIDE_EXAM_APPEAL] },
],
},
{
label: 'nav.groupShared',
items: [
{
to: '/certificate-designer',
label: 'nav.certificateDesigner',
icon: IconRosetteDiscountCheck,
permissions: [P.VIEW_TEMPLATES],
},
{
to: '/certificate-requirements',
label: 'nav.certificateRequirements',
icon: IconClipboardText,
permissions: [P.VIEW_LICENSE_TYPES],
},
{
to: '/payment-config',
label: 'nav.paymentConfig',
icon: IconCreditCard,
permissions: [P.VIEW_PAYMENTS],
},
],
},
{
label: 'nav.groupAdministration',
items: [
{ to: '/um/user-management/dashboard', label: 'nav.userManagement', icon: IconUserShield },
{
// Professions, locations and certifications have no dedicated keys;
// the config-view keys are the closest published contract.
to: '/configuration',
label: 'nav.configuration',
icon: IconSettings,
permissions: [P.VIEW_LICENSE_TYPES, P.VIEW_TEMPLATES],
},
{ to: '/analytics', label: 'nav.analytics', icon: IconChartBar, soon: true },
],
},
// `/profile` deliberately absent: it is a property of the signed-in user,
// not a destination in the authority's workload, and now lives in the
// AppHeader user menu alongside sign-out.
];