Skip to content

Commit 5cd5b0f

Browse files
fix: show session expired modal instead of silent redirect to login (#31)
- Trigger showSessionExpiredModal on 401 in axios interceptor - Show modal with "Session Expired" message before redirecting - Suppress error toasts when session expired modal is showing - User must click "Login" to proceed to login page
1 parent a7af325 commit 5cd5b0f

File tree

3 files changed

+32
-20
lines changed

3 files changed

+32
-20
lines changed

frontend/src/auth/RequireAuth.js

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ import { Navigate, Outlet, useNavigate, useLocation } from "react-router-dom";
55
import { useSessionStore } from "../store/session-store";
66

77
const RequireAuth = () => {
8-
const { showSessionExpiredModal, sessionDetails } = useSessionStore();
8+
const {
9+
showSessionExpiredModal,
10+
setShowSessionExpiredModal,
11+
sessionDetails,
12+
} = useSessionStore();
913
const navigate = useNavigate();
1014
const location = useLocation();
1115

1216
const isLoggedIn = !!sessionDetails?.user?.id;
1317

1418
const handleLoginRedirect = useCallback(() => {
19+
setShowSessionExpiredModal(false);
1520
navigate("/login");
16-
}, [navigate]);
21+
}, [navigate, setShowSessionExpiredModal]);
1722

1823
const modalFooter = useMemo(
1924
() => [
@@ -24,31 +29,33 @@ const RequireAuth = () => {
2429
[handleLoginRedirect]
2530
);
2631

27-
if (!isLoggedIn) {
28-
return <Navigate to="/login" />;
29-
}
30-
31-
if (location.pathname === "/") {
32-
return <Navigate to="/project/list" />;
33-
}
34-
35-
return (
36-
<>
37-
<Outlet />
32+
// Show session expired modal instead of silently redirecting
33+
if (!isLoggedIn && showSessionExpiredModal) {
34+
return (
3835
<Modal
3936
title="Session Expired"
40-
open={showSessionExpiredModal}
37+
open
4138
centered
4239
footer={modalFooter}
40+
closable={false}
4341
maskClosable={false}
4442
>
4543
<Typography>
46-
Your session has expired. Please log in again to continue your
47-
transformation with Visitran Ai.
44+
Your session has expired. Please log in again to continue.
4845
</Typography>
4946
</Modal>
50-
</>
51-
);
47+
);
48+
}
49+
50+
if (!isLoggedIn) {
51+
return <Navigate to="/login" />;
52+
}
53+
54+
if (location.pathname === "/") {
55+
return <Navigate to="/project/list" />;
56+
}
57+
58+
return <Outlet />;
5259
};
5360

5461
export { RequireAuth };

frontend/src/service/axios-service.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function useAxiosPrivate() {
3131
if (error?.response?.status === 401) {
3232
localStorage.removeItem("orgid");
3333
localStorage.removeItem("session-storage");
34+
useSessionStore.getState().setShowSessionExpiredModal(true);
3435
setSessionDetails({});
3536
return Promise.resolve({ suppressed: true });
3637
}

frontend/src/service/notification-service.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { notification, Button } from "antd";
1010
import ReactMarkdown from "react-markdown";
1111
import remarkGfm from "remark-gfm";
1212
import "./notification-border.css";
13+
import { useSessionStore } from "../store/session-store";
1314

1415
const NotificationContext = createContext(null);
1516

@@ -50,8 +51,11 @@ function NotificationProvider({ children }) {
5051
let finalDescription = description;
5152

5253
if (type === "error") {
53-
// Skip notification for 401 errors - session expiry modal handles this
54-
if (error?.response?.status === 401) {
54+
// Skip all notifications when session expired modal is showing
55+
if (
56+
error?.response?.status === 401 ||
57+
useSessionStore.getState().showSessionExpiredModal
58+
) {
5559
return;
5660
}
5761

0 commit comments

Comments
 (0)