session timeout
This commit is contained in:
57
AceJobAgency.client/src/components/SessionTimeout.tsx
Normal file
57
AceJobAgency.client/src/components/SessionTimeout.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import { ToastContainer, toast } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
|
||||
interface SessionTimeoutProps {
|
||||
timeout: number;
|
||||
onLogout: () => void;
|
||||
}
|
||||
|
||||
const SessionTimeout: React.FC<SessionTimeoutProps> = ({
|
||||
timeout,
|
||||
onLogout,
|
||||
}) => {
|
||||
const [lastActivityTime, setLastActivityTime] = useState<number>(Date.now());
|
||||
const [notified, setNotified] = useState<boolean>(false);
|
||||
|
||||
const resetTimer = useCallback(() => {
|
||||
setLastActivityTime(Date.now());
|
||||
setNotified(false);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const events = ["click", "mousemove", "keypress", "scroll", "touchstart"];
|
||||
const eventHandler = () => resetTimer();
|
||||
|
||||
events.forEach((event) => window.addEventListener(event, eventHandler));
|
||||
|
||||
return () => {
|
||||
events.forEach((event) =>
|
||||
window.removeEventListener(event, eventHandler)
|
||||
);
|
||||
};
|
||||
}, [resetTimer]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
const timeElapsed = Date.now() - lastActivityTime;
|
||||
|
||||
if (timeElapsed >= timeout) {
|
||||
onLogout();
|
||||
} else if (timeElapsed >= timeout - 30000 && !notified) {
|
||||
toast.warn("30 more seconds before automatic logout from idling.");
|
||||
setNotified(true);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [lastActivityTime, timeout, onLogout, notified]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ToastContainer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SessionTimeout;
|
||||
@@ -48,7 +48,7 @@ export function login(token: string) {
|
||||
|
||||
export function logout() {
|
||||
clearAccessToken();
|
||||
window.location.reload();
|
||||
window.location.assign("/");
|
||||
}
|
||||
|
||||
export function getAccessToken() {
|
||||
|
||||
@@ -6,6 +6,8 @@ import App from "./App.tsx";
|
||||
import "./index.css";
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import SessionTimeout from "./components/SessionTimeout.tsx";
|
||||
import { getAccessToken, logout } from "./http.ts";
|
||||
|
||||
document.addEventListener("contextmenu", (event) => {
|
||||
event.preventDefault();
|
||||
@@ -18,6 +20,9 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<main>
|
||||
<App />
|
||||
<ToastContainer />
|
||||
{getAccessToken() && (
|
||||
<SessionTimeout timeout={1 * 60 * 1000} onLogout={logout} />
|
||||
)}
|
||||
</main>
|
||||
</HeroUIProvider>
|
||||
</BrowserRouter>
|
||||
|
||||
@@ -16,6 +16,7 @@ export default function EditProfilePage() {
|
||||
const accessToken = getAccessToken();
|
||||
if (!accessToken) {
|
||||
navigate(-1);
|
||||
return;
|
||||
}
|
||||
http.get("/User/profile").then((response) => {
|
||||
if (response.status !== 200) {
|
||||
|
||||
Reference in New Issue
Block a user