/* eslint-disable react-refresh/only-export-components */ import { FC, useState, useEffect, useCallback, createContext, useContext, Dispatch, SetStateAction, } from "react"; import { LayoutSplashScreen } from "../../../../_metronic/layout/core"; import { AuthModel, UserModel } from "./_models"; import * as authHelper from "./AuthHelpers"; import { getUserByToken } from "./_requests"; import { WithChildren } from "../../../../_metronic/helpers"; type AuthContextProps = { auth: AuthModel | undefined; saveAuth: (auth: AuthModel | undefined) => void; currentUser: UserModel | undefined; setCurrentUser: Dispatch>; logout: () => void; }; const initAuthContextPropsState = { auth: authHelper.getAuth(), saveAuth: () => {}, currentUser: undefined, setCurrentUser: () => {}, logout: () => {}, }; const AuthContext = createContext(initAuthContextPropsState); const useAuth = () => { return useContext(AuthContext); }; const AuthProvider: FC = ({ children }) => { const [auth, setAuth] = useState(authHelper.getAuth()); const [currentUser, setCurrentUser] = useState(); const [lastActivityTime, setLastActivityTime] = useState(Date.now()); let checkExpirationInMinutes: number = Number( import.meta.env.VITE_APP_SESSION_EXPIRE_MINUTES ); let expirationChecker: number = Number( import.meta.env.VITE_APP_SESSION_EXPIRE_CHECKER ); const saveAuth = (auth: AuthModel | undefined) => { setAuth(auth); if (auth) { authHelper.setAuth(auth); } else { authHelper.removeAuth(); } }; const logout = () => { saveAuth(undefined); setCurrentUser(undefined); }; useEffect((): any => { const expireSession = () => { localStorage.removeItem("wrenchboard-agent-auth-details"); logout(); }; const checkInactivity = setInterval(() => { let currentTime: number = Date.now(); let checkLastActivityTime: number = lastActivityTime; if (currentTime - checkLastActivityTime > checkExpirationInMinutes) { expireSession(); } }, expirationChecker); // cleaning up listeners return () => { clearInterval(checkInactivity); }; }, [lastActivityTime]); // Reset last activity time on user input const resetTime = useCallback(() => { setLastActivityTime(Date.now()); }, []); useEffect(() => { window.addEventListener("mousemove", resetTime); window.addEventListener("keydown", resetTime); return () => { window.removeEventListener("mousemove", resetTime); window.removeEventListener("keydown", resetTime); }; }, [resetTime]); return ( {children} ); }; const AuthInit: FC = ({ children }) => { const { auth, currentUser, logout, setCurrentUser } = useAuth(); const [showSplashScreen, setShowSplashScreen] = useState(true); // We should request user by authToken (IN OUR EXAMPLE IT'S API_TOKEN) before rendering the application useEffect(() => { const requestUser = async (apiToken: string) => { try { if (!currentUser) { const { data } = await getUserByToken(apiToken); if (data) { setCurrentUser(data); } } } catch (error) { console.error(error); if (currentUser) { logout(); } } finally { setShowSplashScreen(false); } }; if (auth && auth.api_token) { requestUser(auth.api_token); } else { logout(); setShowSplashScreen(false); } // eslint-disable-next-line }, []); return showSplashScreen ? : <>{children}; }; export { AuthProvider, AuthInit, useAuth };