Переписываю спорные решения
This commit is contained in:
parent
1234427b12
commit
75de4983c9
@ -1,2 +1,2 @@
|
|||||||
REACT_APP_API_URL = https://dev.itguild.info
|
REACT_APP_API_URL = https://dev.itguild.info/api
|
||||||
REACT_APP_BASE_URL = https://dev.itguild.info
|
REACT_APP_BASE_URL = https://dev.itguild.info/api
|
39090
package-lock.json
generated
39090
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
|||||||
"@testing-library/user-event": "^12.8.3",
|
"@testing-library/user-event": "^12.8.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.5.0",
|
"@typescript-eslint/eslint-plugin": "^4.5.0",
|
||||||
"@typescript-eslint/parser": "^4.5.0",
|
"@typescript-eslint/parser": "^4.5.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.24.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"babel-jest": "^26.6.0",
|
"babel-jest": "^26.6.0",
|
||||||
"babel-loader": "8.1.0",
|
"babel-loader": "8.1.0",
|
||||||
@ -65,7 +65,7 @@
|
|||||||
"react-phone-input-2": "^2.14.0",
|
"react-phone-input-2": "^2.14.0",
|
||||||
"react-redux": "^7.2.4",
|
"react-redux": "^7.2.4",
|
||||||
"react-refresh": "^0.8.3",
|
"react-refresh": "^0.8.3",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^6.2.1",
|
||||||
"react-select": "^4.3.1",
|
"react-select": "^4.3.1",
|
||||||
"react-syntax-highlighter": "^15.4.5",
|
"react-syntax-highlighter": "^15.4.5",
|
||||||
"react-yandex-metrika": "^2.6.0",
|
"react-yandex-metrika": "^2.6.0",
|
||||||
@ -84,7 +84,8 @@
|
|||||||
"webpack": "4.44.2",
|
"webpack": "4.44.2",
|
||||||
"webpack-dev-server": "3.11.1",
|
"webpack-dev-server": "3.11.1",
|
||||||
"webpack-manifest-plugin": "2.2.0",
|
"webpack-manifest-plugin": "2.2.0",
|
||||||
"workbox-webpack-plugin": "5.1.4"
|
"workbox-webpack-plugin": "5.1.4",
|
||||||
|
"react-router": "latest"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node scripts/start.js",
|
"start": "node scripts/start.js",
|
||||||
|
84
src/App.js
84
src/App.js
@ -1,12 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
|
import {BrowserRouter as Router, Route, Routes, Navigate} from 'react-router-dom';
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css'
|
|
||||||
import './fonts/stylesheet.css'
|
|
||||||
|
|
||||||
import { ProtectedRoute } from './components/ProtectedRoute/ProtectedRoute'
|
|
||||||
|
|
||||||
import AuthPageForDevelopers from './pages/AuthPageForDevelopers'
|
import AuthForPartners from "./pages/AuthForPartners/AuthForPartners";
|
||||||
import AuthPageForPartners from './pages/AuthPageForPartners'
|
import AuthForDevelopers from "./pages/AuthForDevelopers/AuthForDevelopers";
|
||||||
import HomePage from './pages/HomePage'
|
import HomePage from './pages/HomePage'
|
||||||
import CandidatePage from './pages/CandidatePage'
|
import CandidatePage from './pages/CandidatePage'
|
||||||
import CalendarPage from './pages/CalendarPage'
|
import CalendarPage from './pages/CalendarPage'
|
||||||
@ -19,54 +16,51 @@ import { InterjacentPage } from './pages/quiz/InterjacentPage'
|
|||||||
import {QuizTestPage} from './pages/quiz/QuizTestPage'
|
import {QuizTestPage} from './pages/quiz/QuizTestPage'
|
||||||
import {InstructionPage} from './pages/quiz/InstructionPage'
|
import {InstructionPage} from './pages/quiz/InstructionPage'
|
||||||
import {ResultPage} from './pages/quiz/ResultPage'
|
import {ResultPage} from './pages/quiz/ResultPage'
|
||||||
import { Profile } from './pages/Profile.js'
|
import {Profile} from './pages/Profile/Profile.js'
|
||||||
import { Summary } from './pages/Summary'
|
import {Summary} from './pages/Summary/Summary'
|
||||||
|
|
||||||
|
import './fonts/stylesheet.css'
|
||||||
|
import 'bootstrap/dist/css/bootstrap.min.css'
|
||||||
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>IT Аутстаффинг в России</h1>
|
<h1>IT Аутстаффинг в России</h1>
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
|
||||||
<Route path='/authdev' exact>
|
<Routes>
|
||||||
<AuthPageForDevelopers />
|
<Route exact path='/' element={<HomePage/>}/>
|
||||||
|
|
||||||
|
<Route exact path='/authdev' element={<AuthForDevelopers/>}/>
|
||||||
|
<Route exact path='/auth' element={<AuthForPartners/>}/>
|
||||||
|
|
||||||
|
<Route exact path='/candidate/:id' element={<CandidatePage/>}/>
|
||||||
|
<Route exact path='/candidate/:id/form' element={<FormPage/>}/>
|
||||||
|
<Route path='/:userId/calendar' element={<CalendarPage/>}/>
|
||||||
|
|
||||||
|
<Route exact path='/report' element={<ReportPage/>}/>
|
||||||
|
<Route path='/report/:id' element={<SingleReportPage/>}/>
|
||||||
|
|
||||||
|
<Route path='/quiz' element={<QuizPage/>}/>
|
||||||
|
<Route path='/quiz-interjacent' element={<InterjacentPage/>}/>
|
||||||
|
<Route path='/quiz-test' element={<QuizTestPage/>}/>
|
||||||
|
<Route path='/quiz-instruction' element={<InstructionPage/>}/>
|
||||||
|
<Route path='/quiz-result' element={<ResultPage/>}/>
|
||||||
|
|
||||||
|
<Route exact path='/profile' element={<Profile/>}>
|
||||||
|
<Route exact path='calendar' element={<ProfileCalendarPage/>}/>
|
||||||
|
<Route exact path='summary' element={<Summary/>}/>
|
||||||
</Route>
|
</Route>
|
||||||
<Route path='/auth' exact>
|
|
||||||
<AuthPageForPartners />
|
{/*<Route component={() => <div>Page not found</div>} />*/}
|
||||||
</Route>
|
{/*<Route path='*' component={() => <div>Page not found</div>}/>*/}
|
||||||
<ProtectedRoute exact path='/' component={HomePage} />
|
|
||||||
<ProtectedRoute
|
<Route path="*" element={<Navigate to="/" replace/>}/>
|
||||||
exact
|
</Routes>
|
||||||
path='/candidate/:id'
|
|
||||||
component={CandidatePage}
|
|
||||||
/>
|
|
||||||
<ProtectedRoute path='/:userId/calendar' component={CalendarPage} />
|
|
||||||
<ProtectedRoute
|
|
||||||
exact
|
|
||||||
path='/candidate/:id/form'
|
|
||||||
component={FormPage}
|
|
||||||
/>
|
|
||||||
<ProtectedRoute exact path='/report' component={ReportPage} />
|
|
||||||
<ProtectedRoute path='/report/:id' component={SingleReportPage} />
|
|
||||||
<ProtectedRoute path='/ProfileCalendar' component={ProfileCalendarPage} />
|
|
||||||
<ProtectedRoute path='/quiz' component={QuizPage} />
|
|
||||||
<ProtectedRoute
|
|
||||||
path='/quiz-interjacent'
|
|
||||||
component={InterjacentPage}
|
|
||||||
/>
|
|
||||||
<ProtectedRoute path='/quiz-test' component={QuizTestPage} />
|
|
||||||
<ProtectedRoute
|
|
||||||
path='/quiz-instruction'
|
|
||||||
component={InstructionPage}
|
|
||||||
/>
|
|
||||||
<ProtectedRoute path='/profile' component={Profile} />
|
|
||||||
<ProtectedRoute path='/summary' component={Summary} />
|
|
||||||
<ProtectedRoute path='/quiz-result' component={ResultPage} />
|
|
||||||
<ProtectedRoute component={() => <div>Page not found</div>} />
|
|
||||||
</Switch>
|
|
||||||
</Router>
|
</Router>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
48
src/api/request.js
Normal file
48
src/api/request.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// import axios from 'axios';
|
||||||
|
// import {getToken, urlHasParams} from "../helper";
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// const instance = axios.create({
|
||||||
|
// baseURL: process.env.REACT_APP_API_URL,
|
||||||
|
// validateStatus(status) {
|
||||||
|
// return status;
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// export default function request(url, {method = 'get', params, data, headers} = {}) {
|
||||||
|
// const fullHeaders = {...headers, ...getToken()};
|
||||||
|
// let urWithParams = urlHasParams(url);
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// return instance
|
||||||
|
// .request({
|
||||||
|
// url: urWithParams,
|
||||||
|
// method,
|
||||||
|
// params,
|
||||||
|
// data,
|
||||||
|
// headers: {...fullHeaders},
|
||||||
|
// })
|
||||||
|
// .then(response => new Promise(resolve => {
|
||||||
|
// console.log(response, 1)
|
||||||
|
// if(response.data.redirect || response.status === 401) {
|
||||||
|
//
|
||||||
|
// // window.location.href = "/auth"
|
||||||
|
// }
|
||||||
|
// return resolve(response)
|
||||||
|
// }))
|
||||||
|
// .then(response => new Promise(resolve => resolve(response.data)))
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function RequestError(code, msg, data) {
|
||||||
|
// const description = msg ? `- ${msg}` : '';
|
||||||
|
//
|
||||||
|
// this.name = 'RequestError';
|
||||||
|
// this.message = `API returned: ${code}${description}.`;
|
||||||
|
// this.code = code;
|
||||||
|
// this.description = msg;
|
||||||
|
// this.data = data;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// RequestError.prototype = Object.create(Error.prototype);
|
||||||
|
// RequestError.prototype.constructor = RequestError;
|
@ -1,31 +1,71 @@
|
|||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {Link} from 'react-router-dom'
|
import {Link} from 'react-router-dom'
|
||||||
import {useDispatch, useSelector} from 'react-redux'
|
import {useDispatch, useSelector} from 'react-redux'
|
||||||
|
import {withSwalInstance} from 'sweetalert2-react'
|
||||||
import { auth, setUserInfo } from '../../redux/outstaffingSlice'
|
import swal from 'sweetalert2'
|
||||||
import { loading } from '../../redux/loaderSlice'
|
|
||||||
import ellipse from '../../images/ellipse.png'
|
|
||||||
|
|
||||||
import {Loader} from '../Loader/Loader'
|
import {Loader} from '../Loader/Loader'
|
||||||
|
|
||||||
import { fetchAuth } from '../../server/server'
|
import {auth, setUserInfo} from '../../redux/outstaffingSlice'
|
||||||
|
import {loading} from '../../redux/loaderSlice'
|
||||||
import {setRole} from '../../redux/roleSlice'
|
import {setRole} from '../../redux/roleSlice'
|
||||||
|
|
||||||
import {selectIsLoading} from '../../redux/loaderSlice'
|
import {selectIsLoading} from '../../redux/loaderSlice'
|
||||||
|
|
||||||
import './authBox.scss'
|
import ellipse from '../../images/ellipse.png'
|
||||||
|
|
||||||
import { withSwalInstance } from 'sweetalert2-react'
|
import './authBox.scss'
|
||||||
import swal from 'sweetalert2'
|
import {useRequest} from "../../hooks/useRequest";
|
||||||
const SweetAlert = withSwalInstance(swal)
|
|
||||||
|
|
||||||
|
const SweetAlert = withSwalInstance(swal);
|
||||||
|
|
||||||
export const AuthBox = ({title, altTitle, roleChangeLink}) => {
|
export const AuthBox = ({title, altTitle, roleChangeLink}) => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const isLoading = useSelector(selectIsLoading)
|
const {apiRequest} = useRequest();
|
||||||
|
|
||||||
const [username, setUsername] = useState('')
|
const isLoading = useSelector(selectIsLoading);
|
||||||
const [password, setPassword] = useState('')
|
|
||||||
const [error, setError] = useState(null)
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [error, setError] = useState(null);
|
||||||
|
|
||||||
|
const submitHandler = () => {
|
||||||
|
|
||||||
|
if (!isLoading) {
|
||||||
|
dispatch(loading(true));
|
||||||
|
apiRequest('/user/login',
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
data: JSON.stringify({
|
||||||
|
username,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
}).then((res) => {
|
||||||
|
|
||||||
|
if (!res.access_token) {
|
||||||
|
|
||||||
|
setError('Некорректные данные для входа');
|
||||||
|
dispatch(loading(false))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
localStorage.setItem('auth_token', res.access_token);
|
||||||
|
localStorage.setItem('id', res.id);
|
||||||
|
localStorage.setItem('cardId', res.card_id);
|
||||||
|
localStorage.setItem(
|
||||||
|
'access_token_expired_at',
|
||||||
|
res.access_token_expired_at
|
||||||
|
);
|
||||||
|
dispatch(auth(true));
|
||||||
|
dispatch(setUserInfo(res));
|
||||||
|
dispatch(loading(false));
|
||||||
|
dispatch(setRole('ROLE_PARTNER'))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='auth-box'>
|
<div className='auth-box'>
|
||||||
@ -69,28 +109,10 @@ export const AuthBox = ({ title, altTitle, roleChangeLink }) => {
|
|||||||
<div className='auth-box__form-buttons'>
|
<div className='auth-box__form-buttons'>
|
||||||
<button
|
<button
|
||||||
className='auth-box__form-btn'
|
className='auth-box__form-btn'
|
||||||
onClick={
|
onClick={(e) => {
|
||||||
!isLoading
|
e.preventDefault();
|
||||||
? (e) => {
|
submitHandler()
|
||||||
e.preventDefault()
|
}}
|
||||||
dispatch(loading(true))
|
|
||||||
fetchAuth({
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
dispatch: (resJSON) => {
|
|
||||||
dispatch(auth(true))
|
|
||||||
dispatch(setUserInfo(resJSON))
|
|
||||||
dispatch(loading(false))
|
|
||||||
dispatch(setRole('ROLE_PARTNER'))
|
|
||||||
},
|
|
||||||
catchError: () => {
|
|
||||||
setError('Некорректные данные для входа')
|
|
||||||
dispatch(loading(false))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
: () => {}
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{isLoading ? <Loader/> : 'Войти'}
|
{isLoading ? <Loader/> : 'Войти'}
|
||||||
</button>
|
</button>
|
||||||
@ -104,4 +126,4 @@ export const AuthBox = ({ title, altTitle, roleChangeLink }) => {
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {useEffect} from 'react'
|
import React, {useEffect} from 'react'
|
||||||
import {useHistory, useParams, Link} from 'react-router-dom'
|
import {useParams, Link, useNavigate} from 'react-router-dom'
|
||||||
import {useSelector, useDispatch} from 'react-redux'
|
import {useSelector, useDispatch} from 'react-redux'
|
||||||
import {
|
import {
|
||||||
currentCandidate,
|
currentCandidate,
|
||||||
@ -22,8 +22,8 @@ import {Footer} from '../Footer/Footer'
|
|||||||
import './candidate.scss'
|
import './candidate.scss'
|
||||||
|
|
||||||
const Candidate = () => {
|
const Candidate = () => {
|
||||||
const history = useHistory();
|
|
||||||
const {id: candidateId} = useParams();
|
const {id: candidateId} = useParams();
|
||||||
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const role = useSelector(getRole);
|
const role = useSelector(getRole);
|
||||||
const [activeSnippet, setActiveSnippet] = useState(true);
|
const [activeSnippet, setActiveSnippet] = useState(true);
|
||||||
@ -36,7 +36,6 @@ const Candidate = () => {
|
|||||||
fetchGet({
|
fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile/${candidateId}`,
|
link: `${process.env.REACT_APP_API_URL}/api/profile/${candidateId}`,
|
||||||
params: Number(candidateId),
|
params: Number(candidateId),
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((el) => dispatch(currentCandidate(el)))
|
}).then((el) => dispatch(currentCandidate(el)))
|
||||||
@ -97,7 +96,7 @@ const Candidate = () => {
|
|||||||
<div className='row'>
|
<div className='row'>
|
||||||
<div className='col-12 candidate__header'>
|
<div className='col-12 candidate__header'>
|
||||||
|
|
||||||
<div className='candidate__arrow' onClick={() => history.push('/')}>
|
<div className='candidate__arrow' onClick={() => navigate('/')}>
|
||||||
<div className='candidate__arrow-img'>
|
<div className='candidate__arrow-img'>
|
||||||
<img src={arrow} alt=''/>
|
<img src={arrow} alt=''/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,43 +1,42 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import male from '../../images/medium_male.png'
|
import male from '../../images/medium_male.png'
|
||||||
import rectangle from '../../images/rectangle_secondPage.png'
|
import rectangle from '../../images/rectangle_secondPage.png'
|
||||||
import { Link, useHistory } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { LEVELS, SKILLS } from '../constants/constants'
|
import { LEVELS, SKILLS } from '../constants/constants'
|
||||||
import {
|
import {
|
||||||
selectProfiles,
|
selectProfiles,
|
||||||
selectFilteredCandidates,
|
selectFilteredCandidates,
|
||||||
selectItems,
|
selectItems,
|
||||||
auth
|
|
||||||
} from '../../redux/outstaffingSlice'
|
} from '../../redux/outstaffingSlice'
|
||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import { fetchGet } from '../../server/server'
|
|
||||||
import { Loader } from '../Loader/Loader'
|
import { Loader } from '../Loader/Loader'
|
||||||
import { getRole } from '../../redux/roleSlice'
|
import { getRole } from '../../redux/roleSlice'
|
||||||
|
|
||||||
import './description.scss'
|
import './description.scss'
|
||||||
|
import {useRequest} from "../../hooks/useRequest";
|
||||||
|
|
||||||
const Description = ({ onLoadMore, isLoadingMore }) => {
|
const Description = ({ onLoadMore, isLoadingMore }) => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
const [isLoaded, setIsLoaded] = useState(false)
|
const {apiRequest} = useRequest();
|
||||||
const history = useHistory()
|
const [isLoaded, setIsLoaded] = useState(false);
|
||||||
const role = useSelector(getRole)
|
const role = useSelector(getRole);
|
||||||
const candidatesListArr = useSelector(selectProfiles)
|
const candidatesListArr = useSelector(selectProfiles);
|
||||||
const itemsArr = useSelector(selectItems)
|
const itemsArr = useSelector(selectItems);
|
||||||
const filteredListArr = useSelector(selectFilteredCandidates)
|
const filteredListArr = useSelector(selectFilteredCandidates);
|
||||||
const [allCandidates, getAllCandidates] = useState([])
|
const [allCandidates, getAllCandidates] = useState([]);
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
fetchGet({
|
// apiRequest('/profile?limit=',{
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile?limit=`,
|
// params: 1000,
|
||||||
params: 1000,
|
//
|
||||||
history,
|
// role,
|
||||||
role,
|
// logout: () => dispatch(auth(false))
|
||||||
logout: () => dispatch(auth(false))
|
// }).then((p) => {
|
||||||
}).then((p) => {
|
// getAllCandidates(p);
|
||||||
getAllCandidates(p)
|
// setIsLoaded(true)
|
||||||
setIsLoaded(true)
|
// })
|
||||||
})
|
// }, []);
|
||||||
}, [])
|
|
||||||
|
|
||||||
if (!filteredListArr) {
|
if (!filteredListArr) {
|
||||||
return (
|
return (
|
||||||
@ -242,6 +241,6 @@ const Description = ({ onLoadMore, isLoadingMore }) => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Description
|
export default Description
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { fetchPost } from '../../server/server'
|
import { fetchPost } from '../../server/server'
|
||||||
import { auth } from '../../redux/outstaffingSlice'
|
import { auth } from '../../redux/outstaffingSlice'
|
||||||
import { useHistory, useParams, Redirect } from 'react-router-dom'
|
import {useParams, useNavigate} from 'react-router-dom'
|
||||||
import { Loader } from '../Loader/Loader'
|
import { Loader } from '../Loader/Loader'
|
||||||
import PhoneInput from 'react-phone-input-2'
|
import PhoneInput from 'react-phone-input-2'
|
||||||
import 'react-phone-input-2/lib/style.css'
|
import 'react-phone-input-2/lib/style.css'
|
||||||
@ -16,7 +16,7 @@ const SweetAlert = withSwalInstance(swal)
|
|||||||
|
|
||||||
const Form = () => {
|
const Form = () => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const history = useHistory()
|
const navigate = useNavigate()
|
||||||
const role = useSelector(getRole)
|
const role = useSelector(getRole)
|
||||||
const urlParams = useParams()
|
const urlParams = useParams()
|
||||||
const [status, setStatus] = useState(null)
|
const [status, setStatus] = useState(null)
|
||||||
@ -52,7 +52,7 @@ const Form = () => {
|
|||||||
profile_id: urlParams.id,
|
profile_id: urlParams.id,
|
||||||
...data
|
...data
|
||||||
},
|
},
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((res) =>
|
}).then((res) =>
|
||||||
@ -79,8 +79,8 @@ const Form = () => {
|
|||||||
setStatus(null)
|
setStatus(null)
|
||||||
}
|
}
|
||||||
: () => {
|
: () => {
|
||||||
setStatus(null)
|
setStatus(null);
|
||||||
history.push(`/candidate/${urlParams.id}`)
|
navigate(`/candidate/${urlParams.id}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -1,58 +1,64 @@
|
|||||||
import React, {useState, useEffect} from 'react'
|
import React, {useState, useEffect} from 'react'
|
||||||
import {useDispatch, useSelector} from 'react-redux'
|
import {useDispatch, useSelector} from 'react-redux'
|
||||||
|
|
||||||
import Outstaffing from '../Outstaffing/Outstaffing'
|
import Outstaffing from '../Outstaffing/Outstaffing'
|
||||||
import Description from '../Description/Description'
|
import Description from '../Description/Description'
|
||||||
import { fetchGet } from '../../server/server'
|
import {Footer} from '../Footer/Footer'
|
||||||
|
|
||||||
|
|
||||||
import {profiles, tags, auth} from '../../redux/outstaffingSlice'
|
import {profiles, tags, auth} from '../../redux/outstaffingSlice'
|
||||||
import {getRole} from '../../redux/roleSlice'
|
import {getRole} from '../../redux/roleSlice'
|
||||||
import { Footer } from '../Footer/Footer'
|
|
||||||
import { useHistory } from 'react-router-dom'
|
import {useRequest} from "../../hooks/useRequest";
|
||||||
|
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
const history = useHistory()
|
|
||||||
const [isLoadingMore, setIsLoadingMore] = useState(false)
|
|
||||||
const [index, setIndex] = useState(4)
|
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
const [isLoadingMore, setIsLoadingMore] = useState(false);
|
||||||
const role = useSelector(getRole)
|
const [index, setIndex] = useState(4);
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const role = useSelector(getRole);
|
||||||
|
|
||||||
|
const {apiRequest} = useRequest();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsLoadingMore(true)
|
setIsLoadingMore(true);
|
||||||
fetchGet({
|
apiRequest('/profile',{
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile?limit=`,
|
//Корс блокирует все фильтры в гет параметрах
|
||||||
params: index,
|
// params: {"get-document-list": 1000},
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
// logout: () => dispatch(auth(false))
|
||||||
}).then((profileArr) => {
|
}).then((profileArr) => {
|
||||||
dispatch(profiles(profileArr))
|
|
||||||
setIsLoadingMore(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
fetchGet({
|
dispatch(profiles(profileArr));
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/skills/skills-on-main-page`,
|
setIsLoadingMore(false)
|
||||||
history,
|
});
|
||||||
|
|
||||||
|
apiRequest('/skills/skills-on-main-page',{
|
||||||
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
// logout: () => dispatch(auth(false))
|
||||||
}).then((skills) => {
|
}).then((skills) => {
|
||||||
if (!skills) {
|
if (!skills) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
const keys = Object.keys(skills)
|
|
||||||
const values = Object.values(skills)
|
const keys = Object.keys(skills);
|
||||||
|
const values = Object.values(skills);
|
||||||
|
|
||||||
const tempTags = values.map((value, index) =>
|
const tempTags = values.map((value, index) =>
|
||||||
value.map((val) => {
|
value.map((val) => {
|
||||||
return {id: val.id, value: val.tags, name: keys[index]}
|
return {id: val.id, value: val.tags, name: keys[index]}
|
||||||
})
|
})
|
||||||
)
|
);
|
||||||
dispatch(tags(tempTags))
|
dispatch(tags(tempTags))
|
||||||
})
|
})
|
||||||
}, [dispatch, index])
|
}, [dispatch, index]);
|
||||||
|
|
||||||
const loadMore = (count) => {
|
const loadMore = (count) => {
|
||||||
setIndex((prev) => prev + count)
|
setIndex((prev) => prev + count)
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -61,6 +67,6 @@ const Home = () => {
|
|||||||
<Footer/>
|
<Footer/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Home
|
export default Home
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import SVGLoader from 'react-loader-spinner'
|
import SVGLoader from 'react-loader-spinner'
|
||||||
import './loader.scss'
|
import './loader.scss'
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
export const Loader = ({ width = 50, height = 50 }) => {
|
export const Loader = ({ width = 50, height = 50 }) => {
|
||||||
return (
|
return (
|
||||||
@ -7,4 +8,4 @@ export const Loader = ({ width = 50, height = 50 }) => {
|
|||||||
<SVGLoader type='Circles' color='#fff' height={height} width={width} />
|
<SVGLoader type='Circles' color='#fff' height={height} width={width} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {useHistory} from 'react-router-dom'
|
import {useNavigate} from 'react-router-dom'
|
||||||
import {useDispatch, useSelector} from 'react-redux'
|
import {useDispatch, useSelector} from 'react-redux'
|
||||||
import {Loader} from '../Loader/Loader'
|
import {Loader} from '../Loader/Loader'
|
||||||
import {auth} from '../../redux/outstaffingSlice'
|
import {auth} from '../../redux/outstaffingSlice'
|
||||||
@ -11,7 +11,7 @@ export const LogoutButton = () => {
|
|||||||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const userRole = useSelector(getRole);
|
const userRole = useSelector(getRole);
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='logout-button'>
|
<div className='logout-button'>
|
||||||
@ -21,7 +21,7 @@ export const LogoutButton = () => {
|
|||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
dispatch(auth(false));
|
dispatch(auth(false));
|
||||||
setIsLoggingOut(false);
|
setIsLoggingOut(false);
|
||||||
history.push(userRole === 'ROLE_DEV' ? '/authdev' : '/auth')
|
navigate(userRole === 'ROLE_DEV' ? '/authdev' : '/auth')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{isLoggingOut ? <Loader/> : 'Выйти'}{' '}
|
{isLoggingOut ? <Loader/> : 'Выйти'}{' '}
|
||||||
|
@ -21,18 +21,18 @@ const createSelectPositionHandler =
|
|||||||
} else {
|
} else {
|
||||||
dispatch(setPositionId(id))
|
dispatch(setPositionId(id))
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const Outstaffing = () => {
|
const Outstaffing = () => {
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
const positionId = useSelector(getPositionId)
|
const positionId = useSelector(getPositionId);
|
||||||
const tagsArr = useSelector(selectTags)
|
const tagsArr = useSelector(selectTags);
|
||||||
|
|
||||||
const onSelectPosition = createSelectPositionHandler({
|
const onSelectPosition = createSelectPositionHandler({
|
||||||
positionId,
|
positionId,
|
||||||
setPositionId,
|
setPositionId,
|
||||||
dispatch
|
dispatch
|
||||||
})
|
});
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className='outstaffing'>
|
<section className='outstaffing'>
|
||||||
@ -91,6 +91,6 @@ const Outstaffing = () => {
|
|||||||
<TagSelect />
|
<TagSelect />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Outstaffing
|
export default Outstaffing
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from '../../redux/outstaffingSlice'
|
} from '../../redux/outstaffingSlice'
|
||||||
|
|
||||||
import { fetchGet } from '../../server/server'
|
import { fetchGet } from '../../server/server'
|
||||||
import { useHistory } from 'react-router-dom'
|
|
||||||
import { getRole } from '../../redux/roleSlice'
|
import { getRole } from '../../redux/roleSlice'
|
||||||
|
|
||||||
import './outstaffingBlock.scss'
|
import './outstaffingBlock.scss'
|
||||||
@ -19,35 +19,32 @@ const handlePositionClick = ({
|
|||||||
positionId,
|
positionId,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
history,
|
|
||||||
role
|
role
|
||||||
}) => {
|
}) => {
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
fetchGet({
|
fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile?limit=`,
|
link: `${process.env.REACT_APP_API_URL}/api/profile?limit=`,
|
||||||
params: 4,
|
params: 4,
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((profileArr) => {
|
}).then((profileArr) => {
|
||||||
dispatch(filteredCandidates(profileArr))
|
dispatch(filteredCandidates(profileArr));
|
||||||
dispatch(selectedItems([]))
|
dispatch(selectedItems([]));
|
||||||
onSelect(positionId)
|
onSelect(positionId)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
fetchGet({
|
fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile?position_id=`,
|
link: `${process.env.REACT_APP_API_URL}/api/profile?position_id=`,
|
||||||
params: positionId,
|
params: positionId,
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((el) => {
|
}).then((el) => {
|
||||||
dispatch(filteredCandidates(el))
|
dispatch(filteredCandidates(el));
|
||||||
dispatch(selectedItems([]))
|
dispatch(selectedItems([]));
|
||||||
onSelect(positionId)
|
onSelect(positionId)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const OutstaffingBlock = ({
|
const OutstaffingBlock = ({
|
||||||
dataTags = [],
|
dataTags = [],
|
||||||
@ -58,20 +55,20 @@ const OutstaffingBlock = ({
|
|||||||
isSelected,
|
isSelected,
|
||||||
onSelect
|
onSelect
|
||||||
}) => {
|
}) => {
|
||||||
const history = useHistory()
|
|
||||||
const role = useSelector(getRole)
|
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
const role = useSelector(getRole);
|
||||||
|
|
||||||
const itemsArr = useSelector(selectItems)
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const itemsArr = useSelector(selectItems);
|
||||||
|
|
||||||
const handleBlockClick = (item, id) => {
|
const handleBlockClick = (item, id) => {
|
||||||
if (!itemsArr.find((el) => item === el.value)) {
|
if (!itemsArr.find((el) => item === el.value)) {
|
||||||
dispatch(selectedItems([...itemsArr, { id, value: item, label: item }]))
|
dispatch(selectedItems([...itemsArr, { id, value: item, label: item }]))
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
let classes
|
let classes;
|
||||||
|
|
||||||
dataTags.forEach((el) => {
|
dataTags.forEach((el) => {
|
||||||
if (el.name === 'skills_back') {
|
if (el.name === 'skills_back') {
|
||||||
@ -81,7 +78,7 @@ const OutstaffingBlock = ({
|
|||||||
} else if (el.name === 'skills_front') {
|
} else if (el.name === 'skills_front') {
|
||||||
classes = 'front'
|
classes = 'front'
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OutsideClickHandler
|
<OutsideClickHandler
|
||||||
@ -104,7 +101,6 @@ const OutstaffingBlock = ({
|
|||||||
positionId,
|
positionId,
|
||||||
isSelected,
|
isSelected,
|
||||||
onSelect,
|
onSelect,
|
||||||
history,
|
|
||||||
role
|
role
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -136,6 +132,6 @@ const OutstaffingBlock = ({
|
|||||||
</div>
|
</div>
|
||||||
</OutsideClickHandler>
|
</OutsideClickHandler>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default OutstaffingBlock
|
export default OutstaffingBlock
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
|
||||||
import {auth, getProfileInfo, setProfileInfo} from "../../redux/outstaffingSlice";
|
|
||||||
import {useDispatch, useSelector} from "react-redux";
|
|
||||||
import {Loader} from '../Loader/Loader'
|
|
||||||
import {getRole} from "../../redux/roleSlice";
|
|
||||||
import {useHistory, NavLink} from "react-router-dom";
|
|
||||||
import {fetchGet} from "../../server/server";
|
|
||||||
|
|
||||||
import './profileHeader.scss'
|
|
||||||
|
|
||||||
export const ProfileHeader = () => {
|
|
||||||
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const userRole = useSelector(getRole);
|
|
||||||
const profileInfo = useSelector(getProfileInfo)
|
|
||||||
const history = useHistory();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchGet({
|
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile/${localStorage.getItem('cardId')}`,
|
|
||||||
}).then((profileInfo) => {
|
|
||||||
dispatch(setProfileInfo(profileInfo))
|
|
||||||
})
|
|
||||||
}, [])
|
|
||||||
return(
|
|
||||||
<header className='profileHeader'>
|
|
||||||
<div className='profileHeader__head'>
|
|
||||||
<div className='profileHeader__container'>
|
|
||||||
<h2 className='profileHeader__title'>itguild.<span>для разработчиков</span></h2>
|
|
||||||
<button onClick={() => {
|
|
||||||
setIsLoggingOut(true);
|
|
||||||
localStorage.clear();
|
|
||||||
dispatch(auth(false));
|
|
||||||
setIsLoggingOut(false);
|
|
||||||
history.push(userRole === 'ROLE_DEV' ? '/authdev' : '/auth')
|
|
||||||
}}
|
|
||||||
className='profileHeader__logout'>
|
|
||||||
{isLoggingOut ? <Loader/> : 'Выйти'}{' '}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='profileHeader__info'>
|
|
||||||
<div className='profileHeader__container'>
|
|
||||||
<nav className='profileHeader__nav'>
|
|
||||||
<NavLink to={'/summary'}>Резюме</NavLink>
|
|
||||||
<NavLink to={'/profile'}>Отчетность</NavLink>
|
|
||||||
<a>Трекер</a>
|
|
||||||
<a>Выплаты</a>
|
|
||||||
<a>Настройки</a>
|
|
||||||
</nav>
|
|
||||||
<div className='profileHeader__personalInfo'>
|
|
||||||
<h3 className='profileHeader__personalInfoName'>{profileInfo.fio}</h3>
|
|
||||||
<img src={profileInfo.photo} className='profileHeader__personalInfoAvatar' />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
)
|
|
||||||
}
|
|
71
src/components/ProfileHeader/ProfileHeader.js
Normal file
71
src/components/ProfileHeader/ProfileHeader.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import React, {useEffect, useState} from 'react';
|
||||||
|
import {useNavigate, NavLink} from "react-router-dom";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
|
||||||
|
import {Loader} from '../Loader/Loader'
|
||||||
|
|
||||||
|
import {auth, getProfileInfo, setProfileInfo} from "../../redux/outstaffingSlice";
|
||||||
|
import {getRole} from "../../redux/roleSlice";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import './profileHeader.scss'
|
||||||
|
import {useRequest} from "../../hooks/useRequest";
|
||||||
|
|
||||||
|
|
||||||
|
export const ProfileHeader = () => {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
const {apiRequest} = useRequest();
|
||||||
|
|
||||||
|
const userRole = useSelector(getRole);
|
||||||
|
const profileInfo = useSelector(getProfileInfo);
|
||||||
|
|
||||||
|
const [isLoggingOut, setIsLoggingOut] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
apiRequest(`/api/profile/${localStorage.getItem('cardId')}`)
|
||||||
|
.then((profileInfo) =>
|
||||||
|
dispatch(setProfileInfo(profileInfo))
|
||||||
|
);
|
||||||
|
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const handler = () => {
|
||||||
|
setIsLoggingOut(true);
|
||||||
|
localStorage.clear();
|
||||||
|
dispatch(auth(false));
|
||||||
|
setIsLoggingOut(false);
|
||||||
|
navigate(userRole === 'ROLE_DEV' ? '/authdev' : '/auth')
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<header className='profileHeader'>
|
||||||
|
<div className='profileHeader__head'>
|
||||||
|
<div className='profileHeader__container'>
|
||||||
|
<h2 className='profileHeader__title'>itguild.<span>для разработчиков</span></h2>
|
||||||
|
<button onClick={handler} className='profileHeader__logout'>
|
||||||
|
{isLoggingOut ? <Loader/> : 'Выйти'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='profileHeader__info'>
|
||||||
|
<div className='profileHeader__container'>
|
||||||
|
<nav className='profileHeader__nav'>
|
||||||
|
<NavLink to={'/summary'}>Резюме</NavLink>
|
||||||
|
<NavLink to={'/profile'}>Отчетность</NavLink>
|
||||||
|
<NavLink to={'/profile'}>Трекер</NavLink>
|
||||||
|
<NavLink to={'/profile'}>Выплаты</NavLink>
|
||||||
|
<NavLink to={'/profile'}>Настройки</NavLink>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div className='profileHeader__personalInfo'>
|
||||||
|
<h3 className='profileHeader__personalInfoName'>{profileInfo.fio}</h3>
|
||||||
|
<img src={profileInfo.photo} className='profileHeader__personalInfoAvatar' alt='avatar'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
)
|
||||||
|
};
|
@ -8,16 +8,16 @@ export const ProtectedRoute = ({ component: Component, ...rest }) => {
|
|||||||
const existingToken = localStorage.getItem('auth_token')
|
const existingToken = localStorage.getItem('auth_token')
|
||||||
const expiresAt = localStorage.getItem('access_token_expired_at')
|
const expiresAt = localStorage.getItem('access_token_expired_at')
|
||||||
|
|
||||||
const isTokenAlive = (existingToken && expiresAt && new Date(expiresAt).getTime() > (new Date()).getTime());
|
const isTokenAlive = !isAuth && (existingToken && expiresAt && new Date(expiresAt).getTime() > (new Date()).getTime());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
{...rest}
|
{...rest}
|
||||||
render={props =>
|
render={props =>
|
||||||
( isAuth || isTokenAlive) ? (
|
// ( isAuth || isTokenAlive) ? (
|
||||||
<Component {...props} />
|
<Component {...props} />
|
||||||
) : <Redirect to='/auth' />
|
// ) : <Redirect to='/auth' />
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
};
|
@ -1,7 +1,7 @@
|
|||||||
import React, {useState} from 'react'
|
import React, {useState} from 'react'
|
||||||
import {useSelector, useDispatch} from 'react-redux'
|
import {useSelector, useDispatch} from 'react-redux'
|
||||||
import {fetchPost} from '../../server/server'
|
import {fetchPost} from '../../server/server'
|
||||||
import {useHistory, useParams, Redirect, Link} from 'react-router-dom'
|
import {useNavigate, useParams, Redirect, Link} from 'react-router-dom'
|
||||||
import {Loader} from '../Loader/Loader'
|
import {Loader} from '../Loader/Loader'
|
||||||
import {auth} from '../../redux/outstaffingSlice'
|
import {auth} from '../../redux/outstaffingSlice'
|
||||||
import {getReportDate} from '../../redux/reportSlice'
|
import {getReportDate} from '../../redux/reportSlice'
|
||||||
@ -28,7 +28,7 @@ const getCreatedDate = (day) => {
|
|||||||
|
|
||||||
const ReportForm = () => {
|
const ReportForm = () => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const reportDate = useSelector(getReportDate);
|
const reportDate = useSelector(getReportDate);
|
||||||
const role = useSelector(getRole);
|
const role = useSelector(getRole);
|
||||||
|
|
||||||
@ -153,7 +153,6 @@ const ReportForm = () => {
|
|||||||
<button className='report-form__footer-btn' onClick={() => {
|
<button className='report-form__footer-btn' onClick={() => {
|
||||||
fetchPost({
|
fetchPost({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/reports/create`,
|
link: `${process.env.REACT_APP_API_URL}/api/reports/create`,
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
body: {
|
body: {
|
||||||
tasks: inputs,
|
tasks: inputs,
|
||||||
|
@ -12,38 +12,37 @@ import {
|
|||||||
auth
|
auth
|
||||||
} from '../../redux/outstaffingSlice'
|
} from '../../redux/outstaffingSlice'
|
||||||
import { fetchGet } from '../../server/server'
|
import { fetchGet } from '../../server/server'
|
||||||
import { useHistory } from 'react-router-dom'
|
|
||||||
import { getRole } from '../../redux/roleSlice'
|
import { getRole } from '../../redux/roleSlice'
|
||||||
|
|
||||||
const TagSelect = () => {
|
const TagSelect = () => {
|
||||||
const history = useHistory
|
|
||||||
const role = useSelector(getRole)
|
|
||||||
const [searchLoading, setSearchLoading] = useState(false)
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
|
|
||||||
const itemsArr = useSelector(selectItems)
|
const role = useSelector(getRole);
|
||||||
|
const [searchLoading, setSearchLoading] = useState(false);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
const tagsArr = useSelector(selectTags)
|
const itemsArr = useSelector(selectItems);
|
||||||
|
|
||||||
|
const tagsArr = useSelector(selectTags);
|
||||||
|
|
||||||
const handleSubmit = ({ dispatch, setSearchLoading }) => {
|
const handleSubmit = ({ dispatch, setSearchLoading }) => {
|
||||||
setSearchLoading(true)
|
setSearchLoading(true);
|
||||||
|
|
||||||
dispatch(setPositionId(null))
|
dispatch(setPositionId(null));
|
||||||
const filterItemsId = itemsArr.map((item) => item.id).join()
|
const filterItemsId = itemsArr.map((item) => item.id).join();
|
||||||
|
|
||||||
fetchGet({
|
fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile?skills=`,
|
link: `${process.env.REACT_APP_API_URL}/api/profile?skills=`,
|
||||||
params: filterItemsId,
|
params: filterItemsId,
|
||||||
history,
|
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((el) => {
|
}).then((el) => {
|
||||||
dispatch(filteredCandidates(el))
|
dispatch(filteredCandidates(el));
|
||||||
setSearchLoading(false)
|
setSearchLoading(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
// dispatch(selectedItems([]));
|
// dispatch(selectedItems([]));
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -85,6 +84,6 @@ const TagSelect = () => {
|
|||||||
</section>
|
</section>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default TagSelect
|
export default TagSelect
|
||||||
|
@ -5,20 +5,20 @@ import {fetchGet} from "../../../server/server";
|
|||||||
|
|
||||||
|
|
||||||
export const Results = () => {
|
export const Results = () => {
|
||||||
const result = useSelector(selectResult)
|
const result = useSelector(selectResult);
|
||||||
const test = useSelector(selectedTest)
|
const test = useSelector(selectedTest);
|
||||||
const [maxScore, setMaxScore] = useState('')
|
const [maxScore, setMaxScore] = useState('');
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(async () => {
|
useEffect(async () => {
|
||||||
dispatch(fetchResultTest(test.uuid))
|
dispatch(fetchResultTest(test.uuid));
|
||||||
const response = await fetchGet({
|
const response = await fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/user-questionnaire/get-points-number?user_questionnaire_uuid=${test.uuid}`,
|
link: `${process.env.REACT_APP_API_URL}/api/user-questionnaire/get-points-number?user_questionnaire_uuid=${test.uuid}`,
|
||||||
Origin: `${process.env.REACT_APP_BASE_URL}`,
|
Origin: `${process.env.REACT_APP_BASE_URL}`,
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
setMaxScore(response.sum_point)
|
setMaxScore(response.sum_point)
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'result _container'}>
|
<div className={'result _container'}>
|
||||||
|
@ -1,59 +1,62 @@
|
|||||||
import React, {useEffect} from 'react'
|
import React, {useEffect, useState} from 'react'
|
||||||
import {useHistory} from "react-router"
|
import { useNavigate} from "react-router-dom"
|
||||||
import {CodeSnippetlighter} from '../../../pages/CodeSnippetPage'
|
import {useSelector, useDispatch} from 'react-redux'
|
||||||
import './quiz.scss'
|
|
||||||
import {useDispatch} from 'react-redux'
|
|
||||||
import {useState} from 'react'
|
|
||||||
import {
|
import {
|
||||||
fetchGetAnswers,
|
fetchGetAnswers,
|
||||||
selectAnswer,
|
selectAnswer,
|
||||||
selectedTest
|
selectedTest
|
||||||
} from '../../../redux/quizSlice'
|
} from '../../../redux/quizSlice'
|
||||||
import {useSelector} from 'react-redux'
|
|
||||||
import {Progressbar} from './ProgressbarQuiz'
|
import {Progressbar} from './ProgressbarQuiz'
|
||||||
import {fetchUserAnswersMany, fetchUserAnswerOne} from './../../../redux/quizSlice'
|
|
||||||
import {GetOptionTask} from './GetOptionTask'
|
import {GetOptionTask} from './GetOptionTask'
|
||||||
|
|
||||||
|
import {fetchUserAnswersMany, fetchUserAnswerOne} from './../../../redux/quizSlice'
|
||||||
|
|
||||||
import {fetchGet} from "../../../server/server";
|
import {fetchGet} from "../../../server/server";
|
||||||
|
|
||||||
|
import './quiz.scss'
|
||||||
|
|
||||||
export const TaskQuiz = () => {
|
export const TaskQuiz = () => {
|
||||||
|
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch();
|
||||||
const listAnswers = useSelector(selectAnswer)
|
|
||||||
const dataTest = useSelector(selectedTest)
|
|
||||||
const [index, setIndex] = useState(0);
|
|
||||||
const [checkedValues, setCheckedValues] = useState([])
|
|
||||||
const [stripValue, setStripValue] = useState(0);
|
|
||||||
const [inputValue, setInputValue] = useState('')
|
|
||||||
const id = localStorage.getItem('id');
|
|
||||||
const [questions, setQuestions] = useState([])
|
|
||||||
|
|
||||||
useEffect(async () => {
|
const listAnswers = useSelector(selectAnswer);
|
||||||
const response = await fetchGet({
|
const dataTest = useSelector(selectedTest);
|
||||||
|
|
||||||
|
const [index, setIndex] = useState(0);
|
||||||
|
const [checkedValues, setCheckedValues] = useState([]);
|
||||||
|
const [stripValue, setStripValue] = useState(0);
|
||||||
|
const [inputValue, setInputValue] = useState('');
|
||||||
|
const [questions, setQuestions] = useState([]);
|
||||||
|
|
||||||
|
const id = localStorage.getItem('id');
|
||||||
|
|
||||||
|
useEffect( () => {
|
||||||
|
const response = fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/question/get-questions?uuid=${dataTest.uuid}`,
|
link: `${process.env.REACT_APP_API_URL}/api/question/get-questions?uuid=${dataTest.uuid}`,
|
||||||
Origin: `${process.env.REACT_APP_BASE_URL}`,
|
Origin: `${process.env.REACT_APP_BASE_URL}`,
|
||||||
}
|
}
|
||||||
)
|
);
|
||||||
setQuestions(response)
|
setQuestions(response);
|
||||||
dispatch(fetchGetAnswers(response[0].id))
|
dispatch(fetchGetAnswers(response[0].id));
|
||||||
setStripValue((+index + 1) * 100 / response.length)
|
setStripValue((+index + 1) * 100 / response.length)
|
||||||
}, [dispatch])
|
}, [dispatch]);
|
||||||
|
|
||||||
|
|
||||||
const nextQuestion = async (e) => {
|
const nextQuestion = async (e) => {
|
||||||
e.preventDefault()
|
e.preventDefault();
|
||||||
|
|
||||||
//Проверка на валидацию ответов
|
//Проверка на валидацию ответов
|
||||||
if (checkedValues.length || inputValue) {
|
if (checkedValues.length || inputValue) {
|
||||||
switch (questions[index].question_type_id) {
|
switch (questions[index].question_type_id) {
|
||||||
case '3':
|
case '3':
|
||||||
dispatch(fetchUserAnswersMany(checkedValues))
|
dispatch(fetchUserAnswersMany(checkedValues));
|
||||||
break;
|
break;
|
||||||
case '2':
|
case '2':
|
||||||
case '1':
|
case '1':
|
||||||
case '4':
|
case '4':
|
||||||
dispatch(fetchUserAnswerOne(checkedValues))
|
dispatch(fetchUserAnswerOne(checkedValues));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -61,20 +64,20 @@ export const TaskQuiz = () => {
|
|||||||
|
|
||||||
//Проверка на существование следующего запроса
|
//Проверка на существование следующего запроса
|
||||||
if (index < questions.length - 1) {
|
if (index < questions.length - 1) {
|
||||||
await dispatch(fetchGetAnswers(questions[index + 1].id))
|
await dispatch(fetchGetAnswers(questions[index + 1].id));
|
||||||
setIndex(prev => prev >= questions.length - 1 ? prev : prev + 1)
|
setIndex(prev => prev >= questions.length - 1 ? prev : prev + 1);
|
||||||
setStripValue((prev => prev + (100 / questions.length)))
|
setStripValue((prev => prev + (100 / questions.length)));
|
||||||
setCheckedValues([]);
|
setCheckedValues([]);
|
||||||
setInputValue('')
|
setInputValue('')
|
||||||
} else {
|
} else {
|
||||||
history.push(`/quiz-result`)
|
navigate(`/quiz-result`);
|
||||||
alert("Тест пройден!")
|
alert("Тест пройден!")
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
alert("Вы не ответили на вопрос")
|
alert("Вы не ответили на вопрос")
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const handleChange = (e) => {
|
const handleChange = (e) => {
|
||||||
const checked = e.target.checked;
|
const checked = e.target.checked;
|
||||||
@ -86,8 +89,8 @@ export const TaskQuiz = () => {
|
|||||||
question_id: questions[index].id,
|
question_id: questions[index].id,
|
||||||
response_body: e.target.value
|
response_body: e.target.value
|
||||||
}]) :
|
}]) :
|
||||||
setCheckedValues(prev => [...prev.filter(item => item.response_body !== e.target.value)])
|
setCheckedValues(prev => [...prev.filter(item => item.response_body !== e.target.value)]);
|
||||||
break
|
break;
|
||||||
case '1':
|
case '1':
|
||||||
case '2':
|
case '2':
|
||||||
case '4':
|
case '4':
|
||||||
@ -146,4 +149,4 @@ export const TaskQuiz = () => {
|
|||||||
</div>
|
</div>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
@ -18,3 +18,20 @@ export function transformHtml(text) {
|
|||||||
);
|
);
|
||||||
return {__html: finalHtml.join('')}
|
return {__html: finalHtml.join('')}
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// export const setToken = () => {
|
||||||
|
// const url = new URL(window.location.href);
|
||||||
|
// const urlT = url.searchParams.get("token");
|
||||||
|
// urlT ? sessionStorage.setItem('token', 'Bearer ' + urlT) : '';
|
||||||
|
// const tParam = urlT || sessionStorage.getItem('token');
|
||||||
|
// return tParam ? {"Authorization": tParam} : false
|
||||||
|
//
|
||||||
|
// };
|
||||||
|
|
||||||
|
export const getToken = () => {
|
||||||
|
const tParam = `Bearer ${localStorage.getItem('auth_token')}`
|
||||||
|
|
||||||
|
return tParam ? {Authorization: tParam} : {};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const urlHasParams = (url) => url.indexOf('?') > 0 ? `${url}&${window.location.search.substr(1)}` : `${url}${window.location.search}`;
|
||||||
|
20
src/hooks/useLogout.js
Normal file
20
src/hooks/useLogout.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React from "react";
|
||||||
|
import {useDispatch, useSelector} from "react-redux";
|
||||||
|
import {getRole} from "../redux/roleSlice";
|
||||||
|
import {useNavigate} from "react-router-dom";
|
||||||
|
import {auth} from "../redux/outstaffingSlice";
|
||||||
|
|
||||||
|
export const useLogout = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const userRole = useSelector(getRole);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
localStorage.clear();
|
||||||
|
dispatch(auth(false));
|
||||||
|
console.log('logout')
|
||||||
|
navigate(userRole === 'ROLE_DEV' ? '/authdev' : '/auth')
|
||||||
|
};
|
||||||
|
|
||||||
|
return {logout}
|
||||||
|
};
|
64
src/hooks/useRequest.js
Normal file
64
src/hooks/useRequest.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import React from "react";
|
||||||
|
import axios from 'axios';
|
||||||
|
import {getToken, urlHasParams} from "../helper";
|
||||||
|
import {useNavigate} from "react-router";
|
||||||
|
import {useLogout} from "./useLogout";
|
||||||
|
|
||||||
|
|
||||||
|
const instance = axios.create({
|
||||||
|
baseURL: process.env.REACT_APP_API_URL,
|
||||||
|
validateStatus(status) {
|
||||||
|
return status;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const useRequest = () => {
|
||||||
|
|
||||||
|
|
||||||
|
const {logout} = useLogout();
|
||||||
|
|
||||||
|
const apiRequest = (url, {
|
||||||
|
method = 'get', params, data,
|
||||||
|
headers = {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
} = {}) => {
|
||||||
|
const fullHeaders = {...headers, ...getToken()};
|
||||||
|
let urWithParams = urlHasParams(url);
|
||||||
|
|
||||||
|
|
||||||
|
return instance
|
||||||
|
.request({
|
||||||
|
url: urWithParams,
|
||||||
|
method,
|
||||||
|
params,
|
||||||
|
data,
|
||||||
|
headers: {...fullHeaders},
|
||||||
|
})
|
||||||
|
.then(response => new Promise(resolve => {
|
||||||
|
if (response.data.redirect || response.status === 401) {
|
||||||
|
console.log(response, 'LOGUTATAT')
|
||||||
|
logout()
|
||||||
|
}
|
||||||
|
return resolve(response)
|
||||||
|
}))
|
||||||
|
.then(response => new Promise(resolve => resolve(response.data)))
|
||||||
|
};
|
||||||
|
|
||||||
|
const RequestError = (code, msg, data) => {
|
||||||
|
const description = msg ? `- ${msg}` : '';
|
||||||
|
|
||||||
|
this.name = 'RequestError';
|
||||||
|
this.message = `API returned: ${code}${description}.`;
|
||||||
|
this.code = code;
|
||||||
|
this.description = msg;
|
||||||
|
this.data = data;
|
||||||
|
};
|
||||||
|
|
||||||
|
RequestError.prototype = Object.create(Error.prototype);
|
||||||
|
RequestError.prototype.constructor = RequestError;
|
||||||
|
|
||||||
|
|
||||||
|
return {apiRequest}
|
||||||
|
};
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { AuthBox } from '../AuthBox/AuthBox'
|
import { AuthBox } from '../../components/AuthBox/AuthBox'
|
||||||
|
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import arrow from '../../images/arrow__login_page.png'
|
import arrow from '../../images/arrow__login_page.png'
|
||||||
@ -10,16 +10,18 @@ import text from '../../images/Body_Text.png'
|
|||||||
import vector from '../../images/Vector_Smart_Object.png'
|
import vector from '../../images/Vector_Smart_Object.png'
|
||||||
|
|
||||||
import { selectAuth } from '../../redux/outstaffingSlice'
|
import { selectAuth } from '../../redux/outstaffingSlice'
|
||||||
import { Redirect } from 'react-router-dom'
|
import { useNavigate} from 'react-router-dom'
|
||||||
import { Footer } from '../Footer/Footer'
|
import { Footer } from '../../components/Footer/Footer'
|
||||||
|
|
||||||
import './authForDevelopers.scss'
|
import './authForDevelopers.scss'
|
||||||
|
|
||||||
const AuthForDevelopers = () => {
|
const AuthForDevelopers = () => {
|
||||||
const isAuth = useSelector(selectAuth)
|
|
||||||
|
const isAuth = useSelector(selectAuth);
|
||||||
|
let navigate = useNavigate();
|
||||||
|
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
return <Redirect to='/profile' />
|
navigate('/profile')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -89,6 +91,6 @@ const AuthForDevelopers = () => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default AuthForDevelopers
|
export default AuthForDevelopers
|
@ -7,18 +7,19 @@ 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 { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { selectAuth } from '../../redux/outstaffingSlice'
|
import { selectAuth } from '../../redux/outstaffingSlice'
|
||||||
import { Redirect } from 'react-router-dom'
|
import { useNavigate} from 'react-router-dom'
|
||||||
|
|
||||||
import { Footer } from '../Footer/Footer'
|
import { Footer } from '../../components/Footer/Footer'
|
||||||
import { AuthBox } from '../AuthBox/AuthBox'
|
import { AuthBox } from '../../components/AuthBox/AuthBox'
|
||||||
|
|
||||||
import './authForPartners.scss'
|
import './authForPartners.scss'
|
||||||
|
|
||||||
const AuthForPartners = () => {
|
const AuthForPartners = () => {
|
||||||
const isAuth = useSelector(selectAuth)
|
const isAuth = useSelector(selectAuth);
|
||||||
|
let navigate = useNavigate();
|
||||||
|
|
||||||
if (isAuth) {
|
if (isAuth) {
|
||||||
return <Redirect to='/' />
|
navigate('/')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -81,6 +82,6 @@ const AuthForPartners = () => {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
};
|
||||||
|
|
||||||
export default AuthForPartners
|
export default AuthForPartners
|
@ -1,8 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import AuthForDevelopers from '../components/Auth/AuthForDevelopers';
|
|
||||||
|
|
||||||
const AuthPageForDevelopers = () => {
|
|
||||||
return <AuthForDevelopers />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthPageForDevelopers;
|
|
@ -1,8 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import AuthForPartners from '../components/Auth/AuthForPartners';
|
|
||||||
|
|
||||||
const AuthPageForPartners = () => {
|
|
||||||
return <AuthForPartners />;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AuthPageForPartners;
|
|
@ -1,11 +1,11 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useHistory } from 'react-router';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { WithLogout } from '../hoc/withLogout';
|
import { WithLogout } from '../hoc/withLogout';
|
||||||
import Calendar from '../components/Calendar/Calendar';
|
import Calendar from '../components/Calendar/Calendar';
|
||||||
|
|
||||||
const CalendarPage = () => {
|
const CalendarPage = () => {
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
return <WithLogout><Calendar onSelect={() => { history.push('/report/0') }} /></WithLogout>;
|
return <WithLogout><Calendar onSelect={() => { navigate('/report/0') }} /></WithLogout>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default CalendarPage;
|
export default CalendarPage;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {useDispatch, useSelector} from 'react-redux'
|
import {useDispatch, useSelector} from 'react-redux'
|
||||||
import { useHistory, useParams } from 'react-router-dom'
|
import {useParams, useNavigate} from 'react-router-dom'
|
||||||
import {
|
import {
|
||||||
currentCandidate,
|
currentCandidate,
|
||||||
selectCurrentCandidate,
|
selectCurrentCandidate,
|
||||||
@ -20,22 +20,23 @@ import telegramIcon from '../images/telegram-icon.svg'
|
|||||||
import './formPage.scss'
|
import './formPage.scss'
|
||||||
import {getRole} from '../redux/roleSlice'
|
import {getRole} from '../redux/roleSlice'
|
||||||
|
|
||||||
const goBack = (history) => {
|
|
||||||
history.goBack()
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormPage = () => {
|
const FormPage = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const candidate = useSelector(selectCurrentCandidate);
|
const candidate = useSelector(selectCurrentCandidate);
|
||||||
const role = useSelector(getRole);
|
const role = useSelector(getRole);
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
navigate(-1)
|
||||||
|
};
|
||||||
|
|
||||||
if (!candidate.id) {
|
if (!candidate.id) {
|
||||||
fetchGet({
|
fetchGet({
|
||||||
link: `${process.env.REACT_APP_API_URL}/api/profile/`,
|
link: `${process.env.REACT_APP_API_URL}/api/profile/`,
|
||||||
params: Number(params.id),
|
params: Number(params.id),
|
||||||
history,
|
navigate,
|
||||||
role,
|
role,
|
||||||
logout: () => dispatch(auth(false))
|
logout: () => dispatch(auth(false))
|
||||||
}).then((el) => dispatch(currentCandidate(el)))
|
}).then((el) => dispatch(currentCandidate(el)))
|
||||||
@ -45,7 +46,7 @@ const FormPage = () => {
|
|||||||
<WithLogout>
|
<WithLogout>
|
||||||
<div className='form-page'>
|
<div className='form-page'>
|
||||||
<div className='form-page__back'>
|
<div className='form-page__back'>
|
||||||
<div className='form-page__arrow' onClick={() => goBack(history)}>
|
<div className='form-page__arrow' onClick={goBack}>
|
||||||
<div className='form-page__arrow-img'>
|
<div className='form-page__arrow-img'>
|
||||||
<img src={arrow} alt=''/>
|
<img src={arrow} alt=''/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import {useSelector} from "react-redux";
|
|
||||||
import {getProfileInfo} from "../redux/outstaffingSlice";
|
|
||||||
import {ProfileHeader} from "../components/Profile/ProfileHeader";
|
|
||||||
import {Link} from "react-router-dom";
|
|
||||||
import {Footer} from "../components/Footer/Footer";
|
|
||||||
|
|
||||||
import reportsIcon from "../images/reports.png"
|
|
||||||
import summaryIcon from "../images/summaryIcon.png"
|
|
||||||
import timerIcon from "../images/timerIcon.png"
|
|
||||||
import paymentIcon from "../images/paymentIcon.png"
|
|
||||||
import settingIcon from "../images/settingIcon.png"
|
|
||||||
import rightArrow from "../images/arrowRight.png"
|
|
||||||
|
|
||||||
import '../components/Profile/profile.scss'
|
|
||||||
|
|
||||||
export const Profile = () => {
|
|
||||||
const profileInfo = useSelector(getProfileInfo);
|
|
||||||
return(
|
|
||||||
<div className='profile'>
|
|
||||||
<ProfileHeader/>
|
|
||||||
<div className='container'>
|
|
||||||
<h2 className='profile__title'>Добрый день, <span>{profileInfo.fio}</span></h2>
|
|
||||||
<div className='summary__info'>
|
|
||||||
<div className='summary__person'>
|
|
||||||
<img src={profileInfo.photo} className='summary__avatar' alt='avatar'/>
|
|
||||||
<p className='summary__name'>{profileInfo.fio} {profileInfo.specification}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className='profile__items'>
|
|
||||||
<Link to={'/ProfileCalendar'} className='item'>
|
|
||||||
<div className='item__about'>
|
|
||||||
<img src={reportsIcon} alt='report'/>
|
|
||||||
<h3>Ваша отчетность</h3>
|
|
||||||
</div>
|
|
||||||
<div className='item__info'>
|
|
||||||
<p><span>У вас 122 часа</span><br/> отработанных в этом месяце</p>
|
|
||||||
<div className='item__infoLink'>
|
|
||||||
<img src={rightArrow} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link to={'/summary'} className='item'>
|
|
||||||
<div className='item__about'>
|
|
||||||
<img src={summaryIcon} alt='summary'/>
|
|
||||||
<h3>Данные и резюме</h3>
|
|
||||||
</div>
|
|
||||||
<div className='item__info'>
|
|
||||||
<p>Ваше резюме<br/><span>заполнено</span></p>
|
|
||||||
<div className='item__infoLink'>
|
|
||||||
<img src={rightArrow} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link to={'/profile'} className='item'>
|
|
||||||
<div className='item__about'>
|
|
||||||
<img src={timerIcon} alt='timer'/>
|
|
||||||
<h3>Трекер времени</h3>
|
|
||||||
</div>
|
|
||||||
<div className='item__info'>
|
|
||||||
<p>Сколько времени занимает<br/> выполнение задач</p>
|
|
||||||
<div className='item__infoLink'>
|
|
||||||
<img src={rightArrow} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link to={'/profile'} className='item'>
|
|
||||||
<div className='item__about'>
|
|
||||||
<img src={paymentIcon} alt='payment'/>
|
|
||||||
<h3>Выплаты</h3>
|
|
||||||
</div>
|
|
||||||
<div className='item__info'>
|
|
||||||
<p>У вас <span>подтвержден</span><br/> статус самозанятого</p>
|
|
||||||
<div className='item__infoLink'>
|
|
||||||
<img src={rightArrow} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
<Link to={'/profile'} className='item'>
|
|
||||||
<div className='item__about'>
|
|
||||||
<img src={settingIcon} alt='settings'/>
|
|
||||||
<h3>Настройки аккаунта</h3>
|
|
||||||
</div>
|
|
||||||
<div className='item__info'>
|
|
||||||
<p>Перейдите чтобы начать<br/> редактирование</p>
|
|
||||||
<div className='item__infoLink'>
|
|
||||||
<img src={rightArrow} alt='arrow'/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Footer/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
};
|
|
100
src/pages/Profile/Profile.js
Normal file
100
src/pages/Profile/Profile.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
import {Link} from "react-router-dom";
|
||||||
|
|
||||||
|
import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader";
|
||||||
|
import {Footer} from "../../components/Footer/Footer";
|
||||||
|
|
||||||
|
import {getProfileInfo} from "../../redux/outstaffingSlice";
|
||||||
|
|
||||||
|
import reportsIcon from "../../images/reports.png"
|
||||||
|
import summaryIcon from "../../images/summaryIcon.png"
|
||||||
|
import timerIcon from "../../images/timerIcon.png"
|
||||||
|
import paymentIcon from "../../images/paymentIcon.png"
|
||||||
|
import settingIcon from "../../images/settingIcon.png"
|
||||||
|
import rightArrow from "../../images/arrowRight.png"
|
||||||
|
|
||||||
|
import './profile.scss'
|
||||||
|
|
||||||
|
export const Profile = () => {
|
||||||
|
|
||||||
|
const profileInfo = useSelector(getProfileInfo);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='profile'>
|
||||||
|
<ProfileHeader/>
|
||||||
|
<div className='container'>
|
||||||
|
<h2 className='profile__title'>Добрый день, <span>{profileInfo.fio}</span></h2>
|
||||||
|
<div className='summary__info'>
|
||||||
|
<div className='summary__person'>
|
||||||
|
<img src={profileInfo.photo} className='summary__avatar' alt='avatar'/>
|
||||||
|
<p className='summary__name'>{profileInfo.fio} {profileInfo.specification}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className='profile__items'>
|
||||||
|
<Link to={'/calendar'} className='item'>
|
||||||
|
<div className='item__about'>
|
||||||
|
<img src={reportsIcon} alt='report'/>
|
||||||
|
<h3>Ваша отчетность</h3>
|
||||||
|
</div>
|
||||||
|
<div className='item__info'>
|
||||||
|
<p><span>У вас 122 часа</span><br/> отработанных в этом месяце</p>
|
||||||
|
<div className='item__infoLink'>
|
||||||
|
<img src={rightArrow} alt='arrow'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link to={'/summary'} className='item'>
|
||||||
|
<div className='item__about'>
|
||||||
|
<img src={summaryIcon} alt='summary'/>
|
||||||
|
<h3>Данные и резюме</h3>
|
||||||
|
</div>
|
||||||
|
<div className='item__info'>
|
||||||
|
<p>Ваше резюме<br/><span>заполнено</span></p>
|
||||||
|
<div className='item__infoLink'>
|
||||||
|
<img src={rightArrow} alt='arrow'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link to={'/profile'} className='item'>
|
||||||
|
<div className='item__about'>
|
||||||
|
<img src={timerIcon} alt='timer'/>
|
||||||
|
<h3>Трекер времени</h3>
|
||||||
|
</div>
|
||||||
|
<div className='item__info'>
|
||||||
|
<p>Сколько времени занимает<br/> выполнение задач</p>
|
||||||
|
<div className='item__infoLink'>
|
||||||
|
<img src={rightArrow} alt='arrow'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link to={'/profile'} className='item'>
|
||||||
|
<div className='item__about'>
|
||||||
|
<img src={paymentIcon} alt='payment'/>
|
||||||
|
<h3>Выплаты</h3>
|
||||||
|
</div>
|
||||||
|
<div className='item__info'>
|
||||||
|
<p>У вас <span>подтвержден</span><br/> статус самозанятого</p>
|
||||||
|
<div className='item__infoLink'>
|
||||||
|
<img src={rightArrow} alt='arrow'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
<Link to={'/profile'} className='item'>
|
||||||
|
<div className='item__about'>
|
||||||
|
<img src={settingIcon} alt='settings'/>
|
||||||
|
<h3>Настройки аккаунта</h3>
|
||||||
|
</div>
|
||||||
|
<div className='item__info'>
|
||||||
|
<p>Перейдите чтобы начать<br/> редактирование</p>
|
||||||
|
<div className='item__infoLink'>
|
||||||
|
<img src={rightArrow} alt='arrow'/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Footer/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
};
|
@ -1,16 +1,19 @@
|
|||||||
import React, {useEffect, useState} from 'react';
|
import React, {useEffect, useState} from 'react';
|
||||||
import {ProfileHeader} from "../components/Profile/ProfileHeader";
|
import {ProfileHeader} from "../../components/ProfileHeader/ProfileHeader";
|
||||||
import {getProfileInfo} from "../redux/outstaffingSlice";
|
import {getProfileInfo} from "../../redux/outstaffingSlice";
|
||||||
import {useSelector} from "react-redux";
|
import {useSelector} from "react-redux";
|
||||||
import {transformHtml} from "../helper";
|
import {transformHtml} from "../../helper";
|
||||||
import {Footer} from '../components/Footer/Footer'
|
import {Footer} from '../../components/Footer/Footer'
|
||||||
|
|
||||||
|
import arrow from "../../images/right-arrow.png";
|
||||||
|
import rightArrow from "../../images/arrowRight.png"
|
||||||
|
import gitImgItem from "../../images/gitItemImg.png"
|
||||||
|
|
||||||
|
import {fetchGet} from "../../server/server";
|
||||||
|
|
||||||
|
import './summary.scss'
|
||||||
|
|
||||||
import arrow from "../images/right-arrow.png";
|
|
||||||
import rightArrow from "../images/arrowRight.png"
|
|
||||||
import gitImgItem from "../images/gitItemImg.png"
|
|
||||||
|
|
||||||
import '../components/Profile/summary.scss'
|
|
||||||
import {fetchGet} from "../server/server";
|
|
||||||
|
|
||||||
export const Summary = () => {
|
export const Summary = () => {
|
||||||
const profileInfo = useSelector(getProfileInfo);
|
const profileInfo = useSelector(getProfileInfo);
|
@ -1,4 +1,4 @@
|
|||||||
import {Redirect} from "react-router-dom"
|
import {useNavigate} from "react-router-dom"
|
||||||
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
||||||
import {Instruction} from "../../components/features/quiz/Instructions"
|
import {Instruction} from "../../components/features/quiz/Instructions"
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -10,8 +10,9 @@ export const InstructionPage = () => {
|
|||||||
|
|
||||||
const test = useSelector(selectedTest)
|
const test = useSelector(selectedTest)
|
||||||
|
|
||||||
|
let navigate = useNavigate();
|
||||||
if (!test) {
|
if (!test) {
|
||||||
return <Redirect to={'/quiz'} />
|
navigate('/quiz')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -20,4 +21,4 @@ export const InstructionPage = () => {
|
|||||||
<Instruction/>
|
<Instruction/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
@ -1,18 +1,20 @@
|
|||||||
import {Redirect} from "react-router-dom"
|
import React from "react";
|
||||||
|
import {useNavigate} from "react-router-dom"
|
||||||
|
import {useSelector} from "react-redux";
|
||||||
|
|
||||||
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
||||||
import {MyTestsQuiz} from "../../components/features/quiz/MyTestsQuiz"
|
import {MyTestsQuiz} from "../../components/features/quiz/MyTestsQuiz"
|
||||||
import {useSelector} from "react-redux";
|
|
||||||
import {selectedTest, selectPassedTests} from "../../redux/quizSlice";
|
import {selectedTest, selectPassedTests} from "../../redux/quizSlice";
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
|
|
||||||
export const InterjacentPage = () => {
|
export const InterjacentPage = () => {
|
||||||
|
|
||||||
const test = useSelector(selectedTest)
|
const test = useSelector(selectedTest);
|
||||||
const passedTests = useSelector(selectPassedTests)
|
const passedTests = useSelector(selectPassedTests)
|
||||||
|
let navigate = useNavigate();
|
||||||
if (!test) {
|
if (!test) {
|
||||||
return <Redirect to={'/quiz'}/>
|
navigate('/quiz')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -21,4 +23,4 @@ export const InterjacentPage = () => {
|
|||||||
<MyTestsQuiz listTests={passedTests}/>
|
<MyTestsQuiz listTests={passedTests}/>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
};
|
@ -1,4 +1,4 @@
|
|||||||
import {Redirect} from 'react-router-dom'
|
import {useNavigate} from 'react-router-dom'
|
||||||
import {HeaderPageTestsQuiz} from '../../components/features/quiz/HeaderPageTests'
|
import {HeaderPageTestsQuiz} from '../../components/features/quiz/HeaderPageTests'
|
||||||
import {TaskQuiz} from '../../components/features/quiz/Task'
|
import {TaskQuiz} from '../../components/features/quiz/Task'
|
||||||
import {useSelector} from "react-redux";
|
import {useSelector} from "react-redux";
|
||||||
@ -6,11 +6,11 @@ import {selectedTest} from "../../redux/quizSlice";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export const QuizTestPage = () => {
|
export const QuizTestPage = () => {
|
||||||
|
let navigate = useNavigate()
|
||||||
const test = useSelector(selectedTest)
|
const test = useSelector(selectedTest)
|
||||||
|
|
||||||
if (!test) {
|
if (!test) {
|
||||||
return <Redirect to={'/quiz'}/>
|
navigate('/quiz')
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import {Redirect} from "react-router-dom"
|
import {useNavigate} from "react-router-dom"
|
||||||
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
import {HeaderPageTestsQuiz} from "../../components/features/quiz/HeaderPageTests"
|
||||||
import {Results} from "../../components/features/quiz/Results";
|
import {Results} from "../../components/features/quiz/Results";
|
||||||
import {useSelector} from "react-redux";
|
import {useSelector} from "react-redux";
|
||||||
@ -10,8 +10,9 @@ export const ResultPage = () => {
|
|||||||
|
|
||||||
const test = useSelector(selectedTest)
|
const test = useSelector(selectedTest)
|
||||||
|
|
||||||
|
let navigate = useNavigate();
|
||||||
if (!test) {
|
if (!test) {
|
||||||
return <Redirect to={'/quiz'}/>
|
navigate('/quiz')
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
export const withAuthRedirect =
|
export const withAuthRedirect =
|
||||||
(actionCall) =>
|
(actionCall) =>
|
||||||
({ link, params, history, role, logout, body }) => {
|
({ link, params, history, role, logout, body }) => {
|
||||||
const linkWithParams = params
|
// const linkWithParams = params
|
||||||
? `${link}?${new URLSearchParams(params)}`
|
// ? `${link}?${new URLSearchParams(params)}`
|
||||||
: link
|
// : link;
|
||||||
return actionCall(linkWithParams, body)
|
// return actionCall(linkWithParams, body)
|
||||||
.then((res) => {
|
// .then((res) => {
|
||||||
if (res.status && res.status === 401) {
|
// if (res.status && res.status === 401) {
|
||||||
localStorage.clear()
|
// localStorage.clear();
|
||||||
logout && logout()
|
// logout && logout();
|
||||||
history.push(role === 'ROLE_DEV' ? '/authdev' : '/auth')
|
// history.push(role === 'ROLE_DEV' ? '/authdev' : '/auth')
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return res
|
// return res
|
||||||
})
|
// })
|
||||||
.catch((err) => {
|
// .catch((err) => {
|
||||||
localStorage.clear()
|
// localStorage.clear();
|
||||||
logout && logout()
|
// logout && logout();
|
||||||
history.push(role === 'ROLE_DEV' ? '/authdev' : '/auth')
|
// history.push(role === 'ROLE_DEV' ? '/authdev' : '/auth')
|
||||||
})
|
// })
|
||||||
}
|
};
|
||||||
|
@ -19,67 +19,67 @@ import { withAuthRedirect } from './authRedirect'
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
export const fetchAuth = async ({
|
// export const fetchAuth = async ({
|
||||||
username,
|
// username,
|
||||||
password,
|
// password,
|
||||||
dispatch,
|
// dispatch,
|
||||||
catchError
|
// catchError
|
||||||
}) => {
|
// }) => {
|
||||||
const apiURL = process.env.REACT_APP_API_URL;
|
// const apiURL = process.env.REACT_APP_API_URL;
|
||||||
try {
|
// try {
|
||||||
const response = await fetch(`${apiURL}/api/user/login`, {
|
// const response = await fetch(`${apiURL}/api/user/login`, {
|
||||||
method: 'POST',
|
// method: 'POST',
|
||||||
mode: 'cors',
|
// mode: 'cors',
|
||||||
headers: {
|
// headers: {
|
||||||
'Access-Control-Request-Headers': 'authorization',
|
// 'Access-Control-Request-Headers': 'authorization',
|
||||||
'Content-Type': 'application/json'
|
// 'Content-Type': 'application/json'
|
||||||
// Origin: `http://localhost`
|
// // Origin: `http://localhost`
|
||||||
},
|
// },
|
||||||
body: JSON.stringify({
|
// body: JSON.stringify({
|
||||||
username,
|
// username,
|
||||||
password
|
// password
|
||||||
})
|
// })
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
|
// if (!response.ok) {
|
||||||
|
// catchError();
|
||||||
|
// return response.statusText
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// response.json().then((resJSON) => {
|
||||||
|
// localStorage.setItem('auth_token', resJSON.access_token);
|
||||||
|
// localStorage.setItem('id', resJSON.id);
|
||||||
|
// localStorage.setItem('cardId', resJSON.card_id);
|
||||||
|
// localStorage.setItem(
|
||||||
|
// 'access_token_expired_at',
|
||||||
|
// resJSON.access_token_expired_at
|
||||||
|
// );
|
||||||
|
// dispatch(resJSON)
|
||||||
|
// })
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error('Error occured: ', error)
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
if (!response.ok) {
|
// export const fetchReportList = withAuthRedirect(async (link) => {
|
||||||
catchError();
|
// try {
|
||||||
return response.statusText
|
// const response = await fetch(
|
||||||
}
|
// `https://guild.loc/api/reports/index?user_id=26&fromDate=2021-10-18`,
|
||||||
|
// // link,
|
||||||
response.json().then((resJSON) => {
|
// {
|
||||||
localStorage.setItem('auth_token', resJSON.access_token);
|
// method: 'GET',
|
||||||
localStorage.setItem('id', resJSON.id);
|
// headers: {
|
||||||
localStorage.setItem('cardId', resJSON.card_id);
|
// Authorization: `Bearer ${localStorage.getItem('auth_token')}`
|
||||||
localStorage.setItem(
|
// }
|
||||||
'access_token_expired_at',
|
// }
|
||||||
resJSON.access_token_expired_at
|
// );
|
||||||
);
|
// let data = await response.json();
|
||||||
dispatch(resJSON)
|
//
|
||||||
})
|
// return data
|
||||||
} catch (error) {
|
// } catch (error) {
|
||||||
console.error('Error occured: ', error)
|
// console.log('Query error', error)
|
||||||
}
|
// }
|
||||||
};
|
// });
|
||||||
|
|
||||||
export const fetchReportList = withAuthRedirect(async (link) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`https://guild.loc/api/reports/index?user_id=26&fromDate=2021-10-18`,
|
|
||||||
// link,
|
|
||||||
{
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${localStorage.getItem('auth_token')}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let data = await response.json();
|
|
||||||
|
|
||||||
return data
|
|
||||||
} catch (error) {
|
|
||||||
console.log('Query error', error)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
export const fetchGet = withAuthRedirect(async (link) => {
|
export const fetchGet = withAuthRedirect(async (link) => {
|
||||||
try {
|
try {
|
||||||
|
Loading…
Reference in New Issue
Block a user