feat: add permission-gated navigation and admin access

This commit is contained in:
2026-06-16 16:16:03 +05:30
parent 893b49c701
commit 964b177ae1
18 changed files with 401 additions and 112 deletions

22
src/config/app.routes.ts Normal file
View File

@@ -0,0 +1,22 @@
import { PERMISSIONS } from '@/constants/permissions';
import { ROUTES } from '@/utils/routes';
export type AppRoute = {
path: string;
permission?: string;
};
export const appRoutes: AppRoute[] = [
{
path: ROUTES.ROLES,
permission: PERMISSIONS.ROLE.READ,
},
{
path: ROUTES.USERS,
permission: PERMISSIONS.USER.READ,
},
];
export function getRoutePermission(pathname: string) {
return appRoutes.find((route) => route.path === pathname)?.permission;
}

88
src/config/menu.config.ts Normal file
View File

@@ -0,0 +1,88 @@
import {
LayoutDashboard,
Layers,
Milestone,
Package,
Plus,
Settings,
ShieldCheck,
Users,
} from 'lucide-react';
import type { ComponentType, SVGProps } from 'react';
import { PERMISSIONS } from '@/constants/permissions';
import { ROUTES } from '@/utils/routes';
export type MenuItem = {
title: string;
path?: string;
icon: ComponentType<SVGProps<SVGSVGElement>>;
permission?: string;
children?: MenuItem[];
};
export const menuItems: MenuItem[] = [
{
title: 'Dashboard',
path: ROUTES.DASHBOARD,
icon: LayoutDashboard,
},
{
title: 'New Analysis',
path: ROUTES.UPLOAD,
icon: Plus,
},
{
title: 'Project',
path: ROUTES.PROJECT,
icon: Layers,
},
{
title: 'Package',
path: ROUTES.PACKAGE,
icon: Package,
},
{
title: 'Segment',
path: ROUTES.CHAINAGE,
icon: Milestone,
},
{
title: 'Administration',
icon: Settings,
children: [
{
title: 'Roles',
path: ROUTES.ROLES,
icon: ShieldCheck,
permission: PERMISSIONS.ROLE.READ,
},
{
title: 'Users',
path: ROUTES.USERS,
icon: Users,
permission: PERMISSIONS.USER.READ,
},
],
},
];
export function filterMenuItems(
items: MenuItem[],
hasPermission: (permission?: string) => boolean,
): MenuItem[] {
return items
.map((item): MenuItem | null => {
if (!hasPermission(item.permission)) return null;
const children = item.children ? filterMenuItems(item.children, hasPermission) : undefined;
if (item.children && children?.length === 0 && !item.path) return null;
return {
...item,
children,
};
})
.filter((item): item is MenuItem => item !== null);
}