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)}