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";
import { Routes, Route } from "react-router-dom";
import ProductFormPage from "./containers/ProductFormPage/ProductFormPage";
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 Register from "./containers/Register/Register";
import PrivateRoute from "./utils/PrivateRoute";
const App = () => {
const dispatch: AppDispatch = useDispatch()
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
useEffect(() => {
dispatch(checkToken())
}, [])
return (
<Layout>
{isAuth
?
<Routes>
<Route path={'/'} element={<h1>HOME</h1>} />
<Route path={'/products'} element={<ProductsPage />} />
<Route path={'/add-product'} element={<ProductFormPage />} />
</Routes>
:
<Routes>
<Route path={'/'} element={<Login />} />
<Route path={'/register'} element={<Register />} />
</Routes>
}
</Layout>
)
}
<Routes>
<Route element={<PrivateRoute />}>
<Route element={<Layout />} >
<Route path={"/"} element={<h1>HOME</h1>} />
<Route path={"/products"} element={<ProductsPage />} />
<Route path={"/add-product"} element={<ProductFormPage />} />
</Route>
</Route>
<Route path={"/login"} element={<Login />} />
<Route path={"/register"} element={<Register />} />
</Routes>
);
};
export default App
export default App;
import axios from "axios";
import axios, { InternalAxiosRequestConfig } from "axios";
export const instance = axios.create({
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";
import styles from "./Header.module.css";
const Header: FunctionComponent = (): ReactElement => {
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
return (
<header className={styles.Header}>
{isAuth ? (
<>
<NavLink className={styles.Header__link} to={"/add-product"}>
Add product
......@@ -18,16 +16,6 @@ const Header: FunctionComponent = (): ReactElement => {
Products
</NavLink>
</>
) : (
<>
<NavLink className={styles.Header__link} to={"/register"}>
Sign up
</NavLink>
<NavLink className={styles.Header__link} to={"/"}>
Login
</NavLink>
</>
)}
</header>
);
};
......
import { ReactNode } from "react";
export default interface ILayoutProps {
children: ReactNode
}
\ No newline at end of file
import React, { FunctionComponent, ReactElement } from "react";
import { Outlet } from "react-router-dom";
import Header from "../Header/Header";
import ILayoutProps from "./ILayoutProps";
import styles from './Layout.module.css'
const Layout: FunctionComponent<ILayoutProps> = (props): ReactElement => {
const Layout: FunctionComponent = (): ReactElement => {
return (
<div className={styles.Layout}>
<Header/>
<main>
{props.children}
<Outlet />
</main>
</div>
)
......
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import IUserDto from '../../interfaces/IUserCreateDto'
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 { AppDispatch, AppState } from '../../store/store'
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 {messageUser} = useSelector((state: AppState) => state.users, shallowEqual)
const dispatch: AppDispatch = useDispatch()
const navigate = useNavigate()
const location = useLocation()
const {isAuth} = useSelector((state: AppState) => state.users, shallowEqual)
const [values, setValues] = useState<IUserDto>({
username: '',
password: ''
......@@ -23,6 +26,11 @@ const Login: React.FunctionComponent = (): React.ReactElement => {
e.preventDefault()
dispatch(login(values))
}
useEffect(() => {
if (isAuth) {
navigate(location.state?.from ? location.state.from : '/')
}
}, [isAuth])
return (
<>
<div>
......
......@@ -34,7 +34,7 @@ export const usersSlice = createSlice({
name: namespace,
initialState: {
user: {} as IUser,
isAuth: false,
isAuth: !!localStorage.getItem('token') || false,
loadingUser: false,
messageUser: ''
} as IUsersState,
......@@ -86,6 +86,8 @@ export const usersSlice = createSlice({
state.messageUser = action.payload.message
if (user) {
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