From 7961971ad0f5e4813f22f1162d84934134afda13 Mon Sep 17 00:00:00 2001 From: marco370 <48531002-marco370@users.noreply.replit.com> Date: Wed, 29 Oct 2025 08:08:37 +0000 Subject: [PATCH] Organize the main navigation menu with new sub-menus and updated labels Refactor the `app-sidebar.tsx` component to restructure the navigation menu, introducing collapsible sub-menus for planning and master data, and renaming several menu items. Replit-Commit-Author: Agent Replit-Commit-Session-Id: e0b5b11c-5b75-4389-8ea9-5f3cd9332f88 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e0b5b11c-5b75-4389-8ea9-5f3cd9332f88/EPTvOHB --- .replit | 4 + client/src/components/app-sidebar.tsx | 280 +++++++++++++++++--------- 2 files changed, 191 insertions(+), 93 deletions(-) diff --git a/.replit b/.replit index 6b5c189..bc23a6a 100644 --- a/.replit +++ b/.replit @@ -19,6 +19,10 @@ externalPort = 80 localPort = 33035 externalPort = 3001 +[[ports]] +localPort = 40417 +externalPort = 8000 + [[ports]] localPort = 41295 externalPort = 5173 diff --git a/client/src/components/app-sidebar.tsx b/client/src/components/app-sidebar.tsx index 561e184..e636d2f 100644 --- a/client/src/components/app-sidebar.tsx +++ b/client/src/components/app-sidebar.tsx @@ -12,6 +12,11 @@ import { Car, Briefcase, Navigation, + ChevronDown, + FileText, + FolderKanban, + Building2, + Wrench, } from "lucide-react"; import { Link, useLocation } from "wouter"; import { @@ -23,15 +28,31 @@ import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, + SidebarMenuSub, + SidebarMenuSubItem, + SidebarMenuSubButton, SidebarHeader, SidebarFooter, } from "@/components/ui/sidebar"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; import { useAuth } from "@/hooks/useAuth"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Button } from "@/components/ui/button"; import { ThemeToggle } from "@/components/theme-toggle"; -const menuItems = [ +interface MenuItem { + title: string; + url?: string; + icon: any; + roles: string[]; + items?: MenuItem[]; +} + +const menuItems: MenuItem[] = [ { title: "Dashboard", url: "/", @@ -39,100 +60,117 @@ const menuItems = [ roles: ["admin", "coordinator", "guard", "client"], }, { - title: "Turni", - url: "/shifts", - icon: Calendar, - roles: ["admin", "coordinator", "guard"], - }, - { - title: "Pianificazione", - url: "/planning", - icon: ClipboardList, + title: "Planning", + icon: FolderKanban, roles: ["admin", "coordinator"], + items: [ + { + title: "Fissi", + url: "/general-planning", + icon: Calendar, + roles: ["admin", "coordinator"], + }, + { + title: "Mobili", + url: "/planning-mobile", + icon: Navigation, + roles: ["admin", "coordinator"], + }, + { + title: "Vista", + url: "/service-planning", + icon: ClipboardList, + roles: ["admin", "coordinator"], + }, + ], }, { - title: "Pianificazione Operativa", - url: "/operational-planning", - icon: Calendar, - roles: ["admin", "coordinator"], - }, - { - title: "Planning Fissi", - url: "/general-planning", - icon: BarChart3, - roles: ["admin", "coordinator"], - }, - { - title: "Planning Mobile", - url: "/planning-mobile", - icon: Navigation, - roles: ["admin", "coordinator"], - }, - { - title: "Planning di Servizio", - url: "/service-planning", - icon: ClipboardList, - roles: ["admin", "coordinator"], - }, - { - title: "Gestione Pianificazioni", + title: "Scadenziario", url: "/advanced-planning", - icon: ClipboardList, + icon: Calendar, roles: ["admin", "coordinator"], }, { - title: "Guardie", - url: "/guards", - icon: Users, + title: "Anagrafiche", + icon: Building2, roles: ["admin", "coordinator"], + items: [ + { + title: "Guardie", + url: "/guards", + icon: Users, + roles: ["admin", "coordinator"], + }, + { + title: "Siti", + url: "/sites", + icon: MapPin, + roles: ["admin", "coordinator", "client"], + }, + { + title: "Clienti", + url: "/customers", + icon: Briefcase, + roles: ["admin", "coordinator"], + }, + { + title: "Automezzi", + url: "/vehicles", + icon: Car, + roles: ["admin", "coordinator"], + }, + ], }, { - title: "Siti", - url: "/sites", - icon: MapPin, - roles: ["admin", "coordinator", "client"], - }, - { - title: "Clienti", - url: "/customers", - icon: Briefcase, - roles: ["admin", "coordinator"], - }, - { - title: "Servizi", - url: "/services", - icon: Briefcase, - roles: ["admin", "coordinator"], - }, - { - title: "Parco Automezzi", - url: "/vehicles", - icon: Car, + title: "Tipologia", + icon: Wrench, roles: ["admin", "coordinator"], + items: [ + { + title: "Servizi", + url: "/services", + icon: Briefcase, + roles: ["admin", "coordinator"], + }, + { + title: "Contratti", + url: "/parameters", + icon: Settings, + roles: ["admin", "coordinator"], + }, + ], }, { title: "Report", - url: "/reports", icon: BarChart3, roles: ["admin", "coordinator", "client"], + items: [ + { + title: "Report Amministrativo", + url: "/reports", + icon: FileText, + roles: ["admin", "coordinator", "client"], + }, + ], }, { - title: "Notifiche", - url: "/notifications", - icon: Bell, - roles: ["admin", "coordinator", "guard"], - }, - { - title: "Utenti", - url: "/users", - icon: UserCog, - roles: ["admin"], - }, - { - title: "Parametri", - url: "/parameters", + title: "Utilità", icon: Settings, - roles: ["admin", "coordinator"], + roles: ["admin", "coordinator", "guard"], + items: [ + { + title: "Utenti", + url: "/users", + icon: UserCog, + roles: ["admin"], + }, + { + title: "Notifiche", + url: "/notifications", + icon: Bell, + roles: ["admin", "coordinator", "guard"], + }, + ], }, ]; @@ -140,9 +178,78 @@ export function AppSidebar() { const { user } = useAuth(); const [location] = useLocation(); - const filteredItems = menuItems.filter( - (item) => user && item.roles.includes(user.role) - ); + const filterMenuItems = (items: MenuItem[]): MenuItem[] => { + if (!user) return []; + + return items.filter((item) => { + const hasRole = item.roles.includes(user.role); + if (!hasRole) return false; + + if (item.items) { + item.items = filterMenuItems(item.items); + return item.items.length > 0; + } + + return true; + }); + }; + + const filteredItems = filterMenuItems(menuItems); + + const renderMenuItem = (item: MenuItem) => { + // Menu item con sottomenu + if (item.items && item.items.length > 0) { + const isAnySubItemActive = item.items.some((subItem) => location === subItem.url); + + return ( + + + + + + {item.title} + + + + + + {item.items.map((subItem) => ( + + + + + {subItem.title} + + + + ))} + + + + + ); + } + + // Menu item semplice + return ( + + + + + {item.title} + + + + ); + }; return ( @@ -161,20 +268,7 @@ export function AppSidebar() { Menu Principale - {filteredItems.map((item) => ( - - - - - {item.title} - - - - ))} + {filteredItems.map(renderMenuItem)}