diff --git a/apps/portal/src/app/i18n/locales/am.ts b/apps/portal/src/app/i18n/locales/am.ts index 215600216..f7139c2cd 100644 --- a/apps/portal/src/app/i18n/locales/am.ts +++ b/apps/portal/src/app/i18n/locales/am.ts @@ -48,6 +48,10 @@ export const am: Translations = { support: 'እገዛና ድጋፍ', collapseSidebar: 'ሰብስብ', expandSidebar: 'ዘርጋ', + sectionSeafarerServices: 'የመርከበኞች አገልግሎቶች', + sectionVesselServices: 'የመርከብ አገልግሎቶች', + sectionLogisticsLicensing: 'ሎጂስቲክስና ፈቃድ', + sectionAccountManagement: 'የመለያ አስተዳደር', }, common: { diff --git a/apps/portal/src/app/i18n/locales/en.ts b/apps/portal/src/app/i18n/locales/en.ts index 7affb9b11..dbae01a0f 100644 --- a/apps/portal/src/app/i18n/locales/en.ts +++ b/apps/portal/src/app/i18n/locales/en.ts @@ -46,6 +46,10 @@ export const en = { support: 'Help & Support', collapseSidebar: 'Collapse', expandSidebar: 'Expand sidebar', + sectionSeafarerServices: 'Seafarer Services', + sectionVesselServices: 'Vessel Services', + sectionLogisticsLicensing: 'Logistics and Licensing', + sectionAccountManagement: 'Account Management', }, common: { diff --git a/apps/portal/src/app/layouts/PortalLayout.tsx b/apps/portal/src/app/layouts/PortalLayout.tsx index b38e6fe36..80d821257 100644 --- a/apps/portal/src/app/layouts/PortalLayout.tsx +++ b/apps/portal/src/app/layouts/PortalLayout.tsx @@ -28,120 +28,146 @@ import { logout } from "@ema-platform/auth"; import { SUPPORTED_LANGUAGES } from "../i18n/config"; import { useAppSelector } from "../store/hooks"; -const NAV_ITEMS: (NavItem & { i18nKey: string })[] = [ +type SectionId = "seafarer" | "vessel" | "logistics" | "common"; + +const SECTION_I18N_KEY: Record = { + seafarer: "nav.sectionSeafarerServices", + vessel: "nav.sectionVesselServices", + logistics: "nav.sectionLogisticsLicensing", + common: "nav.sectionAccountManagement", +}; + +const NAV_ITEMS: (NavItem & { i18nKey: string; section?: SectionId })[] = [ { to: "/dashboard", label: "Dashboard", i18nKey: "nav.dashboard", icon: IconHome2, }, - { - to: "/seafarer-registry", - label: "Seafarer Registry", - i18nKey: "nav.seafarerRegistry", - icon: IconList, - }, - { - to: "/seaman-book", - label: "My Application", - i18nKey: "nav.myApplication", - icon: IconSend, - }, - { - to: "/vessel-registration-dashboard", - label: "Vessel Registration Dashboard", - i18nKey: "nav.vesselRegistrationDashboard", - icon: IconGauge, - }, - { - to: "/vessel-registration", - label: "Vessel Registration", - i18nKey: "nav.vesselRegistration", - icon: IconShip, - }, - { - to: "/vessel-registration/transfer", - label: "Ownership Transfer", - i18nKey: "nav.ownershipTransfer", - icon: IconArrowsExchange, - }, - { - to: "/logistics-dashboard", - label: "Logistics Licenses Dashboard", - i18nKey: "nav.logisticsDashboard", - icon: IconGauge, - }, - { - to: "/freight-forwarder-license", - label: "Freight Forwarder License", - i18nKey: "nav.freightForwarderLicense", - icon: IconTruck, - }, - { - to: "/shipping-agent-license", - label: "Shipping Agent License", - i18nKey: "nav.shippingAgentLicense", - icon: IconShip, - }, - { - to: "/combined-license", - label: "Combined License", - i18nKey: "nav.combinedLicense", - icon: IconStack2, - }, - { - to: "/joint-investment-license", - label: "Joint Investment License", - i18nKey: "nav.jointInvestmentLicense", - icon: IconUsers, - }, - { - to: "/mto-license", - label: "MTO License", - i18nKey: "nav.mtoLicense", - icon: IconTruck, - }, - { - to: "/waiver", - label: "Waiver", - i18nKey: "nav.waiver", - icon: IconShieldOff, - }, - { - to: "/certificates", - label: "Certificates", - i18nKey: "nav.certificates", - icon: IconShieldCheck, - }, - { - to: "/endorsements", - label: "Endorsements", - i18nKey: "nav.endorsements", - icon: IconRubberStamp, - }, - { - to: "/documents", - label: "My Documents", - i18nKey: "nav.documents", - icon: IconFolderOpen, - }, { to: "/notifications", label: "Notifications", i18nKey: "nav.notifications", icon: IconBell, }, + { + to: "/seafarer-registry", + label: "Seafarer Registry", + i18nKey: "nav.seafarerRegistry", + icon: IconList, + section: "seafarer", + }, + { + to: "/seaman-book", + label: "My Application", + i18nKey: "nav.myApplication", + icon: IconSend, + section: "seafarer", + }, + { + to: "/certificates", + label: "Certificates", + i18nKey: "nav.certificates", + icon: IconShieldCheck, + section: "seafarer", + }, + { + to: "/endorsements", + label: "Endorsements", + i18nKey: "nav.endorsements", + icon: IconRubberStamp, + section: "seafarer", + }, + { + to: "/vessel-registration-dashboard", + label: "Vessel Registration Dashboard", + i18nKey: "nav.vesselRegistrationDashboard", + icon: IconGauge, + section: "vessel", + }, + { + to: "/vessel-registration", + label: "Vessel Registration", + i18nKey: "nav.vesselRegistration", + icon: IconShip, + section: "vessel", + }, + { + to: "/vessel-registration/transfer", + label: "Ownership Transfer", + i18nKey: "nav.ownershipTransfer", + icon: IconArrowsExchange, + section: "vessel", + }, + { + to: "/logistics-dashboard", + label: "Logistics Licenses Dashboard", + i18nKey: "nav.logisticsDashboard", + icon: IconGauge, + section: "logistics", + }, + { + to: "/freight-forwarder-license", + label: "Freight Forwarder License", + i18nKey: "nav.freightForwarderLicense", + icon: IconTruck, + section: "logistics", + }, + { + to: "/shipping-agent-license", + label: "Shipping Agent License", + i18nKey: "nav.shippingAgentLicense", + icon: IconShip, + section: "logistics", + }, + { + to: "/combined-license", + label: "Combined License", + i18nKey: "nav.combinedLicense", + icon: IconStack2, + section: "logistics", + }, + { + to: "/joint-investment-license", + label: "Joint Investment License", + i18nKey: "nav.jointInvestmentLicense", + icon: IconUsers, + section: "logistics", + }, + { + to: "/mto-license", + label: "MTO License", + i18nKey: "nav.mtoLicense", + icon: IconTruck, + section: "logistics", + }, + { + to: "/waiver", + label: "Waiver", + i18nKey: "nav.waiver", + icon: IconShieldOff, + section: "logistics", + }, + { + to: "/documents", + label: "My Documents", + i18nKey: "nav.documents", + icon: IconFolderOpen, + section: "common", + }, { to: "/profile", label: "Profile", i18nKey: "nav.profile", icon: IconUserCircle, + section: "common", }, { to: "/support", label: "Help & Support", i18nKey: "nav.support", icon: IconHeadset, + section: "common", }, ]; @@ -152,11 +178,11 @@ const NAV_ITEMS: (NavItem & { i18nKey: string })[] = [ // matches a profession named "Deck Cadet". Values are the `to` paths from // NAV_ITEMS above. '*' means every item. -const ALWAYS_VISIBLE = ["/notifications", "/profile", "/support"]; +const ALWAYS_VISIBLE = ["/notifications", "/profile", "/support", "/documents"]; const NAV_ACCESS: Record = { null: "*", - //cadet: "*", + // cadet: "*", cadet: [ "/dashboard", "/seafarer-registry", @@ -314,9 +340,10 @@ export function PortalLayout() { }} > ({ + navItems={visibleNavItems.map(({ i18nKey, section, ...rest }) => ({ ...rest, label: t(i18nKey), + section: section ? t(SECTION_I18N_KEY[section]) : undefined, }))} collapsed={sidebarCollapsed} activePath={location.pathname} diff --git a/libs/ui/src/lib/layout/AppSidebar.tsx b/libs/ui/src/lib/layout/AppSidebar.tsx index aca994bbb..c1f252ae2 100644 --- a/libs/ui/src/lib/layout/AppSidebar.tsx +++ b/libs/ui/src/lib/layout/AppSidebar.tsx @@ -1,3 +1,4 @@ +import { Fragment } from 'react'; import { AppShell, NavLink, @@ -21,6 +22,7 @@ export interface NavItem { icon: Icon; to?: string; soon?: boolean; + section?: string; } interface AppSidebarProps { @@ -97,9 +99,25 @@ export function AppSidebar({ {/* Navigation items */} - {navItems.map((item) => { + {navItems.map((item, index) => { const ItemIcon = item.icon; const active = activeNavItem(item); + const showHeader = + !collapsed && !!item.section && item.section !== navItems[index - 1]?.section; + + const header = showHeader ? ( + + {item.section} + + ) : null; if (collapsed) { return ( @@ -124,15 +142,17 @@ export function AppSidebar({ } return ( - } - onClick={() => onNavigate(item)} - variant="light" - styles={{ root: { borderRadius: rem(10) }, label: { fontWeight: 500 } }} - /> + + {header} + } + onClick={() => onNavigate(item)} + variant="light" + styles={{ root: { borderRadius: rem(10) }, label: { fontWeight: 500 } }} + /> + ); })}