VigilanzaTurni/client/src/components/app-sidebar.tsx
marco370 8bb0386d1e Add customer management features and rename planning view
Implement CRUD operations for customers, including API endpoints and database schema. Rename the "Planning Generale" view to "Planning Fissi" and update related UI elements and documentation.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: e5565357-90e1-419f-b9a8-6ee8394636df
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/6d543d2c-20b9-4ea6-93fe-70fe9b1d9f80/e5565357-90e1-419f-b9a8-6ee8394636df/2w7P7NW
2025-10-23 07:58:57 +00:00

207 lines
5.0 KiB
TypeScript

import {
Calendar,
Shield,
MapPin,
Users,
BarChart3,
Bell,
Settings,
LogOut,
UserCog,
ClipboardList,
Car,
Briefcase,
} from "lucide-react";
import { Link, useLocation } from "wouter";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarHeader,
SidebarFooter,
} from "@/components/ui/sidebar";
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 = [
{
title: "Dashboard",
url: "/",
icon: Shield,
roles: ["admin", "coordinator", "guard", "client"],
},
{
title: "Turni",
url: "/shifts",
icon: Calendar,
roles: ["admin", "coordinator", "guard"],
},
{
title: "Pianificazione",
url: "/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 di Servizio",
url: "/service-planning",
icon: ClipboardList,
roles: ["admin", "coordinator"],
},
{
title: "Gestione Pianificazioni",
url: "/advanced-planning",
icon: ClipboardList,
roles: ["admin", "coordinator"],
},
{
title: "Guardie",
url: "/guards",
icon: Users,
roles: ["admin", "coordinator"],
},
{
title: "Siti",
url: "/sites",
icon: MapPin,
roles: ["admin", "coordinator", "client"],
},
{
title: "Servizi",
url: "/services",
icon: Briefcase,
roles: ["admin", "coordinator"],
},
{
title: "Parco Automezzi",
url: "/vehicles",
icon: Car,
roles: ["admin", "coordinator"],
},
{
title: "Report",
url: "/reports",
icon: BarChart3,
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",
icon: Settings,
roles: ["admin", "coordinator"],
},
];
export function AppSidebar() {
const { user } = useAuth();
const [location] = useLocation();
const filteredItems = menuItems.filter(
(item) => user && item.roles.includes(user.role)
);
return (
<Sidebar>
<SidebarHeader className="p-4 border-b">
<div className="flex items-center gap-3">
<Shield className="h-8 w-8 text-primary" />
<div>
<h1 className="text-lg font-semibold">VigilanzaTurni</h1>
<p className="text-xs text-muted-foreground">Sistema Gestione</p>
</div>
</div>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Menu Principale</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
{filteredItems.map((item) => (
<SidebarMenuItem key={item.title}>
<SidebarMenuButton
asChild
isActive={location === item.url}
data-testid={`link-${item.title.toLowerCase()}`}
>
<Link href={item.url}>
<item.icon className="h-4 w-4" />
<span>{item.title}</span>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter className="p-4 border-t space-y-4">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-3 min-w-0">
<Avatar className="h-8 w-8">
<AvatarImage src={user?.profileImageUrl || undefined} />
<AvatarFallback>
{user?.firstName?.[0]}{user?.lastName?.[0]}
</AvatarFallback>
</Avatar>
<div className="min-w-0">
<p className="text-sm font-medium truncate">
{user?.firstName} {user?.lastName}
</p>
<p className="text-xs text-muted-foreground capitalize">
{user?.role}
</p>
</div>
</div>
<ThemeToggle />
</div>
<div className="flex gap-2">
<Button
variant="outline"
size="sm"
className="flex-1"
onClick={() => window.location.href = '/api/logout'}
data-testid="button-logout"
>
<LogOut className="h-4 w-4 mr-2" />
Esci
</Button>
</div>
</SidebarFooter>
</Sidebar>
);
}