Files
edr-platform/apps/edr-freight-web/backoffice/src/layout/AppMenuTabs.tsx
natib21 e6e44e773b fix ui
2026-07-10 11:25:59 +00:00

313 lines
10 KiB
TypeScript

import { NavLink } from "react-router-dom";
import {
Archive,
BarChart,
Building2,
ChartAreaIcon,
ClipboardList,
FileText,
Globe,
Settings,
ShieldAlert,
Users2,
UsersRound,
} from "lucide-react";
import { useAuth } from "@/shared/context/AuthContext";
import { usePermissions } from "@/shared/context/PermissionContext";
import { useTranslation } from "react-i18next";
export interface MenuItem {
label: string;
href: string;
icon: React.ReactNode;
roles?: string[];
permissions?: string[];
isPrimary?: boolean;
displayLabel?: string;
children?: MenuItem[];
}
export const AppMenuTabs = () => {
const { user } = useAuth();
const userRoles = user?.roles.map((role) => role.key) || [];
const menuItems: MenuItem[] = [
{
label: "dashboard",
href: "/user-management/dashboard",
icon: <BarChart className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "organizations",
href: "/user-management/organizations",
icon: <Building2 className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "organizationAdmins", // Shortened for mobile
displayLabel: "organizationAdmins", // Full label for desktop
href: "/user-management/organization_admins",
icon: <Users2 className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "externalUsers", // Shortened for mobile
displayLabel: "externalUsers", // Full label for desktop
href: "/user-management/external_users",
icon: <Users2 className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "dashboard",
href: "/user-management/user_management-dashboard",
icon: <BarChart className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "userManagement",
href: "/user-management/user_management",
icon: <UsersRound className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
// {
// label: "userPositionApproval",
// href: "/user-management/user-position-approval",
// icon: <UsersRound className="h-4 w-4" />,
// roles: ["admin", "organization_admin", "unit_admin"],
// permissions: ["can:activateEmployee"],
// isPrimary: true,
// },
// {
// label: "All Records",
// displayLabel: "All Records",
// href: "/user-management/all-records",
// icon: <FileText className="h-4 w-4" />,
// roles: ["admin", "organization_admin", "unit_admin"],
// permissions: ["can:canViewAllRecords"],
// isPrimary: true,
// },
{
label: "contentManagement", // Shortened for mobile
displayLabel: "contentManagement", // Full label for desktop
href: "/user-management/content-management",
icon: <FileText className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "webManagement",
displayLabel: "webManagement",
href: "/user-management/web-management",
icon: <Globe className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "Position",
displayLabel: "positionTypes",
href: "/user-management/position-management",
icon: <FileText className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin", "super_admin"],
isPrimary: true,
},
{
label: "migratedRecords",
displayLabel: "migratedRecords",
href: "/user-management/migrated-records-management",
icon: <FileText className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "settings",
displayLabel: "settings",
href: "/user-management/organization-settings",
icon: <Settings className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "Bulk",
displayLabel: "bulkUpload",
href: "/user-management/bulk-upload",
icon: <FileText className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "Archive Users",
displayLabel: "Archive Users",
href: "/user-management/archive-users",
icon: <Archive className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "Archived Organizations",
displayLabel: "Archived Organizations",
href: "/user-management/archived-organizations",
icon: <Archive className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
{
label: "Archive Users",
displayLabel: "Archive Users",
href: "/user-management/archives",
icon: <Archive className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "Archived Units & Positions",
displayLabel: "Archived Units & Positions",
href: "/user-management/archived",
icon: <Archive className="h-4 w-4" />,
roles: ["admin", "organization_admin", "unit_admin"],
isPrimary: true,
},
{
label: "Sector Reports",
displayLabel: "Sector Reports",
href: "/user-management/sector-reports",
icon: <ChartAreaIcon className="h-5 w-5" />,
roles: ["unit_admin", "admin", "organization_admin"],
isPrimary: true,
},
{
label: "activityLog",
href: "/user-management/activity_log",
icon: <ClipboardList className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: false,
},
{
label: "setting",
href: "/user-management/settings",
icon: <Settings className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: false,
},
{
label: "Letter Template",
href: "/user-management/templates",
icon: <FileText className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: false,
},
{
label: "Add Site",
href: "/user-management/add-site",
icon: <Globe className="h-4 w-4" />,
roles: ["super_admin"],
isPrimary: true,
},
// {
// label: "branding.title",
// href: "/user-management/web-management/Branding/Branding",
// icon: <ShieldAlert className="h-4 w-4" />,
// roles: ["super_admin"],
// isPrimary: true,
// },
];
const { permissions } = usePermissions();
const { t } = useTranslation();
const filteredMenu = menuItems.filter((item) =>
item?.roles?.some((r) => userRoles.includes(r)),
);
const primaryMenuItems = filteredMenu.filter(
(item) => item.isPrimary !== false,
);
const secondaryMenuItems = filteredMenu.filter(
(item) => item.isPrimary === false,
);
return (
<div className="fixed top-16 left-0 right-0 z-30 bg-white dark:bg-gray-900 border-b dark:border-gray-800 overflow-hidden flex flex-col">
{/* Mobile View - Two separate rows */}
<div className="md:hidden flex flex-col pt-5 pb-3 px-4 space-y-3 mt-2">
{/* Primary items row */}
<div className="flex items-center overflow-x-auto scrollbar-none">
{primaryMenuItems.map((item) => (
<NavLink
key={item.href}
to={item.href}
className={({ isActive }) =>
`flex items-center gap-1 px-3 py-2.5 mr-2 text-xs font-medium transition-colors whitespace-nowrap ${
isActive
? "text-primary dark:text-primary-400 border-b-2 border-primary dark:border-primary-400"
: "text-slate-700 dark:text-gray-300 hover:text-primary dark:hover:text-primary-400"
}`
}
>
{item.icon}
<span className="max-w-[80px] truncate">
{t(`organization.${item.label}`, item.label)}
</span>
</NavLink>
))}
</div>
{/* Secondary items row (if any) */}
{secondaryMenuItems.length > 0 && (
<div className="flex items-center overflow-x-auto scrollbar-none border-t dark:border-gray-800 pt-3">
{secondaryMenuItems.map((item) => (
<NavLink
key={item.href}
to={item.href}
className={({ isActive }) =>
`flex items-center gap-1 px-3 py-2.5 mr-2 text-xs font-medium transition-colors whitespace-nowrap ${
isActive
? "text-primary dark:text-primary-400 border-b-2 border-primary dark:border-primary-400"
: "text-slate-700 dark:text-gray-300 hover:text-primary dark:hover:text-primary-400"
}`
}
>
{item.icon}
<span className="max-w-[80px] truncate">
{t(`organization.${item.label}`, item.label)}
</span>
</NavLink>
))}
</div>
)}
</div>
{/* Desktop View - Single row with all items */}
<div className="hidden md:flex pt-5 pb-3 px-8 mt-1">
<div className="flex items-center gap-2 overflow-x-auto scrollbar-none">
{filteredMenu.map((item) => (
<NavLink
key={item.href}
to={item.href}
className={({ isActive }) =>
`flex items-center gap-2 px-4 py-3 text-sm font-medium transition-colors whitespace-nowrap ${
isActive
? "text-primary dark:text-primary-400 border-b-2 border-primary dark:border-primary-400"
: "text-slate-700 dark:text-gray-300 hover:text-primary dark:hover:text-primary-400"
}`
}
>
{item.icon}
<span className="max-w-full truncate">
{t(`organization.${item.label}`, item.label)}
</span>
</NavLink>
))}
</div>
</div>
</div>
);
};