Files
motovaultpro/frontend/src/features/vehicles/hooks/useVehicles.ts
Eric gullickson d4ca0ba8ae Debugging
2025-09-22 20:58:02 -05:00

124 lines
3.9 KiB
TypeScript

/**
* @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');
},
});
};