// FIXME: all the responses should extend this interface // import type { ApiResponse } from '@/types/apiResponse'; import { useToast } from '@rkheftan/harmony-ui'; import type { AxiosError } from 'axios'; import { useState, useEffect, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; // Define options for the hook interface UseApiOptions { // If true, the API call will be executed immediately on mount immediate?: boolean; } export function useApi( apiFunction: (...args: P) => Promise<{ data: T }>, options: UseApiOptions = {}, ) { const toast = useToast(); const navigate = useNavigate(); const { t } = useTranslation(); const [data, setData] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const execute = useCallback( async (...args: P) => { setLoading(true); setError(null); try { const response = await apiFunction(...args); setData(response.data); return response.data; } catch (err: unknown) { const axiosError = err as AxiosError; console.log(axiosError); // Check for network error first if (axiosError.code === 'ERR_NETWORK') { toast({ message: t('messages.networkError'), severity: 'error', }); } // Check for HTTP status codes on the response object else if (axiosError.response) { if (axiosError.response.status === 401) { navigate('/login'); } if (axiosError.response.status === 500) { toast({ message: t('messages.serverError'), severity: 'error', }); } } setError(err); } finally { setLoading(false); } }, [apiFunction, navigate, t, toast], ); // If the 'immediate' option is true, execute the function on mount useEffect(() => { if (options.immediate) { execute(...([] as unknown as P)); // safe default: no args } }, [execute, options.immediate]); return { data, loading, error, execute }; }