Add new page designs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useCallback, forwardRef } from 'react';
|
||||
import React, { useState, useCallback, forwardRef, useMemo } from 'react';
|
||||
import { clsx } from 'clsx';
|
||||
import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { useAuthUser, useIsAuthenticated } from '../../../stores';
|
||||
@@ -127,53 +127,55 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
|
||||
const sidebarRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
// Get navigation routes from config
|
||||
const navigationRoutes = getNavigationRoutes();
|
||||
|
||||
// Convert route config to navigation items
|
||||
const convertRoutesToItems = (routes: typeof navigationRoutes): NavigationItem[] => {
|
||||
return routes.map(route => ({
|
||||
id: route.path,
|
||||
label: route.title,
|
||||
path: route.path,
|
||||
icon: route.icon ? iconMap[route.icon] : undefined,
|
||||
requiredPermissions: route.requiredPermissions,
|
||||
requiredRoles: route.requiredRoles,
|
||||
children: route.children ? convertRoutesToItems(route.children) : undefined,
|
||||
}));
|
||||
};
|
||||
// Get navigation routes from config and convert to navigation items - memoized
|
||||
const navigationItems = useMemo(() => {
|
||||
const navigationRoutes = getNavigationRoutes();
|
||||
|
||||
const convertRoutesToItems = (routes: typeof navigationRoutes): NavigationItem[] => {
|
||||
return routes.map(route => ({
|
||||
id: route.path,
|
||||
label: route.title,
|
||||
path: route.path,
|
||||
icon: route.icon ? iconMap[route.icon] : undefined,
|
||||
requiredPermissions: route.requiredPermissions,
|
||||
requiredRoles: route.requiredRoles,
|
||||
children: route.children ? convertRoutesToItems(route.children) : undefined,
|
||||
}));
|
||||
};
|
||||
|
||||
const navigationItems = customItems || convertRoutesToItems(navigationRoutes);
|
||||
return customItems || convertRoutesToItems(navigationRoutes);
|
||||
}, [customItems]);
|
||||
|
||||
// Filter items based on user permissions
|
||||
const filterItemsByPermissions = (items: NavigationItem[]): NavigationItem[] => {
|
||||
if (!isAuthenticated || !user) return [];
|
||||
// Filter items based on user permissions - memoized to prevent infinite re-renders
|
||||
const visibleItems = useMemo(() => {
|
||||
const filterItemsByPermissions = (items: NavigationItem[]): NavigationItem[] => {
|
||||
if (!isAuthenticated || !user) return [];
|
||||
|
||||
return items.filter(item => {
|
||||
const userRoles = user.role ? [user.role] : [];
|
||||
const userPermissions: string[] = user?.permissions || [];
|
||||
return items.map(item => ({
|
||||
...item, // Create a shallow copy to avoid mutation
|
||||
children: item.children ? filterItemsByPermissions(item.children) : item.children
|
||||
})).filter(item => {
|
||||
const userRoles = user.role ? [user.role] : [];
|
||||
const userPermissions: string[] = user?.permissions || [];
|
||||
|
||||
const hasAccess = !item.requiredPermissions && !item.requiredRoles ||
|
||||
canAccessRoute(
|
||||
{
|
||||
path: item.path,
|
||||
requiredRoles: item.requiredRoles,
|
||||
requiredPermissions: item.requiredPermissions
|
||||
} as any,
|
||||
isAuthenticated,
|
||||
userRoles,
|
||||
userPermissions
|
||||
);
|
||||
const hasAccess = !item.requiredPermissions && !item.requiredRoles ||
|
||||
canAccessRoute(
|
||||
{
|
||||
path: item.path,
|
||||
requiredRoles: item.requiredRoles,
|
||||
requiredPermissions: item.requiredPermissions
|
||||
} as any,
|
||||
isAuthenticated,
|
||||
userRoles,
|
||||
userPermissions
|
||||
);
|
||||
|
||||
if (hasAccess && item.children) {
|
||||
item.children = filterItemsByPermissions(item.children);
|
||||
}
|
||||
return hasAccess;
|
||||
});
|
||||
};
|
||||
|
||||
return hasAccess;
|
||||
});
|
||||
};
|
||||
|
||||
const visibleItems = filterItemsByPermissions(navigationItems);
|
||||
return filterItemsByPermissions(navigationItems);
|
||||
}, [navigationItems, isAuthenticated, user]);
|
||||
|
||||
// Handle item click
|
||||
const handleItemClick = useCallback((item: NavigationItem) => {
|
||||
@@ -224,30 +226,30 @@ export const Sidebar = forwardRef<SidebarRef, SidebarProps>(({
|
||||
}, []);
|
||||
|
||||
// Auto-expand parent items for active path
|
||||
React.useEffect(() => {
|
||||
const findParentPaths = (items: NavigationItem[], targetPath: string, parents: string[] = []): string[] => {
|
||||
for (const item of items) {
|
||||
const currentPath = [...parents, item.id];
|
||||
|
||||
if (item.path === targetPath) {
|
||||
return parents;
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
const found = findParentPaths(item.children, targetPath, currentPath);
|
||||
if (found.length > 0) {
|
||||
return found;
|
||||
}
|
||||
const findParentPaths = useCallback((items: NavigationItem[], targetPath: string, parents: string[] = []): string[] => {
|
||||
for (const item of items) {
|
||||
const currentPath = [...parents, item.id];
|
||||
|
||||
if (item.path === targetPath) {
|
||||
return parents;
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
const found = findParentPaths(item.children, targetPath, currentPath);
|
||||
if (found.length > 0) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
};
|
||||
}
|
||||
return [];
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
const parentPaths = findParentPaths(visibleItems, location.pathname);
|
||||
if (parentPaths.length > 0) {
|
||||
setExpandedItems(prev => new Set([...prev, ...parentPaths]));
|
||||
}
|
||||
}, [location.pathname, visibleItems]);
|
||||
}, [location.pathname, findParentPaths, visibleItems]);
|
||||
|
||||
// Expose ref methods
|
||||
React.useImperativeHandle(ref, () => ({
|
||||
|
||||
Reference in New Issue
Block a user