logout, hover transition and small fixes

This commit is contained in:
kurpfish 2021-08-09 15:10:12 +03:00
parent 5880137dd8
commit f0a92fd8f2
20 changed files with 218 additions and 39 deletions

8
package-lock.json generated
View File

@ -12735,6 +12735,14 @@
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
}, },
"react-loader-spinner": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/react-loader-spinner/-/react-loader-spinner-4.0.0.tgz",
"integrity": "sha512-RU2vpEej6G4ECei0h3q6bgLU10of9Lw5O+4AwF/mtkrX5oY20Sh/AxoPJ7etbrs/7Q3u4jN5qwCwGLRKCHpk6g==",
"requires": {
"prop-types": "^15.7.2"
}
},
"react-overlays": { "react-overlays": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.0.1.tgz", "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-5.0.1.tgz",

View File

@ -16,6 +16,7 @@
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^1.6.0", "react-bootstrap": "^1.6.0",
"react-dom": "^17.0.2", "react-dom": "^17.0.2",
"react-loader-spinner": "^4.0.0",
"react-redux": "^7.2.4", "react-redux": "^7.2.4",
"react-router-dom": "^5.2.0", "react-router-dom": "^5.2.0",
"react-scripts": "4.0.3", "react-scripts": "4.0.3",

View File

@ -1,19 +1,19 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<title>React App</title> <head>
</head> <meta charset="utf-8" />
<body> <meta name="viewport" content="width=device-width, initial-scale=1" />
<noscript>You need to enable JavaScript to run this app.</noscript> <meta name="theme-color" content="#000000" />
<div id="root"></div> <meta name="description" content="Web site created using create-react-app" />
<title>Outstaffing</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</body>
</html> </html>

View File

@ -1,6 +1,7 @@
import React, { useState } from 'react' import React, { useState } from 'react'
import { useDispatch } from 'react-redux' import { useDispatch, useSelector } from 'react-redux'
import { auth } from '../../redux/outstaffingSlice' import { auth } from '../../redux/outstaffingSlice'
import { loading } from '../../redux/loaderSlice'
import style from './AuthForDevelopers.module.css' import style from './AuthForDevelopers.module.css'
import ellipse from '../../images/ellipse.png' import ellipse from '../../images/ellipse.png'
import arrow from '../../images/arrow__login_page.png' import arrow from '../../images/arrow__login_page.png'
@ -14,13 +15,15 @@ import vector from '../../images/Vector_Smart_Object.png'
import vectorBlack from '../../images/Vector_Smart_Object_black.png' import vectorBlack from '../../images/Vector_Smart_Object_black.png'
import { fetchAuth } from '../../server/server' import { fetchAuth } from '../../server/server'
import { useSelector } from 'react-redux'
import { selectAuth } from '../../redux/outstaffingSlice'; import { selectAuth } from '../../redux/outstaffingSlice';
import { selectIsLoading } from '../../redux/loaderSlice';
import { Redirect, Link } from 'react-router-dom'; import { Redirect, Link } from 'react-router-dom';
import { Loader } from '../Loader/Loader'
const AuthForDevelopers = () => { const AuthForDevelopers = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
const isAuth = useSelector(selectAuth) const isAuth = useSelector(selectAuth)
const isLoading = useSelector(selectIsLoading)
const [username, setUsername] = useState('') const [username, setUsername] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@ -66,19 +69,23 @@ const AuthForDevelopers = () => {
<button <button
className={style.form__btn} className={style.form__btn}
onClick={(e) => { onClick={!isLoading ? (e) => {
e.preventDefault(); e.preventDefault();
dispatch(loading(true))
fetchAuth({ fetchAuth({
username, username,
password, password,
dispatch: ()=> dispatch(auth(true)) dispatch: ()=> {
dispatch(auth(true))
dispatch(loading(false))
}
}) })
}} } : ()=>{}}
> >
Войти { isLoading ? <Loader /> : 'Войти' }
</button> </button>
<button className={`${style.form__btn} ${style.auth__link}`}> <button className={`${style.form__btn__partners} ${style.auth__link}`}>
<Link to='/auth'>Для партнёров</Link> <Link to='/auth'>Для партнёров</Link>
</button> </button>
</form> </form>

View File

@ -153,6 +153,32 @@
letter-spacing: normal; letter-spacing: normal;
line-height: 71.88px; line-height: 71.88px;
text-align: center; text-align: center;
border: 2px solid #6aaf5c;
}
.form__btn:hover {
background-image: none;
background-color: #ffffff;
border: 2px solid #6aaf5c;
color: #6aaf5c !important;
transition: .3s;
}
.form__btn__partners {
width: 288px;
height: 75px;
border-radius: 38px;
background-color: #ffffff;
border: 2px solid #6aaf5c;
font-family: 'Muller';
font-size: 2em;
letter-spacing: normal;
line-height: 71.88px;
text-align: center;
}
.form__btn__partners a {
color: #6aaf5c !important;
} }
@media (max-width: 575.98px) { @media (max-width: 575.98px) {

View File

@ -1,6 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { auth } from '../../redux/outstaffingSlice'; import { auth } from '../../redux/outstaffingSlice';
import { loading } from '../../redux/loaderSlice'
import style from './AuthForPartners.module.css'; import style from './AuthForPartners.module.css';
import ellipse from '../../images/ellipse.png'; import ellipse from '../../images/ellipse.png';
import arrow from '../../images/arrow__login_page.png'; import arrow from '../../images/arrow__login_page.png';
@ -16,12 +17,15 @@ import { fetchAuth } from '../../server/server'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { selectAuth } from '../../redux/outstaffingSlice'; import { selectAuth } from '../../redux/outstaffingSlice';
import { selectIsLoading } from '../../redux/loaderSlice';
import { Redirect, Link } from 'react-router-dom'; import { Redirect, Link } from 'react-router-dom';
import { Loader } from '../Loader/Loader'
const AuthForPartners = () => { const AuthForPartners = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
const isAuth = useSelector(selectAuth) const isAuth = useSelector(selectAuth)
const isLoading = useSelector(selectIsLoading)
console.log('iL',isLoading);
const [username, setUsername] = useState('') const [username, setUsername] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
@ -58,20 +62,25 @@ const AuthForPartners = () => {
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
/> />
<button className={style.form__btn} <button
onClick={(e) => { className={style.form__btn}
onClick={!isLoading ? (e) => {
e.preventDefault(); e.preventDefault();
dispatch(loading(true))
fetchAuth({ fetchAuth({
username, username,
password, password,
dispatch: ()=> dispatch(auth(true)) dispatch: ()=> {
dispatch(auth(true))
dispatch(loading(false))
}
}) })
} } : ()=>{}}
}> >
Войти { isLoading ? <Loader /> : 'Войти' }
</button> </button>
<button className={`${style.form__btn} ${style.auth__link}`}> <button className={`${style.form__btn__dev} ${style.auth__link}`}>
<Link to='/authdev'>Для разработчиков</Link> <Link to='/authdev'>Для разработчиков</Link>
</button> </button>
</form> </form>

View File

@ -153,6 +153,33 @@
letter-spacing: normal; letter-spacing: normal;
line-height: 71.88px; line-height: 71.88px;
text-align: center; text-align: center;
border: 2px solid #6aaf5c;
}
.form__btn:hover {
background-image: none;
background-color: #ffffff;
border: 2px solid #6aaf5c;
color: #6aaf5c !important;
transition: .3s;
}
.form__btn__dev {
width: 288px;
height: 75px;
border-radius: 38px;
background-color: #ffffff;
border: 2px solid #6aaf5c;
font-family: 'Muller';
font-size: 2em;
letter-spacing: normal;
line-height: 71.88px;
text-align: center;
}
.form__btn__dev a {
color: #6aaf5c !important;
} }
@media (max-width: 575.98px) { @media (max-width: 575.98px) {

View File

@ -29,7 +29,9 @@ const Description = ({ onLoadMore }) => {
</div> </div>
<div className="col-12 col-xl-6"> <div className="col-12 col-xl-6">
<h3 className={style.description__title}> <h3 className={style.description__title}>
{SKILLS[el.position_id]}, {LEVELS[el.level]} <Link to={`/candidate/${el.id}`}>
{SKILLS[el.position_id]}, {LEVELS[el.level]}
</Link>
</h3> </h3>
{el.vc_text_short ? ( {el.vc_text_short ? (
@ -64,7 +66,9 @@ const Description = ({ onLoadMore }) => {
</div> </div>
<div className="col-12 col-xl-6"> <div className="col-12 col-xl-6">
<h3 className={style.description__title}> <h3 className={style.description__title}>
{SKILLS[el.position_id]}, {LEVELS[el.level]} <Link to={`/candidate/${el.id}`}>
{SKILLS[el.position_id]}, {LEVELS[el.level]}
</Link>
</h3> </h3>
{el.vc_text_short ? ( {el.vc_text_short ? (

View File

@ -53,6 +53,10 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
.description__title {
color: #333;
}
@media (max-width: 575.98px) { @media (max-width: 575.98px) {
.description__title { .description__title {
text-align: center; text-align: center;

View File

@ -0,0 +1,14 @@
import SVGLoader from "react-loader-spinner";
export const Loader = () => {
return (
<div className='loader'>
<SVGLoader
type="Circles"
color="#fff"
height={50}
width={50}
timeout={3000}
/>
</div>
);
}

View File

@ -0,0 +1,14 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { auth } from '../../redux/outstaffingSlice';
import './logoutButton.css'
export const LogoutButton = () => {
const dispatch = useDispatch();
return (
<div className='logout-button' onClick={()=>{localStorage.clear(); dispatch(auth(false));}}>
<button>Выйти</button>
</div>
)
}

View File

@ -0,0 +1,30 @@
.logout-button {
position: fixed;
top: 2rem;
right: 3.5rem;
z-index: 100;
}
.logout-button button {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
padding: 1rem 2rem;
border-radius: 20px;
background-color: #6aaf5c;
color: #ffffff;
border: 2px solid #6aaf5c;
font-family: 'Muller';
font-size: 2em;
letter-spacing: normal;
text-align: center;
}
.logout-button:hover button {
background-color: #ffffff;
color: #6aaf5c;
border: 2px solid #6aaf5c;
box-shadow: 3px 2px 5px rgba(82, 151, 34, 0.21);
transition: .3s;
}

9
src/hoc/withLogout.js Normal file
View File

@ -0,0 +1,9 @@
import React from 'react';
import { LogoutButton } from '../components/LogoutButton/LogoutButton';
export const WithLogout = (props) => {
return <>
<LogoutButton />
{props.children}
</>
}

View File

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { WithLogout } from '../hoc/withLogout';
import Calendar from '../components/Calendar/Calendar'; import Calendar from '../components/Calendar/Calendar';
const CalendarPage = () => { const CalendarPage = () => {
return <Calendar />; return <WithLogout><Calendar /></WithLogout>;
}; };
export default CalendarPage; export default CalendarPage;

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { WithLogout } from '../hoc/withLogout';
import Candidate from '../components/Candidate/Candidate'; import Candidate from '../components/Candidate/Candidate';
const CandidatePage = () => <Candidate />; const CandidatePage = () => <WithLogout><Candidate /></WithLogout>;
export default CandidatePage; export default CandidatePage;

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { WithLogout } from '../hoc/withLogout';
import Form from '../components/Form/Form'; import Form from '../components/Form/Form';
const FormPage = () => <Form />; const FormPage = () => <WithLogout><Form /></WithLogout>;
export default FormPage; export default FormPage;

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { WithLogout } from '../hoc/withLogout';
import Home from '../components/Home/Home'; import Home from '../components/Home/Home';
const HomePage = () => <Home />; const HomePage = () => <WithLogout><Home /></WithLogout>;
export default HomePage; export default HomePage;

View File

@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import { WithLogout } from '../hoc/withLogout';
import ReportForm from '../components/ReportForm/ReportForm'; import ReportForm from '../components/ReportForm/ReportForm';
const ReportFormPage = () => <ReportForm />; const ReportFormPage = () => <WithLogout><ReportForm /></WithLogout>;
export default ReportFormPage; export default ReportFormPage;

21
src/redux/loaderSlice.js Normal file
View File

@ -0,0 +1,21 @@
import { createSlice } from '@reduxjs/toolkit';
const initialState = {
isLoading: false,
};
export const loaderSlice = createSlice({
name: 'loader',
initialState,
reducers: {
loading: (state, action) => {
state.isLoading = action.payload;
},
},
});
export const { loading } = loaderSlice.actions;
export const selectIsLoading = (state) => state.loader.isLoading;
export default loaderSlice.reducer;

View File

@ -1,8 +1,10 @@
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import outstaffingReducer from '../redux/outstaffingSlice'; import outstaffingReducer from '../redux/outstaffingSlice';
import loaderReducer from '../redux/loaderSlice';
export const store = configureStore({ export const store = configureStore({
reducer: { reducer: {
outstaffing: outstaffingReducer, outstaffing: outstaffingReducer,
loader: loaderReducer,
}, },
}); });