124 lines
3.9 KiB
TypeScript
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');
|
|
},
|
|
});
|
|
};
|