thirukalyanamweb/src/api/axiosInstance.js

186 lines
5.5 KiB
JavaScript

import axios from "axios";
import { API_ENDPOINTS } from "./apiEndpoints";
/**
* Create an Axios instance with the base URL from environment variables
* and default headers for JSON communication.
*/
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_THIRUKALYANAM_API_BASE_URL ||
"https://www.thirukalyanam.amrithaa.net/backend/api/" ,
headers: {
"Content-Type": "application/json",
},
});
/**
* Create a separate Axios instance for handling multipart file uploads
* while sharing the same base URL and authorization mechanism.
*/
const apiForFiles = axios.create({
baseURL: import.meta.env.VITE_THIRUKALYANAM_API_BASE_URL,
headers: {
"Content-Type": "multipart/form-data",
},
});
/**
* Set Access Token
*/
export const setAccessToken = (token) => {
if (token) {
localStorage.setItem("access_token", token); // Store token in localStorage
axiosInstance.defaults.headers["Authorization"] = `Bearer ${token}`;
apiForFiles.defaults.headers["Authorization"] = `Bearer ${token}`;
} else {
localStorage.removeItem("access_token");
delete axiosInstance.defaults.headers["Authorization"];
delete apiForFiles.defaults.headers["Authorization"];
}
};
/**
* Add a request interceptor to include the authorization token
* in the request headers if it exists in localStorage.
*/
const addAuthInterceptor = (instance) => {
instance.interceptors.request.use(
(config) => {
const token = localStorage.getItem("access_token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
};
/**
* Add a response interceptor to handle global error scenarios,
* such as redirecting to the login page on a 401 Unauthorized error.
*/
const addErrorInterceptor = (instance) => {
instance.interceptors.response.use(
(response) => response,
(error) => {
if (error.response && error.response.status === 401 && !error.config?.url?.includes("/login") && !error.config?.url?.includes("/forgot_password_send_otp") && !error.config?.url?.includes("/forgot_password_verify_otp") && !error.config?.url?.includes("/forgot_password_update")) {
console.error("Unauthorized access - logging out...");
localStorage.removeItem("access_token");
// window.location.href = "/";
// SAFE redirect (works outside React)
window.location.replace("/");
} else if (error.response && error.response.status === 403) {
window.location.href = "/";
// navigate("/");
} else if (error.response && error.response.status === 404) {
console.error("404 Error - Endpoint not found:", error.config?.url);
// Don't redirect for 404, let component handle it
} else if (error.response && error.response.status >= 500) {
console.error("Server error:", error.response?.data);
}
return Promise.reject(error);
}
);
};
// Apply interceptors to both instances
addAuthInterceptor(axiosInstance);
addAuthInterceptor(apiForFiles);
addErrorInterceptor(axiosInstance);
addErrorInterceptor(apiForFiles);
/**
* Clear all user data from the browser: localStorage, sessionStorage, and cookies.
*/
export const clearUserData = () => {
try {
// Clear localStorage
localStorage.clear();
// Clear sessionStorage
sessionStorage.clear();
// Clear cookies
document.cookie.split(";").forEach((cookie) => {
const [name] = cookie.split("=");
document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;
});
// Remove authorization headers from Axios instances
delete axiosInstance.defaults.headers["Authorization"];
delete apiForFiles.defaults.headers["Authorization"];
console.log("User data cleared from browser.");
// Add redirect to ensure all tabs show login page
// window.location.href = '/';
} catch (error) {
console.error("Error clearing user data:", error);
}
};
export const urlToFile = async (url, filename = "file") => {
try {
// Use your axios instance to request the URL as a Blob
const response = await apiForFiles.get(url, {
responseType: "blob",
});
// Axios header keys are lowercase
const contentType =
response.headers["content-type"] ||
"*"(
// Guess MIME type based on filename extension
filename.toLowerCase().endsWith(".png")
? "image/png"
: filename.toLowerCase().endsWith(".webp")
? "image/webp"
: filename.toLowerCase().endsWith(".jpg") ||
filename.toLowerCase().endsWith(".jpeg")
? "image/jpeg"
: "application/octet-stream"
);
// Create and return a File object from the blob data
return new File([response.data], filename, { type: contentType });
} catch (error) {
console.error("urlToFile axios error:", error);
return null;
}
};
/**
* Get FCM token from localStorage
*/
const getFcmToken = () => {
return localStorage.getItem("fcm_token");
};
/**
* Clear FCM token from localStorage
*/
const clearFcmToken = () => {
localStorage.removeItem("fcm_token");
};
export const logoutAPI = async () => {
try {
await axiosInstance.post(API_ENDPOINTS.LOGOUT);
} catch (error) {
console.error("Logout API failed:", error);
} finally {
setAccessToken(null);
localStorage.clear();
sessionStorage.clear();
window.location.replace("/login");
}
};
// Export both instances
export default axiosInstance;
export { apiForFiles };