merge fix

This commit is contained in:
Estifo77
2026-08-03 10:56:02 +03:00
parent 07970b85b2
commit 661e5d2f04

View File

@@ -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<string, { i18nKey: string }> = {
'/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 <Navigate to={home} replace />;
}
// Breadcrumb trail
const segments = location.pathname.split("/").filter(Boolean);
const crumbs = [
@@ -204,14 +248,17 @@ export function PortalLayout() {
<AppSidebar
navItems={NAV_SECTIONS.map((section) => ({
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={<BrandMark size={32} />}
/>
</AppShell.Navbar>