import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { format, addWeeks, addDays, startOfWeek } from "date-fns"; import { it } from "date-fns/locale"; import { ChevronLeft, ChevronRight, Users, Building2 } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Skeleton } from "@/components/ui/skeleton"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; type Location = "roccapiemonte" | "milano" | "roma"; interface ShiftDetail { shiftId: string; date: string; from: string; to: string; siteName: string; siteId: string; vehicle?: { licensePlate: string; brand: string; model: string; }; hours: number; } interface GuardSchedule { guardId: string; guardName: string; badgeNumber: string; shifts: ShiftDetail[]; totalHours: number; } interface SiteSchedule { siteId: string; siteName: string; location: string; shifts: { shiftId: string; date: string; from: string; to: string; guards: { guardName: string; badgeNumber: string; hours: number; }[]; vehicle?: { licensePlate: string; brand: string; model: string; }; totalGuards: number; totalHours: number; }[]; totalShifts: number; totalHours: number; } export default function ServicePlanning() { const [selectedLocation, setSelectedLocation] = useState("roccapiemonte"); const [weekStart, setWeekStart] = useState(startOfWeek(new Date(), { weekStartsOn: 1 })); const [viewMode, setViewMode] = useState<"guard" | "site">("guard"); const weekStartStr = format(weekStart, "yyyy-MM-dd"); const weekEndStr = format(addDays(weekStart, 6), "yyyy-MM-dd"); // Query per vista Guardie const { data: guardSchedules, isLoading: isLoadingGuards } = useQuery({ queryKey: ["/api/service-planning/by-guard", weekStartStr, selectedLocation], queryFn: async () => { const response = await fetch(`/api/service-planning/by-guard?weekStart=${weekStartStr}&location=${selectedLocation}`); if (!response.ok) throw new Error("Failed to fetch guard schedules"); return response.json(); }, enabled: viewMode === "guard", }); // Query per vista Siti const { data: siteSchedules, isLoading: isLoadingSites } = useQuery({ queryKey: ["/api/service-planning/by-site", weekStartStr, selectedLocation], queryFn: async () => { const response = await fetch(`/api/service-planning/by-site?weekStart=${weekStartStr}&location=${selectedLocation}`); if (!response.ok) throw new Error("Failed to fetch site schedules"); return response.json(); }, enabled: viewMode === "site", }); const goToPreviousWeek = () => setWeekStart(addWeeks(weekStart, -1)); const goToNextWeek = () => setWeekStart(addWeeks(weekStart, 1)); return (
{/* Header */}

Planning di Servizio

Visualizza orari e dotazioni per guardia o sito

{/* Controlli */}
{/* Selezione sede */}
{/* Navigazione settimana */}
{format(weekStart, "d MMM", { locale: it })} - {format(addDays(weekStart, 6), "d MMM yyyy", { locale: it })}
{/* Tabs per vista */} setViewMode(v as "guard" | "site")}> Vista Agente Vista Sito {/* Vista Agente */} {isLoadingGuards ? (
{[1, 2, 3].map((i) => ( ))}
) : guardSchedules && guardSchedules.length > 0 ? (
{guardSchedules.map((guard) => (
{guard.guardName} {guard.badgeNumber} {guard.totalHours}h totali
{guard.shifts.length === 0 ? (

Nessun turno assegnato

) : (
{guard.shifts.map((shift) => (
{shift.siteName}
{format(new Date(shift.date), "EEEE d MMM", { locale: it })} • {shift.from} - {shift.to} ({shift.hours}h)
{shift.vehicle && (
🚗 {shift.vehicle.licensePlate} ({shift.vehicle.brand} {shift.vehicle.model})
)}
))}
)}
))}
) : (

Nessuna guardia con turni assegnati

)}
{/* Vista Sito */} {isLoadingSites ? (
{[1, 2, 3].map((i) => ( ))}
) : siteSchedules && siteSchedules.length > 0 ? (
{siteSchedules.map((site) => (
{site.siteName}
{site.totalShifts} turni {site.totalHours}h totali
{site.shifts.length === 0 ? (

Nessun turno programmato

) : (
{site.shifts.map((shift) => (
{format(new Date(shift.date), "EEEE d MMM", { locale: it })} • {shift.from} - {shift.to}
{shift.totalGuards} {shift.totalGuards === 1 ? "guardia" : "guardie"}
{shift.guards.map((guard, idx) => (
👤 {guard.guardName} ({guard.badgeNumber}) - {guard.hours}h
))}
{shift.vehicle && (
🚗 {shift.vehicle.licensePlate} ({shift.vehicle.brand} {shift.vehicle.model})
)}
))}
)}
))}
) : (

Nessun sito con turni programmati

)}
); }