mitlist/fe/src/services/api.ts

87 lines
3.0 KiB
TypeScript

import axios from 'axios'
import { API_BASE_URL, API_ENDPOINTS } from '@/config/api-config' // api-config.ts can be moved to src/config/
import router from '@/router' // Import the router instance
import { useAuthStore } from '@/stores/auth' // Import the auth store
import type { SettlementActivityCreate, SettlementActivityPublic } from '@/types/expense' // Import the types for the payload and response
import { stringify } from 'qs';
// Create axios instance
const api = axios.create({
baseURL: API_BASE_URL, // API_BASE_URL should come from env or config
headers: {
'Content-Type': 'application/json',
},
withCredentials: true, // Enable sending cookies and authentication headers
paramsSerializer: {
serialize: (params) => stringify(params, { arrayFormat: 'repeat' }),
},
})
// Create apiClient with helper methods
const apiClient = {
get: (endpoint: string, config = {}) => api.get(endpoint, config),
post: (endpoint: string, data = {}, config = {}) => api.post(endpoint, data, config),
put: (endpoint: string, data = {}, config = {}) => api.put(endpoint, data, config),
patch: (endpoint: string, data = {}, config = {}) => api.patch(endpoint, data, config),
delete: (endpoint: string, config = {}) => api.delete(endpoint, config),
}
// Request interceptor
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => {
console.error('Request error:', error)
return Promise.reject(error)
},
)
// Response interceptor
api.interceptors.response.use(
(response) => response,
async (error) => {
const originalRequest = error.config
const authStore = useAuthStore()
if (error.response?.status === 401 && !originalRequest._retry) {
originalRequest._retry = true
try {
const refreshTokenValue = authStore.refreshToken
if (!refreshTokenValue) {
authStore.clearTokens()
await router.push('/auth/login')
return Promise.reject(error)
}
// Send refresh token in request body as expected by backend
const response = await api.post(API_ENDPOINTS.AUTH.REFRESH, { refresh_token: refreshTokenValue }, {
headers: {
'Content-Type': 'application/json',
}
})
const { access_token: newAccessToken, refresh_token: newRefreshToken } = response.data
authStore.setTokens({ access_token: newAccessToken, refresh_token: newRefreshToken })
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`
return api(originalRequest)
} catch (refreshError) {
authStore.clearTokens()
await router.push('/auth/login')
return Promise.reject(refreshError)
}
}
return Promise.reject(error)
},
)
// Export the original axios too if some parts of your app used it directly
const globalAxios = axios
export { api, globalAxios, API_ENDPOINTS, apiClient }