feat(frontend): enhance 401 handling to clear tokens and redirect
- Update fetch interceptor to special-case 401 responses - Clear invalid tokens from localStorage on 401 (token, refreshToken, user) - Distinguish between page navigation and API calls: - Page navigation: throw error to prevent further processing - API calls: show toast error with session expired message - Suppress network error toast for redirect errors - Compile TypeScript to JavaScript This ensures frontend properly handles expired sessions by clearing stale credentials and showing appropriate error messages.
This commit is contained in:
@@ -161,6 +161,31 @@ const setupFetchInterceptor = (): void => {
|
|||||||
try {
|
try {
|
||||||
const response = await originalFetch(...args);
|
const response = await originalFetch(...args);
|
||||||
|
|
||||||
|
// Special handling for 401 Unauthorized
|
||||||
|
if (response.status === 401) {
|
||||||
|
// Clear invalid tokens from localStorage
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
localStorage.removeItem('refreshToken');
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
|
||||||
|
// Check if this was a page navigation (not API call)
|
||||||
|
const url = args[0] as string;
|
||||||
|
|
||||||
|
// Don't show toast for page navigations - will be handled by redirect
|
||||||
|
if (!url.startsWith('/api/')) {
|
||||||
|
// Direct navigation to protected page will be caught by middleware
|
||||||
|
// Just throw to prevent further processing
|
||||||
|
throw new Error('Session expired');
|
||||||
|
}
|
||||||
|
|
||||||
|
// API call - show toast error
|
||||||
|
const errorMessage = await parseFetchError(response);
|
||||||
|
showToast(errorMessage, 'error');
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle other errors
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorMessage = await parseFetchError(response);
|
const errorMessage = await parseFetchError(response);
|
||||||
showToast(errorMessage, 'error');
|
showToast(errorMessage, 'error');
|
||||||
@@ -168,7 +193,10 @@ const setupFetchInterceptor = (): void => {
|
|||||||
|
|
||||||
return response;
|
return response;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// Don't show toast for redirect errors
|
||||||
|
if ((error as Error).message !== 'Session expired') {
|
||||||
showToast('Network error: Unable to connect to server', 'error');
|
showToast('Network error: Unable to connect to server', 'error');
|
||||||
|
}
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user