This commit is contained in:
hamid zarghami
2025-05-27 09:00:58 +03:30
parent 495e59bec4
commit aecaf193ce
9 changed files with 176 additions and 73 deletions
+1 -61
View File
@@ -5,11 +5,8 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom'
import 'swiper/swiper-bundle.css';
import FaJson from './langs/fa.json'
import AuthRouter from './router/Auth';
import { QueryCache, QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { IApiErrorRepsonse } from './types/error.types';
import { refreshToken } from './pages/auth/service/AuthService';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import ToastContainer from './components/Toast';
import { getRefreshToken, removeRefreshToken, removeToken, setRefreshToken, setToken } from './config/func';
i18next.init({
interpolation: { escapeValue: false },
@@ -29,63 +26,6 @@ declare global {
function App() {
const queryClient = new QueryClient({
queryCache: new QueryCache({
onError: async (error: IApiErrorRepsonse, query) => {
if (error?.response?.status === 401) {
try {
// Use a flag to track if refresh is in progress
if (window.isRefreshingToken) {
// Wait for the refresh to complete
await new Promise(resolve => {
const checkComplete = setInterval(() => {
if (!window.isRefreshingToken) {
clearInterval(checkComplete);
resolve(true);
}
}, 100);
});
return;
}
// Set the flag to indicate refresh is in progress
window.isRefreshingToken = true;
try {
const refreshTokenValue = await getRefreshToken();
const { data } = await refreshToken({ refreshToken: refreshTokenValue || '' });
if (data?.accessToken?.token) {
// Save the new token
await setToken(data?.accessToken?.token);
// If refresh token also returned, update it
if (data.refreshToken?.token) {
await setRefreshToken(data.refreshToken?.token);
}
// Retry the failed request, even if it was muted
if (query) {
queryClient.invalidateQueries({ queryKey: query.queryKey });
} else {
queryClient.invalidateQueries();
}
return;
} else {
throw new Error('Invalid token response');
}
} finally {
window.isRefreshingToken = false;
}
} catch (refreshError: unknown) {
console.error('Token refresh failed:', refreshError);
// Clear tokens and redirect to login
await removeToken();
await removeRefreshToken();
// window.location.href = '/auth/login';
}
}
}
}),
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
+11 -1
View File
@@ -38,11 +38,19 @@ axiosInstance.interceptors.response.use(
try {
const refreshTokenValue = await getRefreshToken();
if (!refreshTokenValue) {
removeRefreshToken();
removeToken();
window.location.href = buildPath("auth/login");
return;
}
const { data } = await refreshToken({
refreshToken: refreshTokenValue || "",
refreshToken: refreshTokenValue,
});
alert("1");
if (data?.accessToken?.token) {
alert("1");
await setToken(data?.accessToken?.token);
if (data.refreshToken?.token) {
await setRefreshToken(data.refreshToken?.token);
@@ -50,6 +58,8 @@ axiosInstance.interceptors.response.use(
originalRequest.headers.Authorization = `Bearer ${data.accessToken.token}`;
return axiosInstance(originalRequest);
} else {
alert("2");
}
} catch (refreshError) {
console.error("Token refresh failed:", refreshError);
+22 -5
View File
@@ -36,26 +36,43 @@ export const getToken = async () => {
return Cookie.get(import.meta.env.VITE_TOKEN_NAME);
};
export const getRefreshToken = () => {
export const getRefreshToken = async () => {
return Cookie.get(import.meta.env.VITE_REFRESH_TOKEN_NAME);
};
const isProduction = import.meta.env.MODE === "production";
const domain = window.location.hostname;
export const setToken = (token: string) => {
Cookie.set(import.meta.env.VITE_TOKEN_NAME, token, { domain });
Cookie.set(import.meta.env.VITE_TOKEN_NAME, token, {
domain,
secure: isProduction,
sameSite: "Lax",
});
};
export const setRefreshToken = (refreshToken: string) => {
Cookie.set(import.meta.env.VITE_REFRESH_TOKEN_NAME, refreshToken, { domain });
Cookie.set(import.meta.env.VITE_REFRESH_TOKEN_NAME, refreshToken, {
domain,
secure: isProduction,
sameSite: "Lax",
});
};
export const removeToken = () => {
Cookie.remove(import.meta.env.VITE_TOKEN_NAME, { domain, path: "/" });
Cookie.remove(import.meta.env.VITE_TOKEN_NAME, {
domain,
secure: isProduction,
sameSite: "Lax",
});
};
export const removeRefreshToken = () => {
Cookie.remove(import.meta.env.VITE_REFRESH_TOKEN_NAME, { domain, path: "/" });
Cookie.remove(import.meta.env.VITE_REFRESH_TOKEN_NAME, {
domain,
secure: isProduction,
sameSite: "Lax",
});
};
export const getRedirectUrl = () => {
+1 -1
View File
@@ -60,7 +60,7 @@ const Username: FC<Props> = (props: Props) => {
setStatus('')
},
onError(error: ErrorType) {
toast(error?.response?.data?.message || 'خطا در تغییر نام کاربری', 'error')
toast(error?.response?.data?.error?.message[0] || 'خطا در تغییر نام کاربری', 'error')
},
})
}
+2 -2
View File
@@ -38,7 +38,7 @@ const ReceiptsDetail: FC = () => {
getInvoce.refetch()
},
onError: (error: ErrorType) => {
toast(error?.response?.data?.message || 'خطا در پرداخت فاکتور', 'error')
toast(error?.response?.data?.error?.message[0], 'error')
}
})
}
@@ -50,7 +50,7 @@ const ReceiptsDetail: FC = () => {
getInvoce.refetch()
},
onError: (error: ErrorType) => {
toast(error?.response?.data?.message || 'خطا در پرداخت فاکتور', 'error')
toast(error?.response?.data?.error?.message[0], 'error')
}
})
}
@@ -36,7 +36,7 @@ const ApproveInvoice: FC<Props> = ({ id, refetch, status }) => {
setShowModal(false)
},
onError: (error: ErrorType) => {
toast(error?.response?.data?.message || 'خطا در تایید فاکتور', 'error')
toast(error?.response?.data?.error?.message[0], 'error')
}
})
}
@@ -52,7 +52,7 @@ const ApproveInvoice: FC<Props> = ({ id, refetch, status }) => {
reset()
},
onError: (error: ErrorType) => {
toast(error?.response?.data?.message || 'خطا در تایید فاکتور', 'error')
toast(error?.response?.data?.error?.message[0] || 'خطا در تایید فاکتور', 'error')
}
})
}
+1 -1
View File
@@ -116,7 +116,7 @@ const Request: FC = () => {
navigate(buildPath(Pages.dashboard, slug))
},
onError: (error: ErrorType) => {
toast(error?.response?.data?.message || 'خطا در ارسال درخواست', 'error')
toast(error?.response?.data?.error?.message[0], 'error')
}
})
}