Add new page designs

This commit is contained in:
Urtzi Alfaro
2025-08-30 19:11:15 +02:00
parent 221781731c
commit 62b1ab9cb1
12 changed files with 2129 additions and 1240 deletions

View File

@@ -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, () => ({