diff --git a/client/src/pages/general-planning.tsx b/client/src/pages/general-planning.tsx index 8fbc718..5167aca 100644 --- a/client/src/pages/general-planning.tsx +++ b/client/src/pages/general-planning.tsx @@ -2,12 +2,21 @@ import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { format, startOfWeek, addWeeks } from "date-fns"; import { it } from "date-fns/locale"; +import { useLocation } from "wouter"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; -import { ChevronLeft, ChevronRight, Calendar, MapPin, Users, AlertTriangle, Car } from "lucide-react"; +import { ChevronLeft, ChevronRight, Calendar, MapPin, Users, AlertTriangle, Car, Edit } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Skeleton } from "@/components/ui/skeleton"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@/components/ui/dialog"; interface GuardWithHours { guardId: string; @@ -50,8 +59,10 @@ interface GeneralPlanningResponse { } export default function GeneralPlanning() { + const [, navigate] = useLocation(); const [selectedLocation, setSelectedLocation] = useState("roccapiemonte"); const [weekStart, setWeekStart] = useState(() => startOfWeek(new Date(), { weekStartsOn: 1 })); + const [selectedCell, setSelectedCell] = useState<{ siteId: string; siteName: string; date: string; data: SiteData } | null>(null); // Query per dati planning settimanale const { data: planningData, isLoading } = useQuery({ @@ -86,6 +97,19 @@ export default function GeneralPlanning() { new Map(allSites.map(site => [site.siteId, site])).values() ); + // Handler per aprire dialog cella + const handleCellClick = (siteId: string, siteName: string, date: string, data: SiteData) => { + setSelectedCell({ siteId, siteName, date, data }); + }; + + // Naviga a pianificazione operativa con parametri + const navigateToOperationalPlanning = () => { + if (selectedCell) { + // Encode parameters nella URL + navigate(`/operational-planning?date=${selectedCell.date}&location=${selectedLocation}`); + } + }; + return (
{/* Header */} @@ -219,6 +243,7 @@ export default function GeneralPlanning() { key={day.date} className="p-2 border-r hover:bg-accent/5 cursor-pointer" data-testid={`cell-${site.siteId}-${day.date}`} + onClick={() => daySiteData && handleCellClick(site.siteId, site.siteName, day.date, daySiteData)} > {daySiteData && daySiteData.shiftsCount > 0 ? (
@@ -298,6 +323,111 @@ export default function GeneralPlanning() { )} + + {/* Dialog dettagli cella */} + setSelectedCell(null)}> + + + + + {selectedCell?.siteName} + + + {selectedCell && format(new Date(selectedCell.date), "EEEE dd MMMM yyyy", { locale: it })} + + + + {selectedCell && ( +
+ {/* Info turni */} +
+
+

Turni Pianificati

+

{selectedCell.data.shiftsCount}

+
+
+

Ore Totali

+

{selectedCell.data.totalShiftHours}h

+
+
+ + {/* Guardie assegnate */} + {selectedCell.data.guards.length > 0 && ( +
+
+ + Guardie Assegnate ({selectedCell.data.guards.length}) +
+
+ {selectedCell.data.guards.map((guard, idx) => ( +
+
+

{guard.guardName}

+

{guard.badgeNumber}

+
+ {guard.hours}h +
+ ))} +
+
+ )} + + {/* Veicoli */} + {selectedCell.data.vehicles.length > 0 && ( +
+
+ + Veicoli Assegnati ({selectedCell.data.vehicles.length}) +
+
+ {selectedCell.data.vehicles.map((vehicle, idx) => ( +
+

{vehicle.licensePlate}

+

+ {vehicle.brand} {vehicle.model} +

+
+ ))} +
+
+ )} + + {/* Guardie mancanti */} + {selectedCell.data.missingGuards > 0 && ( +
+
+ + Attenzione: Guardie Mancanti +
+

+ Servono ancora {selectedCell.data.missingGuards}{" "} + {selectedCell.data.missingGuards === 1 ? "guardia" : "guardie"} per coprire completamente il servizio + (calcolato su {selectedCell.data.totalShiftHours}h con max 9h per guardia e {selectedCell.data.minGuards} {selectedCell.data.minGuards === 1 ? "guardia minima" : "guardie minime"} contemporanee) +

+
+ )} + + {/* No turni */} + {selectedCell.data.shiftsCount === 0 && ( +
+ +

Nessun turno pianificato per questa data

+
+ )} +
+ )} + + + + + +
+
); }