diff --git a/apps/portal/src/app/layouts/PortalLayout.tsx b/apps/portal/src/app/layouts/PortalLayout.tsx index 6effc9e95..7c340930f 100644 --- a/apps/portal/src/app/layouts/PortalLayout.tsx +++ b/apps/portal/src/app/layouts/PortalLayout.tsx @@ -14,15 +14,15 @@ import { IconShip, IconTruck, IconUserCircle, -} from '@tabler/icons-react'; -import { Outlet, useLocation, useNavigate } from 'react-router-dom'; -import { useTranslation } from 'react-i18next'; -import { useDispatch } from 'react-redux'; -import { notify, AppHeader, AppSidebar } from '@ema-platform/ui'; -import type { NavItem } from '@ema-platform/ui'; -import { BrandMark, logout } from '@ema-platform/auth'; -import { SUPPORTED_LANGUAGES } from '../i18n/config'; -import { useAppSelector } from '../store/hooks'; +} from "@tabler/icons-react"; +import { Outlet, useLocation, useNavigate } from "react-router-dom"; +import { useTranslation } from "react-i18next"; +import { useDispatch } from "react-redux"; +import { notify, AppHeader, AppSidebar } from "@ema-platform/ui"; +import type { NavItem } from "@ema-platform/ui"; +import { BrandMark, logout } from "@ema-platform/auth"; +import { SUPPORTED_LANGUAGES } from "../i18n/config"; +import { useAppSelector } from "../store/hooks"; type PortalNavItem = NavItem & { i18nKey: string }; @@ -35,59 +35,131 @@ type PortalNavItem = NavItem & { i18nKey: string }; const NAV_SECTIONS: { label?: string; items: PortalNavItem[] }[] = [ { items: [ - { to: '/dashboard', label: 'Dashboard', i18nKey: 'nav.dashboard', icon: IconHome2 }, - { to: '/notifications', label: 'Notifications', i18nKey: 'nav.notifications', icon: IconBell }, + { + to: "/dashboard", + label: "Dashboard", + i18nKey: "nav.dashboard", + icon: IconHome2, + }, + { + to: "/notifications", + label: "Notifications", + i18nKey: "nav.notifications", + icon: IconBell, + }, ], }, { - label: 'nav.groupLicensing', + label: "nav.groupLicensing", items: [ - { to: '/licensing/applications', label: 'My Applications', i18nKey: 'nav.myApplications', icon: IconTruck }, - { to: '/waiver', label: 'Waiver', i18nKey: 'nav.waiver', icon: IconShieldOff, soon: true }, + { + to: "/licensing/applications", + label: "My Applications", + i18nKey: "nav.myApplications", + icon: IconTruck, + }, + { + to: "/waiver", + label: "Waiver", + i18nKey: "nav.waiver", + icon: IconShieldOff, + soon: true, + }, ], }, { - label: 'nav.groupSeafarer', + label: "nav.groupSeafarer", items: [ - { to: '/seafarer-registry', label: 'Seafarer Registry', i18nKey: 'nav.seafarerRegistry', icon: IconList }, - { to: '/seaman-book', label: 'Seaman Book', i18nKey: 'nav.myApplication', icon: IconSend, soon: true }, - { to: '/certificates', label: 'Certificates', i18nKey: 'nav.certificates', icon: IconShieldCheck, soon: true }, - { to: '/endorsements', label: 'Endorsements', i18nKey: 'nav.endorsements', icon: IconRubberStamp, soon: true }, + { + to: "/seafarer-registry", + label: "Seafarer Registry", + i18nKey: "nav.seafarerRegistry", + icon: IconList, + }, + { + to: "/seaman-book", + label: "Seaman Book", + i18nKey: "nav.myApplication", + icon: IconSend, + soon: true, + }, + { + to: "/certificates", + label: "Certificates", + i18nKey: "nav.certificates", + icon: IconShieldCheck, + soon: true, + }, + { + to: "/endorsements", + label: "Endorsements", + i18nKey: "nav.endorsements", + icon: IconRubberStamp, + soon: true, + }, ], }, { - label: 'nav.groupVessels', + label: "nav.groupVessels", items: [ - { to: '/vessel-registration', label: 'Vessel Registration', i18nKey: 'nav.vesselRegistration', icon: IconShip, soon: true }, - { to: '/vessel-registration/transfer', label: 'Ownership Transfer', i18nKey: 'nav.ownershipTransfer', icon: IconArrowsExchange, soon: true }, + { + to: "/vessel-registration", + label: "Vessel Registration", + i18nKey: "nav.vesselRegistration", + icon: IconShip, + soon: true, + }, + { + to: "/vessel-registration/transfer", + label: "Ownership Transfer", + i18nKey: "nav.ownershipTransfer", + icon: IconArrowsExchange, + soon: true, + }, ], }, { - label: 'nav.groupAccount', + label: "nav.groupAccount", items: [ - { to: '/documents', label: 'My Documents', i18nKey: 'nav.documents', icon: IconFolderOpen }, - { to: '/profile', label: 'Profile', i18nKey: 'nav.profile', icon: IconUserCircle }, - { to: '/support', label: 'Help & Support', i18nKey: 'nav.support', icon: IconHeadset }, + { + to: "/documents", + label: "My Documents", + i18nKey: "nav.documents", + icon: IconFolderOpen, + }, + { + to: "/profile", + label: "Profile", + i18nKey: "nav.profile", + icon: IconUserCircle, + }, + { + to: "/support", + label: "Help & Support", + i18nKey: "nav.support", + icon: IconHeadset, + }, ], }, ]; - const PAGE_META: Record = { - '/dashboard': { i18nKey: 'nav.dashboard' }, - '/vessel-registration-dashboard': { i18nKey: 'nav.vesselRegistrationDashboard' }, - '/vessel-registration': { i18nKey: 'nav.vesselRegistration' }, - '/vessel-registration/transfer': { i18nKey: 'nav.ownershipTransfer' }, - '/licensing/applications': { i18nKey: 'nav.myApplications' }, - '/waiver': { i18nKey: 'nav.waiver' }, - '/seafarer-registry': { i18nKey: 'nav.seafarerRegistry' }, - '/seaman-book': { i18nKey: 'nav.myApplication' }, - '/certificates': { i18nKey: 'nav.certificates' }, - '/endorsements': { i18nKey: 'nav.endorsements' }, - '/documents': { i18nKey: 'nav.documents' }, - '/notifications':{ i18nKey: 'nav.notifications' }, - '/profile': { i18nKey: 'nav.profile' }, - '/support': { i18nKey: 'nav.support' }, + "/dashboard": { i18nKey: "nav.dashboard" }, + "/vessel-registration-dashboard": { + i18nKey: "nav.vesselRegistrationDashboard", + }, + "/vessel-registration": { i18nKey: "nav.vesselRegistration" }, + "/vessel-registration/transfer": { i18nKey: "nav.ownershipTransfer" }, + "/licensing/applications": { i18nKey: "nav.myApplications" }, + "/waiver": { i18nKey: "nav.waiver" }, + "/seafarer-registry": { i18nKey: "nav.seafarerRegistry" }, + "/seaman-book": { i18nKey: "nav.myApplication" }, + "/certificates": { i18nKey: "nav.certificates" }, + "/endorsements": { i18nKey: "nav.endorsements" }, + "/documents": { i18nKey: "nav.documents" }, + "/notifications": { i18nKey: "nav.notifications" }, + "/profile": { i18nKey: "nav.profile" }, + "/support": { i18nKey: "nav.support" }, }; export function PortalLayout() { @@ -96,37 +168,9 @@ export function PortalLayout() { const location = useLocation(); const dispatch = useDispatch(); const user = useAppSelector((state) => state.auth.user); - const currentProfile = useAppSelector((state) => state.auth.currentProfile); - const professionName = ( - currentProfile?.profession?.name?.en ?? "" - ).toLowerCase(); - const matchedKey = Object.keys(NAV_ACCESS).find((key) => - professionName.includes(key), - ); - const allowed = - (matchedKey ? NAV_ACCESS[matchedKey] : undefined) ?? FALLBACK_ACCESS; - const home = allowed === "*" ? "/dashboard" : (allowed[0] ?? "/dashboard"); - const isAllowed = - allowed === "*" || - [...ALWAYS_VISIBLE, ...ALWAYS_ALLOWED, ...allowed].some((p) => - matchesPath(location.pathname, p), - ); - const visibleNavItems = - allowed === "*" - ? NAV_ITEMS - : NAV_ITEMS.filter( - (item) => - ALWAYS_VISIBLE.includes(item.to ?? "") || - allowed.includes(item.to ?? ""), - ); const [navOpened, { toggle: toggleNav, close: closeNav }] = useDisclosure(); const [sidebarCollapsed, { toggle: toggleSidebar }] = useDisclosure(false); - if (!isAllowed) { - notify.error(t("msg.permissionError")); - return ; - } - // Breadcrumb trail const segments = location.pathname.split("/").filter(Boolean); const crumbs = [ @@ -204,14 +248,17 @@ export function PortalLayout() { ({ label: section.label, - items: section.items.map(({ i18nKey, ...rest }) => ({ ...rest, label: t(i18nKey) })), + items: section.items.map(({ i18nKey, ...rest }) => ({ + ...rest, + label: t(i18nKey), + })), }))} collapsed={sidebarCollapsed} activePath={location.pathname} onToggleCollapse={toggleSidebar} onNavigate={go} - brandName={t('app.name')} - brandSubtitle={t('app.authority')} + brandName={t("app.name")} + brandSubtitle={t("app.authority")} brandLogo={} />