mitlist/fe/src/services/api.ts
mohamad 448a0705d2
All checks were successful
Deploy to Production, build images and push to Gitea Registry / build_and_push (pull_request) Successful in 1m30s
feat: Implement comprehensive roadmap for feature updates and enhancements
This commit introduces a detailed roadmap for implementing various features, focusing on backend and frontend improvements. Key additions include:

- New database schema designs for financial audit logging, archiving lists, and categorizing items.
- Backend logic for financial audit logging, archiving functionality, and chore subtasks.
- Frontend UI updates for archiving lists, managing categories, and enhancing the chore interface.
- Introduction of a guest user flow and integration of Redis for caching to improve performance.

These changes aim to enhance the application's functionality, user experience, and maintainability.
2025-06-10 08:16:55 +02:00

113 lines
3.8 KiB
TypeScript

import axios from 'axios'
import { API_BASE_URL, API_VERSION, 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/${API_VERSION}`,
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),
}
// Store for tracking refresh promise to prevent concurrent refresh attempts
let refreshPromise: Promise<any> | null = null
// 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
// If we're already refreshing, wait for that to complete
if (refreshPromise) {
try {
await refreshPromise
// After refresh completes, retry with new token
const newToken = localStorage.getItem('token')
if (newToken) {
originalRequest.headers.Authorization = `Bearer ${newToken}`
return api(originalRequest)
}
} catch (refreshError) {
// Refresh failed, redirect to login
return Promise.reject(error)
}
}
const refreshTokenValue = authStore.refreshToken
if (!refreshTokenValue) {
authStore.clearTokens()
await router.push('/auth/login')
return Promise.reject(error)
}
// Set refreshing state and create refresh promise
authStore.isRefreshing = true
refreshPromise = api.post(API_ENDPOINTS.AUTH.REFRESH, { refresh_token: refreshTokenValue }, {
headers: {
'Content-Type': 'application/json',
}
})
try {
const response = await refreshPromise
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) {
console.error('Token refresh failed:', refreshError)
authStore.clearTokens()
await router.push('/auth/login')
return Promise.reject(refreshError)
} finally {
authStore.isRefreshing = false
refreshPromise = null
}
}
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 }