| | import axios from 'axios' |
| |
|
| | |
| | const api = axios.create({ |
| | baseURL: import.meta.env.VITE_API_URL || 'http://localhost:5000/api', |
| | headers: { |
| | 'Content-Type': 'application/json' |
| | }, |
| | |
| | adapter: 'xhr', |
| | withCredentials: true |
| | }) |
| |
|
| | |
| | api.defaults.timeout = 10000 |
| |
|
| | |
| | const isDevelopment = import.meta.env.VITE_NODE_ENV === 'development' |
| | const isProduction = import.meta.env.VITE_NODE_ENV === 'production' |
| |
|
| | |
| | const logApiCall = (config) => { |
| | if (isDevelopment) { |
| | console.log(`π [API] ${config.method?.toUpperCase()} ${config.url}`, { |
| | data: config.data, |
| | params: config.params, |
| | headers: config.headers |
| | }) |
| | } |
| | } |
| |
|
| | |
| | const logApiError = (error) => { |
| | if (isDevelopment) { |
| | console.error(`β [API Error] ${error.config?.url || 'Unknown URL'}`, { |
| | status: error.response?.status, |
| | statusText: error.response?.statusText, |
| | data: error.response?.data, |
| | message: error.message |
| | }) |
| | } |
| | } |
| |
|
| | |
| | api.interceptors.request.use( |
| | (config) => { |
| | |
| | logApiCall(config) |
| | |
| | const token = localStorage.getItem('token') |
| | if (token) { |
| | config.headers.Authorization = `Bearer ${token}` |
| | } |
| | return config |
| | }, |
| | (error) => { |
| | logApiError(error) |
| | return Promise.reject(error) |
| | } |
| | ) |
| |
|
| | |
| | api.interceptors.request.use( |
| | async (config) => { |
| | const token = localStorage.getItem('token') |
| | if (token) { |
| | try { |
| | |
| | const tokenData = JSON.parse(atob(token.split('.')[1])) |
| | const isExpired = tokenData.exp * 1000 < Date.now() |
| | |
| | if (isExpired) { |
| | |
| | localStorage.removeItem('token') |
| | if (isDevelopment) { |
| | console.log('π [Token] Token expired, removed from storage') |
| | } |
| | |
| | |
| | if (!window.location.pathname.includes('/login')) { |
| | window.location.href = '/login' |
| | } |
| | } else { |
| | |
| | config.headers.Authorization = `Bearer ${token}` |
| | } |
| | } catch (error) { |
| | |
| | localStorage.removeItem('token') |
| | if (isDevelopment) { |
| | console.log('π [Token] Invalid token format, removed from storage') |
| | } |
| | |
| | |
| | if (!window.location.pathname.includes('/login')) { |
| | window.location.href = '/login' |
| | } |
| | } |
| | } |
| | return config |
| | }, |
| | (error) => { |
| | logApiError(error) |
| | return Promise.reject(error) |
| | } |
| | ) |
| |
|
| | |
| | api.interceptors.response.use( |
| | (response) => { |
| | if (isDevelopment) { |
| | console.log(`β
[API Response] ${response.config.url}`, { |
| | status: response.status, |
| | data: response.data |
| | }) |
| | } |
| | return response |
| | }, |
| | (error) => { |
| | logApiError(error) |
| | |
| | if (error.response?.status === 401) { |
| | |
| | if (!window.location.pathname.includes('/login')) { |
| | localStorage.removeItem('token') |
| | window.location.href = '/login' |
| | } |
| | } |
| | |
| | |
| | if (error.response) { |
| | |
| | |
| | const status = error.response.status |
| | const data = error.response.data |
| | |
| | if (isDevelopment) { |
| | console.error(`π¨ [API Error ${status}]`, { |
| | url: error.config.url, |
| | method: error.config.method, |
| | data: data, |
| | headers: error.response.headers |
| | }) |
| | } |
| | } else if (error.request) { |
| | |
| | if (isDevelopment) { |
| | console.error('π¨ [Network Error] No response received:', { |
| | url: error.config?.url, |
| | message: error.message |
| | }) |
| | } |
| | } else { |
| | |
| | if (isDevelopment) { |
| | console.error('π¨ [Request Error]', error.message) |
| | } |
| | } |
| | |
| | return Promise.reject(error) |
| | } |
| | ) |
| |
|
| | export default api |