import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { MapPin, Shield, Car, Clock, User, ChevronLeft, ChevronRight } from "lucide-react"; import { format, addDays, startOfWeek, parseISO, isValid } from "date-fns"; import { it } from "date-fns/locale"; interface GuardAssignment { guardId: string; guardName: string; badgeNumber: string; plannedStartTime: string; plannedEndTime: string; armed: boolean; vehicleId: string | null; vehiclePlate: string | null; } interface SiteDayPlan { date: string; guards: GuardAssignment[]; } interface Site { id: string; name: string; address: string; location: string; } export default function SitePlanningView() { const [selectedSiteId, setSelectedSiteId] = useState(""); const [currentWeekStart, setCurrentWeekStart] = useState(() => { const today = new Date(); return startOfWeek(today, { weekStartsOn: 1 }); }); // Query sites const { data: sites } = useQuery({ queryKey: ["/api/sites"], }); // Query site planning const { data: sitePlanning, isLoading } = useQuery({ queryKey: ["/api/site-planning", selectedSiteId, currentWeekStart.toISOString()], queryFn: async () => { if (!selectedSiteId) return []; const weekEnd = addDays(currentWeekStart, 6); const response = await fetch( `/api/site-planning/${selectedSiteId}?startDate=${currentWeekStart.toISOString()}&endDate=${weekEnd.toISOString()}` ); if (!response.ok) throw new Error("Failed to fetch site planning"); return response.json(); }, enabled: !!selectedSiteId, }); // Naviga settimana precedente const handlePreviousWeek = () => { setCurrentWeekStart(addDays(currentWeekStart, -7)); }; // Naviga settimana successiva const handleNextWeek = () => { setCurrentWeekStart(addDays(currentWeekStart, 7)); }; // Raggruppa per giorno const planningByDay = sitePlanning?.reduce((acc, day) => { acc[day.date] = day.guards; return acc; }, {} as Record) || {}; // Genera array di 7 giorni della settimana const weekDays = Array.from({ length: 7 }, (_, i) => addDays(currentWeekStart, i)); const selectedSite = sites?.find(s => s.id === selectedSiteId); const locationLabels: Record = { roccapiemonte: "Roccapiemonte", milano: "Milano", roma: "Roma", }; return (
{/* Header */}

Planning per Sito

Visualizza tutti gli agenti assegnati a un sito con dotazioni

{/* Selettore sito */} Seleziona Sito
{selectedSite && (

{selectedSite.name}

{selectedSite.address}

)}
{/* Navigazione settimana */} {selectedSiteId && (
{format(currentWeekStart, "dd MMMM", { locale: it })} -{" "} {format(addDays(currentWeekStart, 6), "dd MMMM yyyy", { locale: it })}
)} {/* Loading state */} {isLoading && ( Caricamento planning sito... )} {/* Griglia giorni settimana */} {selectedSiteId && !isLoading && (
{weekDays.map((day) => { const dateStr = format(day, "yyyy-MM-dd"); const dayGuards = planningByDay[dateStr] || []; return ( {format(day, "EEEE dd/MM", { locale: it })} {dayGuards.length === 0 ? "Nessun agente" : `${dayGuards.length} agente${dayGuards.length > 1 ? "i" : ""}`} {dayGuards.length === 0 ? (
Nessuna copertura
) : ( dayGuards.map((guard, index) => { // Parsing sicuro orari let startTime = "N/A"; let endTime = "N/A"; if (guard.plannedStartTime) { const parsedStart = parseISO(guard.plannedStartTime); if (isValid(parsedStart)) { startTime = format(parsedStart, "HH:mm"); } } if (guard.plannedEndTime) { const parsedEnd = parseISO(guard.plannedEndTime); if (isValid(parsedEnd)) { endTime = format(parsedEnd, "HH:mm"); } } return (
{guard.guardName}
Matricola: {guard.badgeNumber}
{startTime} - {endTime}
{/* Dotazioni */}
{guard.armed && ( Armato )} {guard.vehicleId && ( {guard.vehiclePlate || "Automezzo"} )}
); }) )}
); })}
)}
); }