From 60b619c16037e9cf081ad5aafc447d63ace0c05b Mon Sep 17 00:00:00 2001 From: gloginov Date: Tue, 8 Oct 2024 22:56:39 +0500 Subject: [PATCH] [SOK-32] +add hoc component for layouts --- .../src/components/hoc/withAuthUser.tsx | 62 +++++++++++++++++++ .../src/layouts/AuthLayout/AuthLayout.tsx | 25 ++------ .../layouts/PrivateLayout/PrivateLayout.tsx | 39 ++---------- 3 files changed, 72 insertions(+), 54 deletions(-) create mode 100644 packages/client/src/components/hoc/withAuthUser.tsx diff --git a/packages/client/src/components/hoc/withAuthUser.tsx b/packages/client/src/components/hoc/withAuthUser.tsx new file mode 100644 index 0000000..b3a81c8 --- /dev/null +++ b/packages/client/src/components/hoc/withAuthUser.tsx @@ -0,0 +1,62 @@ +import { ComponentType, useEffect } from 'react' +import { actions, getUser, UserType } from '@/store/reducers/auth-reducer' +import { toast } from 'react-toastify' +import { useNavigate, useLocation } from 'react-router-dom' +import { RootState, useAppDispatch } from '@/store' +import { useSelector } from 'react-redux' + +export default function withAuthUser

( + Component: ComponentType

, + redirectTo?: string +) { + return function WrappedWithAuthUser(props: P) { + const user = useSelector( + state => state.authReducer.user + ) + const userIsLogged = window.sessionStorage.getItem('userIsLogged') === '1' + const navigate = useNavigate() + const dispatch = useAppDispatch() + const location = useLocation() + const { pathname } = location + + const successAuth = (redirectTo: string) => { + toast.success('Вы уже авторизованы', { + autoClose: 1500, + onClose: () => { + navigate(redirectTo) + }, + }) + } + + useEffect(() => { + if (!userIsLogged || user === null) { + dispatch(getUser()) + .unwrap() + .then(data => { + dispatch(actions.setUser(data)) + window.sessionStorage.setItem('userIsLogged', '1') // 0 + + if (redirectTo) { + successAuth(redirectTo) + } + }) + .catch(() => { + window.sessionStorage.setItem('userIsLogged', '0') // 1 + + if (!['/sign-in', '/sign-up'].includes(pathname)) { + toast.error('Необходимо авторизоваться', { + autoClose: 1500, + onClose: () => { + navigate('/sign-in') + }, + }) + } + }) + } else if (redirectTo) { + successAuth(redirectTo) + } + }, [user, userIsLogged]) + + return + } +} diff --git a/packages/client/src/layouts/AuthLayout/AuthLayout.tsx b/packages/client/src/layouts/AuthLayout/AuthLayout.tsx index e6243f2..cfdc75a 100644 --- a/packages/client/src/layouts/AuthLayout/AuthLayout.tsx +++ b/packages/client/src/layouts/AuthLayout/AuthLayout.tsx @@ -1,24 +1,7 @@ -import { Outlet, useNavigate } from 'react-router-dom' -import { useSelector } from 'react-redux' -import { RootState } from '@/store' -import { UserType } from '@/store/reducers/auth-reducer' -import { toast } from 'react-toastify' -import { useEffect } from 'react' - -export default function AuthLayout() { - const user = useSelector(state => state.authReducer.user) - const navigate = useNavigate() - - useEffect(() => { - if (window.sessionStorage.getItem('userIsLogged') === '1') { - toast.success('Вы уже авторизованы', { - autoClose: 1500, - onClose: () => { - navigate('/game') - }, - }) - } - }, [user]) +import { Outlet } from 'react-router-dom' +import withAuthUser from '@/components/hoc/withAuthUser' +const AuthLayout = () => { return } +export default withAuthUser(AuthLayout, '/game') diff --git a/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx b/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx index 827715e..55d6143 100644 --- a/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx +++ b/packages/client/src/layouts/PrivateLayout/PrivateLayout.tsx @@ -1,38 +1,10 @@ import { Header } from '@/components/common/Header/Header' -import { RootState, useAppDispatch } from '@/store' -import { actions, getUser, UserType } from '@/store/reducers/auth-reducer' -import { useEffect } from 'react' -import { useSelector } from 'react-redux' -import { Outlet, useNavigate } from 'react-router-dom' -import { toast } from 'react-toastify' +import { Outlet } from 'react-router-dom' +import withAuthUser from '@/components/hoc/withAuthUser' import './PrivateLayout.scss' -export default function PrivateLayout() { - const user = useSelector(state => state.authReducer.user) - const navigate = useNavigate() - const userIsLogged = window.sessionStorage.getItem('userIsLogged') === '1' - const dispatch = useAppDispatch() - - useEffect(() => { - if (!userIsLogged) { - dispatch(getUser()) - .unwrap() - .then(data => { - dispatch(actions.setUser(data)) - window.sessionStorage.setItem('userIsLogged', '1') // 0 - }) - .catch(() => { - window.sessionStorage.setItem('userIsLogged', '0') // 0 - - toast.error('Необходимо авторизоваться', { - autoClose: 1500, - onClose: () => { - navigate('/sign-in') - }, - }) - }) - } - }, []) +const PrivateLayout = (props: any & { userIsLogged: boolean }) => { + const { userIsLogged } = props if (userIsLogged) { return ( @@ -44,5 +16,6 @@ export default function PrivateLayout() { ) } - return user === null ?

Загрузка...

: + return

Загрузка...

} +export default withAuthUser(PrivateLayout)