import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
import { useAuthStore } from '@/stores/authStore'
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:6972'
class ApiClient {
private client: AxiosInstance
constructor() {
this.client = axios.create({
baseURL: API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
})
// Request interceptor to add auth token
this.client.interceptors.request.use(
(config) => {
const token = useAuthStore.getState().token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
// Response interceptor to handle errors
this.client.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
// Token expired or invalid
useAuthStore.getState().logout()
}
return Promise.reject(error)
}
)
}
async get<T>(url: string, config?: AxiosRequestConfig) {
const response = await this.client.get<T>(url, config)
return response.data
}
async post<T>(url: string, data?: any, config?: AxiosRequestConfig) {
const response = await this.client.post<T>(url, data, config)
return response.data
}
async put<T>(url: string, data?: any, config?: AxiosRequestConfig) {
const response = await this.client.put<T>(url, data, config)
return response.data
}
async delete<T>(url: string, config?: AxiosRequestConfig) {
const response = await this.client.delete<T>(url, config)
return response.data
}
async upload<T>(url: string, file: File, config?: AxiosRequestConfig) {
const formData = new FormData()
formData.append('file', file)
const response = await this.client.post<T>(url, formData, {
...config,
headers: {
'Content-Type': 'multipart/form-data',
...config?.headers,
},
})
return response.data
}
}
export const apiClient = new ApiClient()