Initial commit: admin dashboard for GameNo.
Vue 3 + Vite dashboard with PrimeVue, i18n, and API integration for institution management.
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
// /src/api/axiosInstance.js
|
||||
import axios from 'axios';
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000/api';
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: API_BASE_URL,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
timeout: 15000
|
||||
});
|
||||
|
||||
// Request interceptor: attach token
|
||||
axiosInstance.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = localStorage.getItem('accessToken') || Cookies.get('accessToken');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// Ask backend for Persian (or stored) localized error messages
|
||||
const lang = localStorage.getItem('lang') || 'fa';
|
||||
config.headers['Accept-Language'] = lang;
|
||||
if (!config.params) config.params = {};
|
||||
if (config.params.lang == null) {
|
||||
config.params.lang = lang;
|
||||
}
|
||||
|
||||
return config;
|
||||
},
|
||||
(error) => Promise.reject(error)
|
||||
);
|
||||
|
||||
// Response interceptor: auto-refresh token on 401
|
||||
let isRefreshing = false;
|
||||
let failedQueue = [];
|
||||
|
||||
const processQueue = (error, token = null) => {
|
||||
failedQueue.forEach(prom => {
|
||||
if (error) {
|
||||
prom.reject(error);
|
||||
} else {
|
||||
prom.resolve(token);
|
||||
}
|
||||
});
|
||||
failedQueue = [];
|
||||
};
|
||||
|
||||
axiosInstance.interceptors.response.use(
|
||||
(response) => response.data,
|
||||
async (error) => {
|
||||
const originalRequest = error.config;
|
||||
|
||||
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||
if (originalRequest.url.includes('/auth/login') || originalRequest.url.includes('/auth/refresh')) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
if (isRefreshing) {
|
||||
return new Promise((resolve, reject) => {
|
||||
failedQueue.push({ resolve, reject });
|
||||
})
|
||||
.then((token) => {
|
||||
originalRequest.headers.Authorization = `Bearer ${token}`;
|
||||
return axiosInstance(originalRequest);
|
||||
})
|
||||
.catch((err) => Promise.reject(err));
|
||||
}
|
||||
|
||||
originalRequest._retry = true;
|
||||
isRefreshing = true;
|
||||
|
||||
const refreshToken = localStorage.getItem('refreshToken') || Cookies.get('refreshToken');
|
||||
|
||||
if (!refreshToken) {
|
||||
isRefreshing = false;
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('refreshToken');
|
||||
window.location.href = '/login';
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
try {
|
||||
const refreshResponse = await axios.post(`${API_BASE_URL}/auth/refresh`, { refreshToken });
|
||||
const data = refreshResponse.data?.data || refreshResponse.data;
|
||||
const newAccessToken = data.accessToken;
|
||||
const newRefreshToken = data.refreshToken;
|
||||
|
||||
localStorage.setItem('accessToken', newAccessToken);
|
||||
Cookies.set('accessToken', newAccessToken);
|
||||
if (newRefreshToken) {
|
||||
localStorage.setItem('refreshToken', newRefreshToken);
|
||||
Cookies.set('refreshToken', newRefreshToken);
|
||||
}
|
||||
|
||||
axiosInstance.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`;
|
||||
originalRequest.headers.Authorization = `Bearer ${newAccessToken}`;
|
||||
|
||||
processQueue(null, newAccessToken);
|
||||
return axiosInstance(originalRequest);
|
||||
} catch (refreshErr) {
|
||||
processQueue(refreshErr, null);
|
||||
localStorage.removeItem('accessToken');
|
||||
localStorage.removeItem('refreshToken');
|
||||
Cookies.remove('accessToken');
|
||||
Cookies.remove('refreshToken');
|
||||
window.location.href = '/login';
|
||||
return Promise.reject(refreshErr);
|
||||
} finally {
|
||||
isRefreshing = false;
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default axiosInstance;
|
||||
Reference in New Issue
Block a user