user route

This commit is contained in:
yaschalew
2026-07-10 10:56:59 +03:00
parent 28a20923ff
commit 2696ca7498
3 changed files with 545 additions and 0 deletions

View File

@@ -0,0 +1,312 @@
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>
);
};

View File

@@ -0,0 +1,36 @@
import { useLocation } from "react-router-dom";
import { Outlet } from "react-router-dom";
import { AppMenuTabs } from "./AppMenuTabs";
import { useSidebar } from "@/shared/common/ui/sidebar";
import Top from "@/record-management/components/common/Top";
import { useAuth } from "@/shared/context/AuthContext";
export const AppLayout = () => {
const { pathname } = useLocation();
const isAuthPage = pathname === "/";
const { toggleSidebar } = useSidebar();
const { user } = useAuth();
const userRoles = user?.roles?.map((role) => role.key) || [];
const isSuperAdmin = userRoles.includes("super_admin");
if (isAuthPage) {
return (
<div className="min-h-screen w-full bg-gray-50">
<Outlet />
</div>
);
}
return (
<div className="w-full flex flex-col min-h-screen bg-background text-foreground">
<Top onToggleSidebar={toggleSidebar} showRecordManagementShortcut={!isSuperAdmin} />
<AppMenuTabs />
<div className="px-2 pb-2 pt-8 sm:px-4 sm:pb-4 sm:pt-10 flex-1">
<div className="w-full overflow-x-auto">
<Outlet />
</div>
</div>
</div>
);
};

View File

@@ -0,0 +1,197 @@
<Route element={<AppLayout />}>
<Route
path="user-management"
element={
<div className="w-full flex flex-col p-4">
<UserManagementRedirect />
</div>
}
/>
<Route
path="/user-management/archive/edit/:id"
element={<UserProfileEditPage />}
/>
<Route
path="user-management/position-management"
element={<PositionManagementPage />}
/>
<Route
path="user-management/migrated-records-management"
element={<MigratedDataManagementPage />}
/>
<Route
path="user-management/position-management/edit/:id"
element={<EditPositionPage />}
/>
<Route
path="user-management/position-management/new"
element={<CreatePositionPage />}
/>
{/* Super Admin */}
<Route
element={
<PrivateRoute allowedRoles={["super_admin"]} />
}
>
<Route
path="user-management/dashboard"
element={<DashboardPage />}
/>
<Route
path="user-management/organizations"
element={<OrganizationsPage />}
/>
<Route
path="user-management/organizations/detail/:id"
element={<OrganizationDetailPage />}
/>
<Route
path="super-admin/organizations/:id"
element={<OrganizationDetailPage />}
/>
<Route
path="user-management/organizations/new"
element={<NewOrganizationPage />}
/>
<Route
path="user-management/organizations/edit/:id"
element={<EditOrganizationPage />}
/>
<Route
path="user-management/external_users"
element={<PendingExternalUsers />}
/>
<Route
path="user-management/migrated-records-management/view/:id"
element={<ViewMigratedDataPage />}
/>
<Route
path="user-management/external_users/view/:id"
element={<UploadedDocumentViewPage />}
/>
<Route
path="user-management/external_users/edit/:id"
element={<UserProfileEditPage />}
/>
<Route
path="user-management/organization_admins"
element={<OrganizationAdminsPage />}
/>
<Route
path="user-management/add_admin"
element={<AdminRegistrationPage />}
/>
<Route
path="user-management/activity_log"
element={<ActivityLogPage />}
/>
<Route
path="user-management/settings"
element={<SettingsPage />}
/>
<Route
path="user-management/archive-users"
element={<SuperAdminArchiveUsersPage />}
/>
<Route
path="user-management/archived-organizations"
element={<SuperAdminArchivedPage />}
/>
<Route
path="user-management/templates"
element={<TemplatePage />}
/>
<Route
path="user-management/add-site"
element={<AddSitePage />}
/>
<Route
path="/user-management/web-management/Branding/Branding/:siteId"
element={<Branding />}
/>
</Route>
{/* Org Admin */}
<Route
element={
<PrivateRoute
allowedRoles={[
"admin",
"organization_admin",
"unit_admin",
]}
/>
}
>
<Route
path="user-management/user_management-dashboard"
element={<OrgAdminDashboard />}
/>
<Route
path="user-management/user_management"
element={<UserManagementPage />}
/>
<Route
path="user-management/user-position-approval"
element={
// <WithPermission
// perms={["can:activateEmployee"]}
// fallback={<Navigate to="/" replace />}
// >
<UserPositionApprovalPage />
// </WithPermission>
}
/>
<Route
path="user-management/all-records"
element={
<WithPermission
perms={["can:viewAllRecords"]}
fallback={<Navigate to="/" replace />}
>
<AllRecordsPage />
</WithPermission>
}
/>
<Route
path="user-management/all-records/:id"
element={
<WithPermission
perms={["can:viewAllRecords"]}
fallback={<Navigate to="/" replace />}
>
<AllRecordDetailsPage />
</WithPermission>
}
/>
<Route
path="user-management/content-management"
element={<ContentManagementPage />}
/>
<Route
path="user-management/bulk-upload"
element={<BulkUploadPage />}
/>
<Route
path="user-management/web-management/*"
element={<WebManagement />}
/>
<Route
path="user-management/archives"
element={<ArchiveUsersPage />}
/>
<Route
path="user-management/sector-reports"
element={<SectorReportsPage />}
/>
<Route
path="user-management/archived"
element={<ArchivedUnitsPositionsPage />}
/>
<Route
path="user-management/organization-settings"
element={<ConfigurationPage />}
/>
</Route>
</Route>