import { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Truck, Plus, Search, Filter, Edit2, Trash2, X, Loader2, AlertCircle, Gauge, } from 'lucide-react'; import { vehiclesApi } from '../services/api/vehicles'; import { customersApi } from '../services/api/customers'; import type { Vehicle, VehicleType, VehicleStatus, VehicleFilters } from '../types'; import type { Customer } from '../services/api/customers'; const VEHICLE_TYPES: { value: VehicleType; label: string }[] = [ { value: 'truck', label: 'Camion' }, { value: 'trailer', label: 'Trailer' }, { value: 'bus', label: 'Autobus' }, { value: 'pickup', label: 'Pickup' }, { value: 'other', label: 'Otro' }, ]; const VEHICLE_STATUS: { value: VehicleStatus; label: string; color: string }[] = [ { value: 'active', label: 'Activo', color: 'bg-green-100 text-green-800' }, { value: 'inactive', label: 'Inactivo', color: 'bg-gray-100 text-gray-800' }, { value: 'sold', label: 'Vendido', color: 'bg-red-100 text-red-800' }, ]; const vehicleSchema = z.object({ customerId: z.string().min(1, 'Cliente requerido'), licensePlate: z.string().min(1, 'Placas requeridas'), vin: z.string().optional(), economicNumber: z.string().optional(), make: z.string().min(1, 'Marca requerida'), model: z.string().min(1, 'Modelo requerido'), year: z.number().min(1900).max(new Date().getFullYear() + 1), color: z.string().optional(), vehicleType: z.enum(['truck', 'trailer', 'bus', 'pickup', 'other']), currentOdometer: z.number().optional(), notes: z.string().optional(), }); type VehicleForm = z.infer; export function VehiclesPage() { const queryClient = useQueryClient(); const [filters, setFilters] = useState({ page: 1, pageSize: 20 }); const [searchTerm, setSearchTerm] = useState(''); const [showModal, setShowModal] = useState(false); const [editingVehicle, setEditingVehicle] = useState(null); const [customerSearch, setCustomerSearch] = useState(''); const [showCustomerDropdown, setShowCustomerDropdown] = useState(false); const [selectedCustomer, setSelectedCustomer] = useState(null); const { register, handleSubmit, reset, setValue, formState: { errors }, } = useForm({ resolver: zodResolver(vehicleSchema), defaultValues: { vehicleType: 'truck', year: new Date().getFullYear(), }, }); // Fetch vehicles const { data, isLoading, error } = useQuery({ queryKey: ['vehicles', filters], queryFn: () => vehiclesApi.list(filters), }); // Fetch customers for search const { data: customersData } = useQuery({ queryKey: ['customers', customerSearch], queryFn: () => customersApi.list({ search: customerSearch, pageSize: 10 }), enabled: customerSearch.length >= 2, }); // Create mutation const createMutation = useMutation({ mutationFn: (data: VehicleForm) => vehiclesApi.create(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); handleCloseModal(); }, }); // Update mutation const updateMutation = useMutation({ mutationFn: ({ id, data }: { id: string; data: Partial }) => vehiclesApi.update(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); handleCloseModal(); }, }); // Delete mutation const deleteMutation = useMutation({ mutationFn: (id: string) => vehiclesApi.delete(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); }, }); const vehicles = data?.data?.data || []; const customers = customersData?.data?.data || []; const handleSearch = () => { setFilters({ ...filters, search: searchTerm, page: 1 }); }; const handleOpenCreate = () => { setEditingVehicle(null); setSelectedCustomer(null); setCustomerSearch(''); reset({ vehicleType: 'truck', year: new Date().getFullYear(), }); setShowModal(true); }; const handleOpenEdit = (vehicle: Vehicle) => { setEditingVehicle(vehicle); reset({ customerId: vehicle.customerId, licensePlate: vehicle.licensePlate, vin: vehicle.vin, economicNumber: vehicle.economicNumber, make: vehicle.make, model: vehicle.model, year: vehicle.year, color: vehicle.color, vehicleType: vehicle.vehicleType, currentOdometer: vehicle.currentOdometer, notes: vehicle.notes, }); setShowModal(true); }; const handleCloseModal = () => { setShowModal(false); setEditingVehicle(null); setSelectedCustomer(null); reset(); }; const handleCustomerSelect = (customer: Customer) => { setSelectedCustomer(customer); setValue('customerId', customer.id); setShowCustomerDropdown(false); setCustomerSearch(customer.name); }; const onSubmit = (data: VehicleForm) => { if (editingVehicle) { updateMutation.mutate({ id: editingVehicle.id, data }); } else { createMutation.mutate(data); } }; const handleDelete = (vehicle: Vehicle) => { if (confirm(`Eliminar vehiculo ${vehicle.make} ${vehicle.model}?`)) { deleteMutation.mutate(vehicle.id); } }; return (
{/* Header */}

Vehiculos

Gestiona los vehiculos registrados

{/* Filters */}
setSearchTerm(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleSearch()} className="w-full rounded-lg border border-gray-300 py-2 pl-10 pr-4 text-sm focus:border-diesel-500 focus:outline-none focus:ring-1 focus:ring-diesel-500" />
{/* Table */}
{isLoading ? (
) : error ? (

Error al cargar vehiculos

) : vehicles.length === 0 ? (

No hay vehiculos registrados

) : ( {vehicles.map((vehicle: Vehicle) => { const typeLabel = VEHICLE_TYPES.find(t => t.value === vehicle.vehicleType)?.label || vehicle.vehicleType; const statusConfig = VEHICLE_STATUS.find(s => s.value === vehicle.status) || VEHICLE_STATUS[0]; return ( ); })}
Vehiculo Placas Tipo Odometro Estado Acciones

{vehicle.make} {vehicle.model}

{vehicle.year}

{vehicle.licensePlate}

{vehicle.economicNumber && (

Eco: {vehicle.economicNumber}

)}
{typeLabel} {vehicle.currentOdometer ? ( {vehicle.currentOdometer.toLocaleString()} km ) : '-'} {statusConfig.label}
)} {/* Pagination */} {data?.data && vehicles.length > 0 && (
Pagina {data.data.page} de {data.data.totalPages}
)}
{/* Modal */} {showModal && (

{editingVehicle ? 'Editar Vehiculo' : 'Nuevo Vehiculo'}

{/* Customer Search */} {!editingVehicle && (
{ setCustomerSearch(e.target.value); setShowCustomerDropdown(true); }} onFocus={() => setShowCustomerDropdown(true)} className="w-full rounded-lg border border-gray-300 py-2 pl-10 pr-4 text-sm focus:border-diesel-500 focus:outline-none" />
{showCustomerDropdown && customers.length > 0 && (
{customers.map((customer: Customer) => ( ))}
)} {selectedCustomer && (
Cliente: {selectedCustomer.name}
)} {errors.customerId && (

{errors.customerId.message}

)}
)}
{errors.make &&

{errors.make.message}

}
{errors.model &&

{errors.model.message}

}
{errors.year &&

{errors.year.message}

}
{errors.licensePlate &&

{errors.licensePlate.message}

}