Files
edr-platform/apps/edr-freight-web/backoffice/src/user-management/route.tsx
yaschalew 917c5604eb fix ui
2026-07-11 11:10:51 +03:00

319 lines
14 KiB
TypeScript

import type { ReactElement } from "react";
import { Navigate, Outlet, Route } from "react-router-dom";
import { useAuth } from "@/auth/useAuth";
import { isSuperAdmin } from "@/lib/permissions";
import { WithPermission } from "@/shared/hooks/useHas";
import PendingExternalUsers from "@/super-admin/components/externalUsers/PendingExternalUsers";
import TemplatePage from "@/super-admin/components/templates/components/templates";
import CreatePositionPage from "./pages/position-management/create";
import EditPositionPage from "./pages/position-management/edit";
import PositionManagementPage from "./pages/position-management";
import MigratedDataManagementPage from "./pages/position-management/MigratedDataManagementPage";
import UserPositionApprovalPage from "./pages/UserPositionApprovalPage";
import ViewMigratedDataPage from "./components/MigratedRecords/ViewMigratedDataPage";
import AllRecordsPage from "./all-records/pages/AllRecordsPage";
import AllRecordDetailsPage from "./all-records/pages/AllRecordDetailsPage";
import Branding from "./web-Management/Branding/Branding";
import { AppLayout } from "./Applayout";
import ActivityLogPage from "@/pages/ActivityLogPage";
import AdminRegistrationPage from "@/pages/Organizations/AdminRegistrationPage";
import OrganizationAdminsPage from "@/pages/OrganizationAdminsPage";
import UserProfileEditPage from "@/pages/UserProfileEditPage";
import UploadedDocumentViewPage from "@/pages/UploadedDocumentViewPage";
import EditOrganizationPage from "@/pages/Organizations/EditOrganizationPage";
import NewOrganizationPage from "@/pages/Organizations/NewOrganizationPage";
import OrganizationDetailPage from "@/pages/Organizations/OrganizationDetailPage";
import OrganizationsPage from "@/pages/Organizations/OrganizationsPage";
import DashboardPage from "@/pages/DashboardPage";
import AddSitePage from "@/pages/AddSitePage";
import SuperAdminArchivedPage from "@/pages/SuperAdminArchivedPage";
import SuperAdminArchiveUsersPage from "@/pages/SuperAdminArchiveUsersPage";
import SettingsPage from "@/pages/SettingsPage";
import OrgAdminDashboard from "@/pages/OrgAdminDashboard";
import ContentManagementPage from "@/pages/ContentManagementPage";
import BulkUploadPage from "@/pages/BulkUploadPage";
import WebManagement from "@/pages/WebManagementPage";
import ArchiveUsersPage from "@/pages/ArchiveUsersPage";
import SectorReportsPage from "@/record-management/pages/User/sectorReports";
import ArchivedUnitsPositionsPage from "@/pages/ArchivedUnitsPositionsPage";
import ConfigurationPage from "@/pages/ConfigurationPage";
import { SidebarProvider } from "@/shared/common/ui/sidebar";
import { AuthProvider as UmAuthProvider } from "@/shared/context/AuthContext";
import { PermissionProvider } from "@/shared/context/PermissionContext";
import UserManagementPage from "@/pages/UserManagementPage";
/**
* Provider shell for the vendored IAM UI. Feeds its Auth + Permission contexts
* from the real freight session so AppMenuTabs / pages see the signed-in user
* and their permission keys (otherwise both are null/empty). Wraps AppLayout in
* SidebarProvider (its useSidebar dependency).
*/
function UmShell(): ReactElement {
const { user } = useAuth();
return (
<UmAuthProvider>
<PermissionProvider
// eslint-disable-next-line @typescript-eslint/no-explicit-any
permissions={(user?.permissions as any) ?? []}
>
<SidebarProvider>
<AppLayout />
</SidebarProvider>
</PermissionProvider>
</UmAuthProvider>
);
}
/**
* Layout wrapper for the user-management route subtree. Self-contained (the
* original vendored AppLayout was removed when the folder was re-copied and it
* pulled the un-migrated @/record-management chrome). Just renders the matched
* child route; swap in the real IAM shell later if desired.
*/
/**
* Role gate for the nested super-admin / org-admin route groups. Renders child
* routes via <Outlet /> only when the user holds an allowed role (super admins
* always pass); otherwise bounces to the overview.
*/
function PrivateRoute({ allowedRoles }: { allowedRoles: string[] }): ReactElement {
const { user } = useAuth();
const roleKeys = (user?.roles ?? [])
.map((r) => r.key)
.filter((k): k is string => Boolean(k));
const allowed =
isSuperAdmin(user) || allowedRoles.some((r) => roleKeys.includes(r));
return allowed ? <Outlet /> : <Navigate to="/dashboard/overview" replace />;
}
export const UserManagementRedirect = () => {
const { user } = useAuth();
const roles = user?.roles?.map((r) => r.key) || [];
if (roles.includes("super_admin")) {
return <Navigate to="/user-management/dashboard" replace />;
}
if (roles.includes("admin") || roles.includes("unit_admin")) {
return <Navigate to="/user-management/user_management-dashboard" replace />;
}
return <Navigate to="/" replace />; // fallback
};
/**
* Placeholder for user-management pages present in the source IAM app's route
* map but not yet migrated into this backoffice. Keeps the route live and
* honest instead of failing the build. See the `TODO(um-migration)` markers.
*/
/**
* User-management route subtree. Mount inside the app's <Routes>:
* <Routes>{UserManagementRoutes()}</Routes>
* Child paths are relative (RRv6 forbids absolute paths on nested routes), so
* they serve at /user-management/* under the app root.
*/
export function UserManagementRoutes(): ReactElement {
return (
<Route
element={<UmShell />}
>
<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>
);
}