import axios from 'axios' import toast from 'react-hot-toast' const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1' // Create axios instance export const api = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, }) // Request interceptor to add auth token api.interceptors.request.use( (config) => { const token = localStorage.getItem('accessToken') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }, (error) => { return Promise.reject(error) } ) // Response interceptor to handle token refresh api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true try { const refreshToken = localStorage.getItem('refreshToken') if (refreshToken) { const response = await axios.post(`${API_BASE_URL}/auth/refresh/`, { refresh: refreshToken, }) const { access } = response.data localStorage.setItem('accessToken', access) // Retry original request with new token originalRequest.headers.Authorization = `Bearer ${access}` return api(originalRequest) } else { // No refresh token, clear everything and redirect localStorage.removeItem('accessToken') localStorage.removeItem('refreshToken') // Only redirect if not already on login page if (window.location.pathname !== '/login') { window.location.href = '/login' } } } catch (refreshError) { // Refresh failed, clear tokens but don't redirect if already on login localStorage.removeItem('accessToken') localStorage.removeItem('refreshToken') if (window.location.pathname !== '/login') { window.location.href = '/login' } return Promise.reject(refreshError) } } // Handle other errors if (error.response?.status >= 500) { toast.error('Server error. Please try again later.') } else if (error.response?.status === 403) { toast.error('Access denied. You do not have permission to perform this action.') } else if (error.response?.status === 404) { toast.error('Resource not found.') } else if (error.response?.data?.message) { toast.error(error.response.data.message) } else if (error.message) { toast.error(error.message) } return Promise.reject(error) } ) // API endpoints export const authAPI = { login: (credentials) => api.post('/auth/login/', credentials), register: (userData) => api.post('/auth/register/', userData), logout: () => api.post('/auth/logout/'), refresh: (refreshToken) => api.post('/auth/refresh/', { refresh: refreshToken }), getUser: () => api.get('/auth/user/'), updateUser: (userData) => api.patch('/auth/update/', userData), changePassword: (passwordData) => api.post('/auth/change-password/', passwordData), } export const analyticsAPI = { getTransactions: (params) => api.get('/analytics/transactions/', { params }), getTransactionSummary: (params) => api.get('/analytics/summary/', { params }), getAreaStats: (params) => api.get('/analytics/area-stats-data/', { params }), getPropertyTypeStats: (params) => api.get('/analytics/property-type-stats/', { params }), getTimeSeriesData: (params) => api.get('/analytics/time-series-data/', { params }), getMarketAnalysis: (params) => api.get('/analytics/market-analysis/', { params }), generateForecast: (data) => api.post('/analytics/forecast/', data), } export const reportsAPI = { getReports: (params) => api.get('/reports/', { params }), getReport: (id) => api.get(`/reports/${id}/`), generateTransactionSummary: (data) => api.post('/reports/generate/transaction-summary/', data), generateAreaAnalysis: (data) => api.post('/reports/generate/area-analysis/', data), generateForecast: (data) => api.post('/reports/generate/forecast/', data), downloadReport: (id) => api.get(`/reports/${id}/download/`, { responseType: 'blob' }), } export const usersAPI = { getUsers: (params) => api.get('/auth/list/', { params }), getUser: (id) => api.get(`/auth/${id}/`), updateUser: (id, data) => api.patch(`/auth/${id}/`, data), updateSubscription: (data) => api.post('/auth/update-subscription/', data), toggleApiAccess: (data) => api.post('/auth/toggle-api-access/', data), regenerateApiKey: () => api.post('/auth/regenerate-api-key/'), } export const billingAPI = { getUsageStats: () => api.get('/billing/usage/'), getSubscriptionInfo: () => api.get('/billing/subscription/'), } export const monitoringAPI = { getMetrics: () => api.get('/monitoring/metrics/'), getHealthCheck: () => api.get('/monitoring/health/'), }