import { useQuery } from "@tanstack/react-query"; import { ShiftWithDetails, Guard } from "@shared/schema"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { BarChart3, Users, Clock, Calendar, TrendingUp } from "lucide-react"; import { Skeleton } from "@/components/ui/skeleton"; import { differenceInHours, format, startOfMonth, endOfMonth } from "date-fns"; import { it } from "date-fns/locale"; export default function Reports() { const { data: shifts, isLoading: shiftsLoading } = useQuery({ queryKey: ["/api/shifts"], }); const { data: guards, isLoading: guardsLoading } = useQuery({ queryKey: ["/api/guards"], }); const isLoading = shiftsLoading || guardsLoading; // Calculate statistics const completedShifts = shifts?.filter(s => s.status === "completed") || []; const totalHours = completedShifts.reduce((acc, shift) => { return acc + differenceInHours(new Date(shift.endTime), new Date(shift.startTime)); }, 0); // Hours per guard const hoursPerGuard: Record = {}; completedShifts.forEach(shift => { shift.assignments.forEach(assignment => { const guardId = assignment.guardId; const guardName = `${assignment.guard.user?.firstName || ""} ${assignment.guard.user?.lastName || ""}`.trim(); const hours = differenceInHours(new Date(shift.endTime), new Date(shift.startTime)); if (!hoursPerGuard[guardId]) { hoursPerGuard[guardId] = { name: guardName, hours: 0 }; } hoursPerGuard[guardId].hours += hours; }); }); const guardStats = Object.values(hoursPerGuard).sort((a, b) => b.hours - a.hours); // Monthly statistics const currentMonth = new Date(); const monthStart = startOfMonth(currentMonth); const monthEnd = endOfMonth(currentMonth); const monthlyShifts = completedShifts.filter(s => { const shiftDate = new Date(s.startTime); return shiftDate >= monthStart && shiftDate <= monthEnd; }); const monthlyHours = monthlyShifts.reduce((acc, shift) => { return acc + differenceInHours(new Date(shift.endTime), new Date(shift.startTime)); }, 0); return (

Report e Statistiche

Ore lavorate e copertura servizi

{isLoading ? (
) : ( <> {/* Summary Cards */}
Ore Totali Lavorate

{totalHours}h

{completedShifts.length} turni completati

Ore Mese Corrente

{monthlyHours}h

{format(currentMonth, "MMMM yyyy", { locale: it })}

Guardie Attive

{guardStats.length}

Con turni completati

{/* Hours per Guard */} Ore per Guardia Ore totali lavorate per ogni guardia {guardStats.length > 0 ? (
{guardStats.map((stat, index) => (

{stat.name}

{stat.hours}h

))}
) : (

Nessun dato disponibile

)} {/* Recent Shifts Summary */} Turni Recenti Ultimi turni completati {completedShifts.length > 0 ? (
{completedShifts.slice(0, 5).map((shift) => (

{shift.site.name}

{format(new Date(shift.startTime), "dd MMM yyyy", { locale: it })}

{differenceInHours(new Date(shift.endTime), new Date(shift.startTime))}h

{shift.assignments.length} guardie

))}
) : (

Nessun turno completato

)}
)}
); }