/** * @ai-summary React hooks for vehicles feature */ import React from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { useAuth0 } from '@auth0/auth0-react'; import { vehiclesApi } from '../api/vehicles.api'; import { CreateVehicleRequest, UpdateVehicleRequest } from '../types/vehicles.types'; import toast from 'react-hot-toast'; interface ApiError { response?: { data?: { error?: string; }; }; message?: string; } export const useVehicles = () => { const { isAuthenticated, isLoading } = useAuth0(); console.log('[useVehicles] Hook called - isAuthenticated:', isAuthenticated, 'isLoading:', isLoading); const query = useQuery({ queryKey: ['vehicles'], queryFn: () => { console.log('[useVehicles] Query function called - fetching vehicles'); return vehiclesApi.getAll(); }, enabled: isAuthenticated && !isLoading, staleTime: 5 * 60 * 1000, // 5 minutes - prevent unnecessary refetches gcTime: 10 * 60 * 1000, // 10 minutes cache time retry: (failureCount, error: any) => { // Retry 401 errors up to 3 times for mobile auth timing issues if (error?.response?.status === 401 && failureCount < 3) { console.log(`[Mobile Auth] API retry ${failureCount + 1}/3 for 401 error`); return true; } return false; }, retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), refetchOnWindowFocus: false, // Prevent refetch on window focus refetchOnMount: false, // Only fetch on mount if data is stale }); // Handle success/error with useEffect instead of deprecated callbacks React.useEffect(() => { if (query.data) { console.log('[useVehicles] Query success - vehicles loaded:', Array.isArray(query.data) ? query.data.length : 0); } if (query.error) { console.log('[useVehicles] Query error:', query.error); } }, [query.data, query.error]); return query; }; export const useVehicle = (id: string) => { const { isAuthenticated, isLoading } = useAuth0(); return useQuery({ queryKey: ['vehicles', id], queryFn: () => vehiclesApi.getById(id), enabled: !!id && isAuthenticated && !isLoading, retry: (failureCount, error: any) => { // Retry 401 errors up to 3 times for mobile auth timing issues if (error?.response?.status === 401 && failureCount < 3) { console.log(`[Mobile Auth] API retry ${failureCount + 1}/3 for 401 error`); return true; } return false; }, retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), }); }; export const useCreateVehicle = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (data: CreateVehicleRequest) => vehiclesApi.create(data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); toast.success('Vehicle added successfully'); }, onError: (error: ApiError) => { toast.error(error.response?.data?.error || 'Failed to add vehicle'); }, }); }; export const useUpdateVehicle = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: ({ id, data }: { id: string; data: UpdateVehicleRequest }) => vehiclesApi.update(id, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); toast.success('Vehicle updated successfully'); }, onError: (error: ApiError) => { toast.error(error.response?.data?.error || 'Failed to update vehicle'); }, }); }; export const useDeleteVehicle = () => { const queryClient = useQueryClient(); return useMutation({ mutationFn: (id: string) => vehiclesApi.delete(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['vehicles'] }); toast.success('Vehicle deleted successfully'); }, onError: (error: ApiError) => { toast.error(error.response?.data?.error || 'Failed to delete vehicle'); }, }); };