186 lines
5.5 KiB
JavaScript
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 };
|