import { useState } from "react"; import { useQuery, useMutation } from "@tanstack/react-query"; import { queryClient, apiRequest } from "@/lib/queryClient"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { insertVehicleSchema, type Vehicle, type Guard } from "@shared/schema"; import { z } from "zod"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Skeleton } from "@/components/ui/skeleton"; import { useToast } from "@/hooks/use-toast"; import { Car, Plus, Pencil, Trash2, Loader2 } from "lucide-react"; const vehicleTypeLabels = { car: "Auto", van: "Furgone", motorcycle: "Moto", suv: "SUV", }; const vehicleStatusLabels = { available: "Disponibile", in_use: "In uso", maintenance: "In manutenzione", out_of_service: "Fuori servizio", }; const vehicleStatusColors = { available: "bg-green-500/10 text-green-500 border-green-500/20", in_use: "bg-blue-500/10 text-blue-500 border-blue-500/20", maintenance: "bg-orange-500/10 text-orange-500 border-orange-500/20", out_of_service: "bg-red-500/10 text-red-500 border-red-500/20", }; type VehicleForm = z.infer; export default function Vehicles() { const { toast } = useToast(); const [createDialogOpen, setCreateDialogOpen] = useState(false); const [editDialogOpen, setEditDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); const [selectedVehicle, setSelectedVehicle] = useState(null); const { data: vehicles, isLoading: isLoadingVehicles } = useQuery({ queryKey: ["/api/vehicles"], }); const { data: guards } = useQuery({ queryKey: ["/api/guards"], }); const createForm = useForm({ resolver: zodResolver(insertVehicleSchema.extend({ year: z.number().min(1900).max(new Date().getFullYear() + 1).optional().or(z.literal(null)), mileage: z.number().min(0).optional().or(z.literal(null)), })), defaultValues: { licensePlate: "", brand: "", model: "", vehicleType: "car", year: undefined, assignedGuardId: null, status: "available", lastMaintenanceDate: null, nextMaintenanceDate: null, mileage: undefined, notes: null, }, }); const editForm = useForm({ resolver: zodResolver(insertVehicleSchema.extend({ year: z.number().min(1900).max(new Date().getFullYear() + 1).optional().or(z.literal(null)), mileage: z.number().min(0).optional().or(z.literal(null)), })), defaultValues: { licensePlate: "", brand: "", model: "", vehicleType: "car", year: undefined, assignedGuardId: null, status: "available", lastMaintenanceDate: null, nextMaintenanceDate: null, mileage: undefined, notes: null, }, }); const createVehicleMutation = useMutation({ mutationFn: async (data: VehicleForm) => { return apiRequest("POST", "/api/vehicles", data); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["/api/vehicles"] }); toast({ title: "Veicolo creato", description: "Il veicolo è stato aggiunto con successo.", }); setCreateDialogOpen(false); createForm.reset(); }, onError: (error: any) => { toast({ title: "Errore", description: error.message || "Impossibile creare il veicolo.", variant: "destructive", }); }, }); const updateVehicleMutation = useMutation({ mutationFn: async ({ id, data }: { id: string; data: VehicleForm }) => { return apiRequest("PATCH", `/api/vehicles/${id}`, data); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["/api/vehicles"] }); toast({ title: "Veicolo aggiornato", description: "Il veicolo è stato modificato con successo.", }); setEditDialogOpen(false); setSelectedVehicle(null); editForm.reset(); }, onError: (error: any) => { toast({ title: "Errore", description: error.message || "Impossibile aggiornare il veicolo.", variant: "destructive", }); }, }); const deleteVehicleMutation = useMutation({ mutationFn: async (id: string) => { return apiRequest("DELETE", `/api/vehicles/${id}`); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["/api/vehicles"] }); toast({ title: "Veicolo eliminato", description: "Il veicolo è stato eliminato con successo.", }); setDeleteDialogOpen(false); setSelectedVehicle(null); }, onError: () => { toast({ title: "Errore", description: "Impossibile eliminare il veicolo.", variant: "destructive", }); }, }); const handleEdit = (vehicle: Vehicle) => { setSelectedVehicle(vehicle); editForm.reset({ licensePlate: vehicle.licensePlate, brand: vehicle.brand, model: vehicle.model, vehicleType: vehicle.vehicleType, year: vehicle.year ?? undefined, assignedGuardId: vehicle.assignedGuardId, status: vehicle.status, lastMaintenanceDate: vehicle.lastMaintenanceDate, nextMaintenanceDate: vehicle.nextMaintenanceDate, mileage: vehicle.mileage ?? undefined, notes: vehicle.notes, }); setEditDialogOpen(true); }; const handleDelete = (vehicle: Vehicle) => { setSelectedVehicle(vehicle); setDeleteDialogOpen(true); }; if (isLoadingVehicles) { return (

Parco Automezzi

Gestione veicoli aziendali

{[1, 2, 3].map((i) => (
))}
); } return (

Parco Automezzi

Gestisci i veicoli aziendali e le assegnazioni

Veicoli Registrati {vehicles?.length || 0} veicoli nel parco aziendale Targa Veicolo Tipo Stato Assegnato a Azioni {vehicles?.map((vehicle) => { const assignedGuard = guards?.find(g => g.id === vehicle.assignedGuardId); return ( {vehicle.licensePlate}

{vehicle.brand} {vehicle.model}

{vehicle.year &&

Anno {vehicle.year}

}
{vehicleTypeLabels[vehicle.vehicleType]} {vehicleStatusLabels[vehicle.status]} {assignedGuard ? ( {assignedGuard.badgeNumber} ) : ( Non assegnato )}
); })}
{vehicles?.length === 0 && (

Nessun veicolo registrato

)}
{/* Create Vehicle Dialog */} Aggiungi Nuovo Veicolo Inserisci i dati del veicolo da aggiungere al parco aziendale.
createVehicleMutation.mutate(data))} className="space-y-4">
( Targa * )} /> ( Tipo * )} />
( Marca * )} /> ( Modello * )} /> ( Anno field.onChange(e.target.value ? parseInt(e.target.value) : null)} /> )} />
( Stato * )} /> ( Assegnato a )} />
( Chilometraggio field.onChange(e.target.value ? parseInt(e.target.value) : null)} /> )} /> ( Note