Commit 07b61617 authored by Pavel Mishakov's avatar Pavel Mishakov

add token check and Private route

parent db6fb5cb
...@@ -2,38 +2,24 @@ import Layout from "./components/Layout/Layout"; ...@@ -2,38 +2,24 @@ import Layout from "./components/Layout/Layout";
import { Routes, Route } from "react-router-dom"; import { Routes, Route } from "react-router-dom";
import ProductFormPage from "./containers/ProductFormPage/ProductFormPage"; import ProductFormPage from "./containers/ProductFormPage/ProductFormPage";
import ProductsPage from "./containers/ProductsPage/ProductsPage"; import ProductsPage from "./containers/ProductsPage/ProductsPage";
import { AppDispatch, AppState } from "./store/store";
import { shallowEqual, useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { checkToken } from "./store/users/users.slice";
import Login from "./containers/Login/Login"; import Login from "./containers/Login/Login";
import Register from "./containers/Register/Register"; import Register from "./containers/Register/Register";
import PrivateRoute from "./utils/PrivateRoute";
const App = () => { const App = () => {
const dispatch: AppDispatch = useDispatch()
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
useEffect(() => {
dispatch(checkToken())
}, [])
return ( return (
<Layout> <Routes>
{isAuth <Route element={<PrivateRoute />}>
? <Route element={<Layout />} >
<Routes> <Route path={"/"} element={<h1>HOME</h1>} />
<Route path={'/'} element={<h1>HOME</h1>} /> <Route path={"/products"} element={<ProductsPage />} />
<Route path={'/products'} element={<ProductsPage />} /> <Route path={"/add-product"} element={<ProductFormPage />} />
<Route path={'/add-product'} element={<ProductFormPage />} /> </Route>
</Routes> </Route>
: <Route path={"/login"} element={<Login />} />
<Routes> <Route path={"/register"} element={<Register />} />
<Route path={'/'} element={<Login />} /> </Routes>
<Route path={'/register'} element={<Register />} /> );
</Routes> };
}
</Layout>
)
}
export default App export default App;
import axios from "axios"; import axios, { InternalAxiosRequestConfig } from "axios";
export const instance = axios.create({ export const instance = axios.create({
baseURL: import.meta.env.VITE_BASE_URL baseURL: import.meta.env.VITE_BASE_URL
})
instance.interceptors.request.use((req: InternalAxiosRequestConfig) => {
const token = localStorage.getItem('token')
if (token) {
req.headers.Authorization = token
}
return req
}) })
\ No newline at end of file
...@@ -5,11 +5,9 @@ import { AppState } from "../../store/store"; ...@@ -5,11 +5,9 @@ import { AppState } from "../../store/store";
import styles from "./Header.module.css"; import styles from "./Header.module.css";
const Header: FunctionComponent = (): ReactElement => { const Header: FunctionComponent = (): ReactElement => {
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
return ( return (
<header className={styles.Header}> <header className={styles.Header}>
{isAuth ? (
<> <>
<NavLink className={styles.Header__link} to={"/add-product"}> <NavLink className={styles.Header__link} to={"/add-product"}>
Add product Add product
...@@ -18,16 +16,6 @@ const Header: FunctionComponent = (): ReactElement => { ...@@ -18,16 +16,6 @@ const Header: FunctionComponent = (): ReactElement => {
Products Products
</NavLink> </NavLink>
</> </>
) : (
<>
<NavLink className={styles.Header__link} to={"/register"}>
Sign up
</NavLink>
<NavLink className={styles.Header__link} to={"/"}>
Login
</NavLink>
</>
)}
</header> </header>
); );
}; };
......
import { ReactNode } from "react";
export default interface ILayoutProps {
children: ReactNode
}
\ No newline at end of file
import React, { FunctionComponent, ReactElement } from "react"; import React, { FunctionComponent, ReactElement } from "react";
import { Outlet } from "react-router-dom";
import Header from "../Header/Header"; import Header from "../Header/Header";
import ILayoutProps from "./ILayoutProps";
import styles from './Layout.module.css' import styles from './Layout.module.css'
const Layout: FunctionComponent<ILayoutProps> = (props): ReactElement => { const Layout: FunctionComponent = (): ReactElement => {
return ( return (
<div className={styles.Layout}> <div className={styles.Layout}>
<Header/> <Header/>
<main> <main>
{props.children} <Outlet />
</main> </main>
</div> </div>
) )
......
import React, { useState } from 'react' import React, { useEffect, useState } from 'react'
import IUserDto from '../../interfaces/IUserCreateDto' import IUserDto from '../../interfaces/IUserCreateDto'
import styles from './Login.module.css' import styles from './Login.module.css'
import {Link} from 'react-router-dom' import {Link, useLocation, useNavigate} from 'react-router-dom'
import { shallowEqual, useDispatch, useSelector } from 'react-redux' import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { AppDispatch, AppState } from '../../store/store' import { AppDispatch, AppState } from '../../store/store'
import {login} from '../../store/users/users.slice' import {login} from '../../store/users/users.slice'
...@@ -10,6 +10,9 @@ import {login} from '../../store/users/users.slice' ...@@ -10,6 +10,9 @@ import {login} from '../../store/users/users.slice'
const Login: React.FunctionComponent = (): React.ReactElement => { const Login: React.FunctionComponent = (): React.ReactElement => {
const {messageUser} = useSelector((state: AppState) => state.users, shallowEqual) const {messageUser} = useSelector((state: AppState) => state.users, shallowEqual)
const dispatch: AppDispatch = useDispatch() const dispatch: AppDispatch = useDispatch()
const navigate = useNavigate()
const location = useLocation()
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
const [values, setValues] = useState<IUserDto>({ const [values, setValues] = useState<IUserDto>({
username: '', username: '',
password: '' password: ''
...@@ -23,6 +26,11 @@ const Login: React.FunctionComponent = (): React.ReactElement => { ...@@ -23,6 +26,11 @@ const Login: React.FunctionComponent = (): React.ReactElement => {
e.preventDefault() e.preventDefault()
dispatch(login(values)) dispatch(login(values))
} }
useEffect(() => {
if (isAuth) {
navigate(location.state?.from ? location.state.from : '/')
}
}, [isAuth])
return ( return (
<> <>
<div> <div>
......
...@@ -34,7 +34,7 @@ export const usersSlice = createSlice({ ...@@ -34,7 +34,7 @@ export const usersSlice = createSlice({
name: namespace, name: namespace,
initialState: { initialState: {
user: {} as IUser, user: {} as IUser,
isAuth: false, isAuth: !!localStorage.getItem('token') || false,
loadingUser: false, loadingUser: false,
messageUser: '' messageUser: ''
} as IUsersState, } as IUsersState,
...@@ -86,6 +86,8 @@ export const usersSlice = createSlice({ ...@@ -86,6 +86,8 @@ export const usersSlice = createSlice({
state.messageUser = action.payload.message state.messageUser = action.payload.message
if (user) { if (user) {
state.isAuth = true state.isAuth = true
} else {
state.isAuth = false
} }
}) })
} }
......
import React, { useEffect } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { Navigate, Outlet, useLocation } from 'react-router-dom'
import { AppDispatch, AppState } from '../store/store'
import { checkToken } from '../store/users/users.slice'
const PrivateRoute: React.FunctionComponent = (): React.ReactElement => {
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
const location = useLocation()
const dispatch: AppDispatch = useDispatch()
useEffect(() => {
dispatch(checkToken())
}, [isAuth])
return (
isAuth
?
<Outlet />
:
<Navigate to='/login' replace state={{from: location}} />
)
}
export default PrivateRoute
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment