Skip to content

Commit

Permalink
Merge pull request #6 from 001elijah/auth
Browse files Browse the repository at this point in the history
Auth add login,register,current,logout
  • Loading branch information
001elijah authored Jun 19, 2023
2 parents 028dac1 + 5b32bd8 commit 85b214c
Show file tree
Hide file tree
Showing 16 changed files with 327 additions and 18 deletions.
15 changes: 15 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"react-responsive": "^9.0.2",
"react-router-dom": "^6.13.0",
"react-scripts": "5.0.1",
"redux-persist": "^6.0.0",
"sass": "^1.63.4",
"shortid": "^2.2.16",
"web-vitals": "^2.1.3",
Expand Down
1 change: 1 addition & 0 deletions src/assets/styles/_vars.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $white-text-color: #ffffff;
$priority-low-color: #8fa1d0;
$priority-medium-color: #e09cb5;
$priority-high-color: #bedbb0;
$red-error-color: #ff0000;

$start-background-color: linear-gradient(
180deg,
Expand Down
32 changes: 25 additions & 7 deletions src/components/App.jsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
import { Navigate, Route, Routes } from 'react-router-dom';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';

import { HomePage } from 'pages/HomePage';
import { BoardPage } from 'pages/BoardPage';
import { WelcomePage } from 'pages/WelcomePage/WelcomePage';
import AuthPage from '../pages/AuthPage/AuthPage';
import { SharedLayout } from './SharedLayout/SharedLayout';
import { PrivateRoute, PublicRoute } from './AuthForm/route';
import { currentUser } from 'redux/Auth/authOperations';

export const App = () => {
const dispatch = useDispatch();

useEffect(() => {
dispatch(currentUser());
}, [dispatch]);

return (
<>
<SharedLayout />
<Routes>
<Route path="/" element={<WelcomePage />} />
<Route path="auth/:id" element={<AuthPage />} />

<Route path="/home" element={<HomePage />} />
<Route path="/board" element={<BoardPage />} />

<Route path="*" element={<Navigate to="/" />} />
<Route path="/" element={<PublicRoute component={<WelcomePage />} />} />
<Route
path="/auth/:id"
element={<PublicRoute component={<AuthPage />} />}
/>
<Route
path="/home"
element={<PrivateRoute component={<HomePage />} />}
/>
<Route
path="/board"
element={<PrivateRoute component={<BoardPage />} />}
/>
<Route path="*" element={<Navigate to="/home" />} />
</Routes>
</>
);
Expand Down
5 changes: 4 additions & 1 deletion src/components/AuthForm/Login/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { useFormik } from 'formik';
import { useState } from 'react';
import { useDispatch } from 'react-redux';

import { ButtonAuth } from '../ButtonAuth/ButtonAuth';
import { validationSchemaLogin } from '../schemaValidation';
import { loginUser } from 'redux/Auth/authOperations';

import icons from '../../../assets/icons/sprite.svg';
import y from './Login.module.scss';

export const Login = () => {
const dispatch = useDispatch();
const [showPassword, setShowPassword] = useState(false);

const toggleShowPassword = () => setShowPassword(!showPassword);
Expand All @@ -19,7 +22,7 @@ export const Login = () => {
},
validationSchema: validationSchemaLogin,
onSubmit: values => {
console.log(values);
dispatch(loginUser(values));
},
});
return (
Expand Down
5 changes: 4 additions & 1 deletion src/components/AuthForm/Login/Login.module.scss
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
@import '../../../assets/styles/vars';

.error {
position: absolute;
color: #ff0000;
color: $red-error-color;
font-size: 12px;
}

Expand All @@ -16,4 +18,5 @@
bottom: 15px;

opacity: 0.4;
cursor: pointer;
}
11 changes: 7 additions & 4 deletions src/components/AuthForm/Register/Register.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
import { useFormik } from 'formik';
import { useState } from 'react';
import { useDispatch } from 'react-redux';

import { ButtonAuth } from '../ButtonAuth/ButtonAuth';
import { validationSchemaRegister } from '../schemaValidation';
import { registerUser } from 'redux/Auth/authOperations';

import icons from '../../../assets/icons/sprite.svg';
import y from '../Login/Login.module.scss';

export const Register = () => {
const dispatch = useDispatch();
const [showPassword, setShowPassword] = useState(false);

const toggleShowPassword = () => setShowPassword(!showPassword);

const formik = useFormik({
initialValues: {
name: '',
userName: '',
email: '',
password: '',
},
validationSchema: validationSchemaRegister,
onSubmit: values => {
console.log(values);
dispatch(registerUser(values));
},
});
return (
<form onSubmit={formik.handleSubmit}>
<label htmlFor="name">
<input
id="name"
name="name"
id="userName"
name="userName"
type="text"
onChange={formik.handleChange}
value={formik.values.name}
Expand Down
27 changes: 27 additions & 0 deletions src/components/AuthForm/route.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useSelector } from 'react-redux';
import { Navigate } from 'react-router';
import PropTypes from 'prop-types';

import { selectorIsAuth } from 'redux/Auth/authSelectors';

export const PrivateRoute = ({ component, redirectTo = '/' }) => {
const isAuth = useSelector(selectorIsAuth);

return isAuth ? component : <Navigate to={redirectTo} />;
};

export const PublicRoute = ({ component, redirectTo = '/home' }) => {
const isAuth = useSelector(selectorIsAuth);

return !isAuth ? component : <Navigate to={redirectTo} />;
};

PrivateRoute.propTypes = {
component: PropTypes.object.isRequired,
redirectTo: PropTypes.string,
};

PublicRoute.propTypes = {
component: PropTypes.object.isRequired,
redirectTo: PropTypes.string,
};
2 changes: 1 addition & 1 deletion src/components/AuthForm/schemaValidation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const validationSchemaLogin = yup.object().shape({
});

export const validationSchemaRegister = yup.object().shape({
name: yup
userName: yup
.string()
.matches(
/^[a-zA-Z0-9]+$/,
Expand Down
14 changes: 11 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@ import ReactDOM from 'react-dom/client';
import { App } from 'components/App';
import { BrowserRouter } from 'react-router-dom';

import { Provider } from 'react-redux';
import { persistor, store } from './redux/store';
import { PersistGate } from 'redux-persist/integration/react';

import './index.scss';

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<BrowserRouter basename="/bc48-node-team-project-frontend">
<App />
</BrowserRouter>
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<BrowserRouter basename="/bc48-node-team-project-frontend">
<App />
</BrowserRouter>
</PersistGate>
</Provider>
</React.StrictMode>,
);
9 changes: 8 additions & 1 deletion src/pages/HomePage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { logoutUser } from 'redux/Auth/authOperations';

export const HomePage = () => {
return <div>HomePage</div>;
const dispatch = useDispatch();
return (
<div>
<button onClick={() => dispatch(logoutUser())}>Log logOut</button>
</div>
);
};
69 changes: 69 additions & 0 deletions src/redux/Auth/authOperations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { createAsyncThunk } from '@reduxjs/toolkit';

import {
registerUserApi,
loginUserApi,
currentUserApi,
logoutUserApi,
} from 'services/backendAPI';

export const registerUser = createAsyncThunk(
'auth/register',
async (dataUser, { rejectWithValue }) => {
try {
const data = await registerUserApi(dataUser);
return data;
} catch (error) {
return rejectWithValue(error.message);
}
},
);

export const loginUser = createAsyncThunk(
'auth/login',
async (dataUser, { rejectWithValue }) => {
try {
const userData = await loginUserApi(dataUser);
return userData;
} catch (error) {
return rejectWithValue(error.message);
}
},
);

export const currentUser = createAsyncThunk(
'auth/current',
async (_, { getState, rejectWithValue, dispatch }) => {
const { token } = getState().auth;
try {
const data = await currentUserApi(token);
return data;
} catch (error) {
setTimeout(() => {
dispatch(logoutUser(token));
}, 0);
return rejectWithValue(error.message);
}
},
{
condition(_, { getState }) {
const { token } = getState().auth;
return Boolean(token);
},
},
);

export const logoutUser = createAsyncThunk(
'auth/logout',
async (_, { getState, rejectWithValue }) => {
const { token } = getState().auth;
try {
await logoutUserApi(token);
return null;
} catch (error) {
return rejectWithValue(error.message);
}
},
);


3 changes: 3 additions & 0 deletions src/redux/Auth/authSelectors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const selectorIsAuth = state => Boolean(state.auth.token);

export const selectorTheme = state => state.auth.theme;
Loading

0 comments on commit 85b214c

Please sign in to comment.