Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ddce27c65a | |||
| 87d1615b73 | |||
| 9ef2084956 | |||
| 15e6ed3264 |
@@ -18,7 +18,7 @@ REACT_APP_USERS_ENDPOINT="https://apigate.lotus.g1.wrenchboard.com/svs/user"
|
||||
#"https://devapi.mermsemr.com/en/desktop/api/v2/myfituser"
|
||||
|
||||
REACT_APP_SESSION_EXPIRE_MINUTES=300000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=60000
|
||||
REACT_APP_SESSION_EXPIRE_CHECKER=300000
|
||||
|
||||
REACT_APP_LOGIN_ERROR_TIMEOUT=7000
|
||||
REACT_APP_SIGNUP_ERROR_TIMEOUT=7000
|
||||
|
||||
@@ -9,7 +9,13 @@ import usersService from "../../../services/UsersService";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {updateUserDetails} from '../../../store/UserDetails'
|
||||
|
||||
export default function Login() {
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const [checked, setValue] = useState(false);
|
||||
const [loginLoading, setLoginLoading] = useState(false);
|
||||
|
||||
@@ -51,21 +57,13 @@ export default function Login() {
|
||||
//debugger;
|
||||
// if (email === "support@mermsemr.com") {
|
||||
if (loginResult.data.status > 0 && loginResult.data.internal_return == 100 && loginResult.data.session != '') { // just for a start
|
||||
localStorage.setItem("email", `${loginResult.data.email}`);
|
||||
localStorage.setItem("member_id", `${loginResult.data.member_id}`);
|
||||
localStorage.setItem("uid", `${loginResult.data.uid}`);
|
||||
localStorage.setItem("session_token", `${loginResult.data.session}`);
|
||||
localStorage.setItem("added", `${loginResult.data.added}`);
|
||||
localStorage.setItem("city", `${loginResult.data.city}`);
|
||||
localStorage.setItem("country", `${loginResult.data.country}`);
|
||||
localStorage.setItem("firstname", `${loginResult.data.firstname}`);
|
||||
localStorage.setItem("last_login", `${loginResult.data.last_login}`);
|
||||
localStorage.setItem("lastname", `${loginResult.data.lastname}`);
|
||||
localStorage.setItem("state", `${loginResult.data.state}`);
|
||||
localStorage.setItem("zip_code", `${loginResult.data.zip_code}`);
|
||||
localStorage.setItem("session", `${loginResult.data.session}`);
|
||||
setLoginLoading(true);
|
||||
// userApi.getUserReminders(); //testing
|
||||
dispatch(updateUserDetails(loginResult.data))
|
||||
setTimeout(() => {
|
||||
navigate("/", { replace: true });
|
||||
setLoginLoading(false);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useLayoutEffect, useCallback } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useLocation, Link, useNavigate } from "react-router-dom";
|
||||
import AuthLayout from "../AuthLayout";
|
||||
import InputCom from "../../Helpers/Inputs/InputCom";
|
||||
@@ -28,34 +28,6 @@ export default function VerifyLink() {
|
||||
setPassword(e.target.value);
|
||||
};
|
||||
|
||||
// for verifying the incoming verification link and render the correct component
|
||||
const verifyEmail = useCallback(async (code) => {
|
||||
try {
|
||||
const verifyRes = await userApi.verifyEmail(code);
|
||||
if (verifyRes.status === 200) {
|
||||
let { data } = verifyRes;
|
||||
|
||||
if (
|
||||
data &&
|
||||
data.internal_return >= 0 &&
|
||||
data.status_text === "Link Verfied"
|
||||
) {
|
||||
setPageLoader(false);
|
||||
} else {
|
||||
setPageLoader(false);
|
||||
setLinkSuccess(false);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setPageLoader(false);
|
||||
setLinkSuccess(false);
|
||||
throw new Error(error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// delay verify requests by 10000ms
|
||||
const debouncedEmail = debounce(verifyEmail, 1000);
|
||||
|
||||
// if verification is okay. set a complete signup form
|
||||
const completeSignup = async () => {
|
||||
if (email === "" && password === "") {
|
||||
@@ -85,14 +57,6 @@ export default function VerifyLink() {
|
||||
localStorage.setItem("email", `${data?.email}`);
|
||||
localStorage.setItem("member_id", `${data?.member_id}`);
|
||||
localStorage.setItem("session_token", `${data?.session}`);
|
||||
localStorage.setItem("added", `${data?.added}`);
|
||||
localStorage.setItem("city", `${data?.city}`);
|
||||
localStorage.setItem("country", `${data?.country}`);
|
||||
localStorage.setItem("firstname", `${data?.firstname}`);
|
||||
localStorage.setItem("last_login", `${data?.last_login}`);
|
||||
localStorage.setItem("lastname", `${data?.lastname}`);
|
||||
localStorage.setItem("state", `${data?.state}`);
|
||||
localStorage.setItem("zip_code", `${data?.zip_code}`);
|
||||
localStorage.setItem("session", `${data?.session}`);
|
||||
|
||||
navigate("/", { replace: true });
|
||||
@@ -118,9 +82,37 @@ export default function VerifyLink() {
|
||||
}
|
||||
};
|
||||
|
||||
useLayoutEffect(() => {
|
||||
// for verifying the incoming verification link and render the correct component
|
||||
const verifyEmail = useCallback(async (code) => {
|
||||
try {
|
||||
const verifyRes = await userApi.verifyEmail(code);
|
||||
if (verifyRes.status === 200) {
|
||||
let { data } = verifyRes;
|
||||
|
||||
if (
|
||||
data &&
|
||||
data.internal_return >= 0 &&
|
||||
data.status_text === "Link Verfied"
|
||||
) {
|
||||
setPageLoader(false);
|
||||
} else {
|
||||
setPageLoader(false);
|
||||
setLinkSuccess(false);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
setPageLoader(false);
|
||||
setLinkSuccess(false);
|
||||
throw new Error(error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// delay verify requests by 10000ms
|
||||
const debouncedEmail = debounce(verifyEmail, 1000);
|
||||
|
||||
useEffect(() => {
|
||||
debouncedEmail(token);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -9,6 +9,7 @@ import slider3 from "../../assets/images/slider-3.jpg";
|
||||
import CountDown from "../Helpers/CountDown";
|
||||
import SliderCom from "../Helpers/SliderCom";
|
||||
import HomeSliders from "./HomeSliders";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function Hero({ className }) {
|
||||
const settings = {
|
||||
@@ -20,6 +21,8 @@ export default function Hero({ className }) {
|
||||
};
|
||||
const sildeData =null;
|
||||
const [addFavorite, setValue] = useState(false);
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails)
|
||||
const favoriteHandler = () => {
|
||||
if (!addFavorite) {
|
||||
setValue(true);
|
||||
@@ -29,6 +32,11 @@ export default function Hero({ className }) {
|
||||
toast.warn("Remove to Favorite List");
|
||||
}
|
||||
};
|
||||
|
||||
let loginDate = userDetails?.last_login.split(' ')[0]
|
||||
let {firstname, lastname, email, profile_pic} = userDetails
|
||||
let userEmail = email.split('@')[0]
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`w-full lg:h-[444px] h-full lg:flex lg:p-8 p-4 justify-between items-center lg:space-x-28 rounded-2xl overflow-hidden ${
|
||||
@@ -47,19 +55,19 @@ export default function Hero({ className }) {
|
||||
Welcome
|
||||
</h1>
|
||||
<span className="text-[18px] font-thin tracking-wide text-white">
|
||||
Last Login : 10-10-2026
|
||||
Last Login : {loginDate}
|
||||
</span>
|
||||
</div>
|
||||
{/* user */}
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="w-14 h-14 flex justify-center items-center rounded-full overflow-hidden">
|
||||
<img src={heroUser} alt="" />
|
||||
<img src={profile_pic != '' ? profile_pic : heroUser} alt="" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xl tracking-wide font-bold antise text-white">
|
||||
Brokln Simons
|
||||
{`${firstname} ${lastname}`}
|
||||
</p>
|
||||
<p className="text-sm tracking-wide text-white">@broklinslam_75</p>
|
||||
<p className="text-sm tracking-wide text-white">@{userEmail}</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* countdown */}
|
||||
|
||||
@@ -10,6 +10,8 @@ import UpdateTable from "./UpdateTable";
|
||||
import HomeTaskDisplay from "./HomeTaskDisplay";
|
||||
import UsersService from "../../services/UsersService";
|
||||
import usersService from "../../services/UsersService";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
|
||||
export default function Home() {
|
||||
const trending = datas.datas;
|
||||
@@ -18,10 +20,12 @@ export default function Home() {
|
||||
const userApi = new usersService();
|
||||
const homeData = userApi.getHomeDate();
|
||||
|
||||
const {userDetails} = useSelector((state) => state?.userDetails)
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="home-page-wrapper">
|
||||
<Hero className="mb-10" />
|
||||
<Hero className="mb-10" data={userDetails} />
|
||||
{/* <CreateNft />
|
||||
<TrendingSection trending={trending} className="mb-10" />*/}
|
||||
<HomeTaskDisplay
|
||||
|
||||
@@ -15,6 +15,7 @@ import usersService from "../../services/UsersService";
|
||||
|
||||
import siteLogo from '../../assets/images/wrenchboard.png'
|
||||
import Flag from '../../assets/images/united-states.svg'
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
|
||||
export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
@@ -24,6 +25,8 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
const [moneyPopup, setPopup] = useToggle(false);
|
||||
const [toggleNotification, setToggleNotification] = useToggle(false)
|
||||
const darkMode = useContext(DarkModeContext);
|
||||
const {userDetails} = useSelector((state) => state?.userDetails)
|
||||
|
||||
|
||||
const [myWalletList, setMyWalletList] = useState([]);
|
||||
const api = new usersService();
|
||||
@@ -87,6 +90,11 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
const setNotification = ()=> {
|
||||
setToggleNotification.toggle()
|
||||
}
|
||||
|
||||
// User Profile
|
||||
let {firstname, lastname, email, profile_pic} = userDetails
|
||||
let userEmail = email.split('@')[0]
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="header-wrapper backdrop-blur-sm bg-[#efedfe5e]/60 dark:bg-transparent w-full h-full flex items-center xl:px-0 md:px-10 px-5">
|
||||
@@ -463,17 +471,17 @@ export default function Header({ logoutModalHandler, sidebarHandler }) {
|
||||
{/* profile-image */}
|
||||
<div className="lg:w-[62px] lg:h-[62px] w-[50px] h-[50px] rounded-full overflow-hidden">
|
||||
<img
|
||||
src={profileImg}
|
||||
src={profile_pic != '' ? profile_pic : profileImg}
|
||||
alt="profile"
|
||||
className="w-full h-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="lg:block hidden">
|
||||
<h1 className="text-xl font-bold text-dark-gray dark:text-white">
|
||||
Brokln Simons
|
||||
{`${firstname} ${lastname}`}
|
||||
</h1>
|
||||
<p className="text-sm text-thin-light-gray">
|
||||
@broklinslam_75
|
||||
@{userEmail}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,9 +22,9 @@ export default function Layout({ children }) {
|
||||
const logOut = () => {
|
||||
localStorage.removeItem("email");
|
||||
localStorage.clear();
|
||||
toast.success("Come Back Soon", {
|
||||
icon: `🙂`,
|
||||
});
|
||||
// toast.success("Come Back Soon", {
|
||||
// icon: `🙂`,
|
||||
// });
|
||||
|
||||
navigate("/login", { replace: true });
|
||||
};
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react'
|
||||
|
||||
function LoadingSpinner({size, color}) {
|
||||
function LoadingSpinner({size, color, height}) {
|
||||
return (
|
||||
<div className='flex items-center justify-center'>
|
||||
<div className={`flex items-center justify-center ${height ? height : ''}`}>
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" className={`w-${size} h-${size} text-gray-200 animate-spin dark:text-gray-600 fill-${color}`} viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z" fill="currentColor"/>
|
||||
|
||||
@@ -1,38 +1,31 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||
import usersService from '../services/UsersService'
|
||||
import LoadingSpinner from '../components/Spinners/LoadingSpinner'
|
||||
import WrenchBoard from "../assets/images/wrenchboard.png"
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {updateUserDetails} from '../store/UserDetails'
|
||||
|
||||
|
||||
const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
const apiCall = new usersService()
|
||||
|
||||
const dispatch = useDispatch()
|
||||
|
||||
const [lastActivityTime, setLastActivityTime] = useState(Date.now());
|
||||
const isLogin = localStorage.getItem("email");
|
||||
let [isLogin, setIsLogin] = useState({loading: true, status: false})
|
||||
|
||||
const navigate = useNavigate();
|
||||
const { pathname } = useLocation();
|
||||
|
||||
//Removing Data stored at localStorage after session expires
|
||||
const expireSession = () => {
|
||||
localStorage.removeItem("email");
|
||||
localStorage.removeItem('session_token');
|
||||
localStorage.removeItem('firstname');
|
||||
localStorage.removeItem('member_id');
|
||||
localStorage.removeItem('lastname');
|
||||
localStorage.removeItem('state');
|
||||
localStorage.removeItem('last_login');
|
||||
localStorage.removeItem('uid');
|
||||
localStorage.removeItem('session');
|
||||
localStorage.removeItem('city');
|
||||
localStorage.removeItem('country');
|
||||
localStorage.removeItem('loglevel');
|
||||
localStorage.removeItem('zip_code');
|
||||
localStorage.removeItem('added');
|
||||
navigate("/login", { replace: true }); // redirects user to login page after session expires
|
||||
};
|
||||
|
||||
const checkInactivity = setInterval(() => {
|
||||
if (Date.now() - lastActivityTime > process.env.REACT_APP_SESSION_EXPIRE_MINUTES) {
|
||||
expireSession()
|
||||
}
|
||||
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER) // Checks for inactivity every minute
|
||||
|
||||
// Reset last activity time on user input
|
||||
const resetTime = () => {
|
||||
setLastActivityTime(Date.now());
|
||||
@@ -40,19 +33,52 @@ const AuthRoute = ({ redirectPath = "/login", children }) => {
|
||||
window.addEventListener('mousemove', resetTime)
|
||||
window.addEventListener('keydown', resetTime)
|
||||
|
||||
const loadProfile = ()=>{ // function to load user profile
|
||||
apiCall.loadProfile().then((res)=>{
|
||||
if(res.data.internal_return < 0){
|
||||
setIsLogin({loading: false, status: false})
|
||||
return
|
||||
}
|
||||
dispatch(updateUserDetails(res.data))
|
||||
setIsLogin({loading: false, status: true})
|
||||
}).catch(error =>{
|
||||
setIsLogin({loading: false, status: false})
|
||||
})
|
||||
}
|
||||
const getProfile = useCallback(()=>{
|
||||
loadProfile() // API CALL TO GET USER PROFILE
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
getProfile()
|
||||
|
||||
const checkInactivity = setInterval(() => {
|
||||
if (Date.now() - lastActivityTime > process.env.REACT_APP_SESSION_EXPIRE_MINUTES) {
|
||||
expireSession()
|
||||
}
|
||||
}, process.env.REACT_APP_SESSION_EXPIRE_CHECKER) // Checks for inactivity every minute
|
||||
|
||||
// cleaning up listeners
|
||||
return () => {
|
||||
clearInterval(checkInactivity)
|
||||
window.removeEventListener('mousemove', resetTime)
|
||||
window.removeEventListener('keydown', resetTime)
|
||||
}
|
||||
}, [pathname, lastActivityTime])
|
||||
}, [lastActivityTime])
|
||||
|
||||
if (!isLogin) {
|
||||
return <Navigate to={redirectPath} replace />;
|
||||
}
|
||||
return children || <Outlet />;
|
||||
return (
|
||||
isLogin.loading ?
|
||||
<LoadingSpinner size='32' color='sky-blue' height='h-screen' />
|
||||
// Stills needs fixing
|
||||
// <div className="h-screen m-auto">
|
||||
// <img src={WrenchBoard} alt="wrenchboard" className="h-10" />
|
||||
// </div>
|
||||
:
|
||||
!isLogin.status ?
|
||||
<Navigate to={redirectPath} replace />
|
||||
:
|
||||
(children || <Outlet />)
|
||||
)
|
||||
};
|
||||
|
||||
export default AuthRoute;
|
||||
export default AuthRoute;
|
||||
@@ -0,0 +1,20 @@
|
||||
import { createSlice } from "@reduxjs/toolkit";
|
||||
|
||||
const initialState = {
|
||||
userDetails: {}
|
||||
};
|
||||
|
||||
export const userSlice = createSlice({
|
||||
name: "userDetails",
|
||||
initialState,
|
||||
reducers: {
|
||||
updateUserDetails: (state,payload) => {
|
||||
state.userDetails = {...payload.payload}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Action creators are generated for each case reducer function
|
||||
export const { updateUserDetails } = userSlice.actions;
|
||||
|
||||
export default userSlice.reducer;
|
||||
+4
-1
@@ -1,8 +1,11 @@
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import drawerReducer from "./drawer";
|
||||
|
||||
import userDetailReducer from "./UserDetails";
|
||||
|
||||
export default configureStore({
|
||||
reducer: {
|
||||
drawer: drawerReducer,
|
||||
userDetails: userDetailReducer,
|
||||
},
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user