import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Badge } from "@/components/ui/badge"; import { Download, Users, Building2, Clock, TrendingUp } from "lucide-react"; import { format } from "date-fns"; import { it } from "date-fns/locale"; type Location = "roccapiemonte" | "milano" | "roma"; interface GuardReport { guardId: string; guardName: string; badgeNumber: string; ordinaryHours: number; overtimeHours: number; totalHours: number; mealVouchers: number; workingDays: number; } interface SiteReport { siteId: string; siteName: string; serviceTypes: { name: string; hours: number; shifts: number; }[]; totalHours: number; totalShifts: number; } export default function Reports() { const [selectedLocation, setSelectedLocation] = useState("roccapiemonte"); const [selectedMonth, setSelectedMonth] = useState(format(new Date(), "yyyy-MM")); // Query per report guardie const { data: guardReport, isLoading: isLoadingGuards } = useQuery<{ month: string; location: string; guards: GuardReport[]; summary: { totalGuards: number; totalOrdinaryHours: number; totalOvertimeHours: number; totalHours: number; totalMealVouchers: number; }; }>({ queryKey: ["/api/reports/monthly-guard-hours", selectedMonth, selectedLocation], queryFn: async () => { const response = await fetch(`/api/reports/monthly-guard-hours?month=${selectedMonth}&location=${selectedLocation}`); if (!response.ok) throw new Error("Failed to fetch guard report"); return response.json(); }, }); // Query per report siti const { data: siteReport, isLoading: isLoadingSites } = useQuery<{ month: string; location: string; sites: SiteReport[]; summary: { totalSites: number; totalHours: number; totalShifts: number; }; }>({ queryKey: ["/api/reports/billable-site-hours", selectedMonth, selectedLocation], queryFn: async () => { const response = await fetch(`/api/reports/billable-site-hours?month=${selectedMonth}&location=${selectedLocation}`); if (!response.ok) throw new Error("Failed to fetch site report"); return response.json(); }, }); // Genera mesi disponibili (ultimi 12 mesi) const availableMonths = Array.from({ length: 12 }, (_, i) => { const date = new Date(); date.setMonth(date.getMonth() - i); return format(date, "yyyy-MM"); }); // Export CSV guardie const exportGuardsCSV = () => { if (!guardReport?.guards) return; const headers = "Guardia,Badge,Ore Ordinarie,Ore Straordinarie,Ore Totali,Buoni Pasto,Giorni Lavorativi\n"; const rows = guardReport.guards.map(g => `"${g.guardName}",${g.badgeNumber},${g.ordinaryHours},${g.overtimeHours},${g.totalHours},${g.mealVouchers},${g.workingDays}` ).join("\n"); const csv = headers + rows; const blob = new Blob([csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `ore_guardie_${selectedMonth}_${selectedLocation}.csv`; a.click(); }; // Export CSV siti const exportSitesCSV = () => { if (!siteReport?.sites) return; const headers = "Sito,Tipologia Servizio,Ore,Turni\n"; const rows = siteReport.sites.flatMap(s => s.serviceTypes.map(st => `"${s.siteName}","${st.name}",${st.hours},${st.shifts}` ) ).join("\n"); const csv = headers + rows; const blob = new Blob([csv], { type: "text/csv" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `ore_siti_${selectedMonth}_${selectedLocation}.csv`; a.click(); }; return (
{/* Header */}

Report e Export

Ore lavorate, buoni pasto e fatturazione

{/* Filtri */}
{/* Tabs Report */} Report Guardie Report Siti {/* Tab Report Guardie */} {isLoadingGuards ? (
) : guardReport ? ( <> {/* Summary cards */}
Guardie

{guardReport.summary.totalGuards}

Ore Ordinarie

{guardReport.summary.totalOrdinaryHours}h

Ore Straordinarie

{guardReport.summary.totalOvertimeHours}h

Buoni Pasto

{guardReport.summary.totalMealVouchers}

{/* Tabella guardie */}
Dettaglio Ore per Guardia Ordinarie, straordinarie e buoni pasto
{guardReport.guards.length > 0 ? (
{guardReport.guards.map((guard) => ( ))}
Guardia Badge Ore Ord. Ore Strao. Totale Buoni Pasto Giorni
{guard.guardName} {guard.badgeNumber} {guard.ordinaryHours}h {guard.overtimeHours > 0 ? `${guard.overtimeHours}h` : "-"} {guard.totalHours}h {guard.mealVouchers} {guard.workingDays}
) : (

Nessuna guardia con ore lavorate

)}
) : null}
{/* Tab Report Siti */} {isLoadingSites ? (
) : siteReport ? ( <> {/* Summary cards */}
Siti Attivi

{siteReport.summary.totalSites}

Ore Fatturabili

{siteReport.summary.totalHours}h

Turni Totali

{siteReport.summary.totalShifts}

{/* Tabella siti */}
Ore Fatturabili per Sito Raggruppate per tipologia servizio
{siteReport.sites.length > 0 ? (
{siteReport.sites.map((site) => (

{site.siteName}

{site.totalHours}h totali {site.totalShifts} turni
{site.serviceTypes.map((st, idx) => (
{st.name}
{st.shifts} turni {st.hours}h
))}
))}
) : (

Nessun sito con ore fatturabili

)}
) : null}
); }