diff --git a/src/utils/axiosClient.jsx b/src/utils/axiosClient.jsx index e2766d4c..d44679be 100644 --- a/src/utils/axiosClient.jsx +++ b/src/utils/axiosClient.jsx @@ -32,18 +32,90 @@ axiosClient.interceptors.request.use( // // Response interceptor to handle responses globally (optional) // Add an interceptor to handle expired tokens + +// PAST CODE +// axiosClient.interceptors.response.use( +// (response) => response, + +// async (error) => { +// const originalRequest = error.config; + +// // Prevent infinite loop +// if (!originalRequest || originalRequest._retry) { +// return Promise.reject(error); +// } + +// // Only show one toast per request +// if (!originalRequest._toastShown) { +// originalRequest._toastShown = true; + +// if (error.code === "ERR_CONNECTION_REFUSED") { +// showToast("Unable to connect to the server. Please try again later.", "error"); +// } else if (error.code === "ERR_NETWORK") { +// showToast("Network error. Please check your connection.", "error"); +// redirectToLogin(); +// } else if (error.code === "ECONNABORTED") { +// showToast("Request timed out. Please try again.", "error"); +// } else if (error.response) { +// const status = error.response.status; +// const isRefreshRequest = error.config.url.includes("refresh-token"); + +// if (status === 401 && !isRefreshRequest) { +// // Mark as retried to avoid loops +// originalRequest._retry = true; + +// const refreshToken = localStorage.getItem("refreshToken"); + +// if (!refreshToken || error.response.data?.errors === "Invalid or expired refresh token.") { +// redirectToLogin(); +// return Promise.reject(error); +// } + +// try { +// // Refresh token +// const res = await axiosClient.post("/api/Auth/refresh-token", { +// token: localStorage.getItem("jwtToken"), +// refreshToken, +// }); + +// const { token, refreshToken: newRefreshToken } = res.data.data; + +// // Save new tokens +// localStorage.setItem("jwtToken", token); +// localStorage.setItem("refreshToken", newRefreshToken); + +// // Set Authorization header +// originalRequest.headers["Authorization"] = `Bearer ${token}`; + +// // Optional: Instead of retrying, you may choose to reload app or go to home +// return axiosClient(originalRequest); // <== only retry once +// } catch (refreshError) { +// redirectToLogin(); +// return Promise.reject(refreshError); +// } +// } +// } else { +// showToast("An unknown error occurred.", "error"); +// } +// } +// return Promise.reject(error); +// } +// ); + +// Generic API Call + axiosClient.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; - - // Prevent infinite loop - if (!originalRequest || originalRequest._retry) { + //change here + if (!originalRequest || originalRequest._retry > 0) { return Promise.reject(error); } + //add this line + originalRequest._retry = originalRequest._retry || 0; - // Only show one toast per request if (!originalRequest._toastShown) { originalRequest._toastShown = true; @@ -56,21 +128,27 @@ axiosClient.interceptors.response.use( showToast("Request timed out. Please try again.", "error"); } else if (error.response) { const status = error.response.status; - const isRefreshRequest = error.config.url.includes("refresh-token"); + const isRefreshRequest = originalRequest.url.includes("refresh-token"); + // const errorMessage = error.response?.data?.message || error.response?.data?.errors; + + // add this line + if (isLoginAuthError && !isRefreshRequest) { + // showToast(errorMessage || "Authentication failed. Please check your credentials.", "error"); + return Promise.reject(error); + } if (status === 401 && !isRefreshRequest) { - // Mark as retried to avoid loops - originalRequest._retry = true; + originalRequest._retry++; // this add const refreshToken = localStorage.getItem("refreshToken"); - if (!refreshToken || error.response.data?.errors === "Invalid or expired refresh token.") { + if (!refreshToken || errorMessage === "Invalid or expired refresh token.") { + showToast("Your session has expired. Please log in again.", "error"); redirectToLogin(); return Promise.reject(error); } try { - // Refresh token const res = await axiosClient.post("/api/Auth/refresh-token", { token: localStorage.getItem("jwtToken"), refreshToken, @@ -78,19 +156,20 @@ axiosClient.interceptors.response.use( const { token, refreshToken: newRefreshToken } = res.data.data; - // Save new tokens localStorage.setItem("jwtToken", token); localStorage.setItem("refreshToken", newRefreshToken); - // Set Authorization header originalRequest.headers["Authorization"] = `Bearer ${token}`; - // Optional: Instead of retrying, you may choose to reload app or go to home - return axiosClient(originalRequest); // <== only retry once + return axiosClient(originalRequest); } catch (refreshError) { + showToast("Failed to refresh session. Please log in again.", "error"); redirectToLogin(); return Promise.reject(refreshError); } + } else { + const defaultErrorMessage = `Error ${status}: ${error.response?.statusText || "Something went wrong."}`; + showToast(errorMessage || defaultErrorMessage, "error"); } } else { showToast("An unknown error occurred.", "error"); @@ -100,7 +179,6 @@ axiosClient.interceptors.response.use( } ); -// Generic API Call const apiRequest = async (method, url, data = {}, config = {}) => { try { const response = await axiosClient({