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 };