fixed code

This commit is contained in:
Hope87 2021-07-02 16:02:47 +03:00
parent edd01168a5
commit c44c1fe27c
28 changed files with 356 additions and 357 deletions

View File

@ -1,7 +1,9 @@
import React, { useState, Suspense, lazy } from 'react'; import React, { Suspense, lazy } from 'react';
import { HashRouter as Router, Route, Switch } from 'react-router-dom'; import { HashRouter as Router, Route, Switch } from 'react-router-dom';
import { useSelector } from 'react-redux';
import 'bootstrap/dist/css/bootstrap.min.css'; import 'bootstrap/dist/css/bootstrap.min.css';
import './fonts/stylesheet.css'; import './fonts/stylesheet.css';
import { selectAuth } from './redux/outstaffingSlice';
const AuthPageForDevelopers = lazy(() => import('./pages/AuthPageForDevelopers')); const AuthPageForDevelopers = lazy(() => import('./pages/AuthPageForDevelopers'));
// const AuthPageForPartners = lazy(() => import('./pages/AuthPageForPartners')); // const AuthPageForPartners = lazy(() => import('./pages/AuthPageForPartners'));
@ -11,18 +13,13 @@ const CalendarPage = lazy(() => import('./pages/CalendarPage'));
const ReportPage = lazy(() => import('./pages/ReportFormPage.js')); const ReportPage = lazy(() => import('./pages/ReportFormPage.js'));
const App = () => { const App = () => {
const [isAuth, setIsAuth] = useState(true); const isAuth = useSelector(selectAuth);
const [candidates, setCandidates] = useState([]); // const [candidateForCalendar, setCandidateForCalendar] = useState([]);
const [candidateForCalendar, setCandidateForCalendar] = useState([]);
const getCandidate = (candidateArr) => { // const getCandidateForCalendar = (candidate) => {
console.log('candidateArr ', candidateArr); // console.log('candidate ', candidate);
setCandidates(candidateArr); // setCandidateForCalendar(candidate);
}; // };
const getCandidateForCalendar = (candidate) => {
setCandidateForCalendar(candidate);
};
return ( return (
<Router> <Router>
@ -30,13 +27,13 @@ const App = () => {
{isAuth ? ( {isAuth ? (
<Switch> <Switch>
<Route path="/" exact> <Route path="/" exact>
<HomePage getCandidate={getCandidate} /> <HomePage />
</Route> </Route>
<Route path="/candidate/:id"> <Route path="/candidate/:id">
<CandidatePage candidatesArr={candidates} getCandidateForCalendar={getCandidateForCalendar} /> <CandidatePage />
</Route> </Route>
<Route path="/calendar"> <Route path="/calendar">
<CalendarPage candidateForCalendar={candidateForCalendar} /> <CalendarPage />
</Route> </Route>
<Route path="/report"> <Route path="/report">
<ReportPage /> <ReportPage />
@ -47,8 +44,8 @@ const App = () => {
</Switch> </Switch>
) : ( ) : (
<Route path="/" exact> <Route path="/" exact>
<AuthPageForDevelopers setAuth={setIsAuth} /> {/* <AuthPageForPartners /> */}
{/* <AuthPageForPartners setAuth={setIsAuth} /> */} <AuthPageForDevelopers />
</Route> </Route>
)} )}
</Suspense> </Suspense>

View File

@ -1,4 +1,6 @@
import React from 'react'; import React from 'react';
import { useDispatch } from 'react-redux';
import { auth } from '../../redux/outstaffingSlice';
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';
@ -11,7 +13,8 @@ import telegram from '../../images/telegram.png';
import vector from '../../images/Vector_Smart_Object.png'; 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';
const AuthForDevelopers = ({ setAuthed }) => { const AuthForDevelopers = () => {
const dispatch = useDispatch();
return ( return (
<section className={style.developers}> <section className={style.developers}>
<div className={style.developers__background}> <div className={style.developers__background}>
@ -35,7 +38,7 @@ const AuthForDevelopers = ({ setAuthed }) => {
<label htmlFor="password">Пароль:</label> <label htmlFor="password">Пароль:</label>
<input id="password" type="password" placeholder="Пароль" /> <input id="password" type="password" placeholder="Пароль" />
<button className={style.form__btn} type="submit" onClick={() => setAuthed(true)}> <button className={style.form__btn} type="submit" onClick={() => dispatch(auth(true))}>
Войти Войти
</button> </button>
</form> </form>

View File

@ -1,10 +1,11 @@
import React from 'react'; import React from 'react';
import { useDispatch } from 'react-redux';
import { auth } from '../../redux/outstaffingSlice';
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';
import medium from '../../images/medium_male_big.png'; import medium from '../../images/medium_male_big.png';
import cross from '../../images/cross.png'; import cross from '../../images/cross.png';
// import specialists from '../../images/specialists.png';
import text from '../../images/Body_Text.png'; import text from '../../images/Body_Text.png';
import align from '../../images/align-left.png'; import align from '../../images/align-left.png';
import phone from '../../images/phone.png'; import phone from '../../images/phone.png';
@ -12,7 +13,9 @@ import telegram from '../../images/telegram.png';
import vector from '../../images/Vector_Smart_Object.png'; 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';
const AuthForPartners = ({ setAuthed }) => { const AuthForPartners = () => {
const dispatch = useDispatch();
return ( return (
<section className={style.partners}> <section className={style.partners}>
<div className={style.partners__background}> <div className={style.partners__background}>
@ -36,7 +39,7 @@ const AuthForPartners = ({ setAuthed }) => {
<label htmlFor="password">Пароль:</label> <label htmlFor="password">Пароль:</label>
<input id="password" type="password" placeholder="Пароль" /> <input id="password" type="password" placeholder="Пароль" />
<button className={style.form__btn} type="submit" onClick={() => setAuthed(true)}> <button className={style.form__btn} type="submit" onClick={() => dispatch(auth(true))}>
Войти Войти
</button> </button>
</form> </form>

View File

@ -1,4 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux';
import { selectCurrentCandidate } from '../../redux/outstaffingSlice';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import style from './Calendar.module.css'; import style from './Calendar.module.css';
import calendarMale from '../../images/medium_male.png'; import calendarMale from '../../images/medium_male.png';
@ -6,7 +8,9 @@ import rectangle from '../../images/rectangle_secondPage.png';
import CalendarComponent from './CalendarComponent'; import CalendarComponent from './CalendarComponent';
import { currentMonth } from './calendarHelper'; import { currentMonth } from './calendarHelper';
const Calendar = ({ candidateForCalendar }) => { const Calendar = () => {
const candidateForCalendar = useSelector(selectCurrentCandidate);
const [month, setMonth] = useState(''); const [month, setMonth] = useState('');
useEffect(() => { useEffect(() => {

View File

@ -1,24 +1,24 @@
import React from 'react'; import React from 'react';
import { useHistory, useParams } from 'react-router-dom'; import { useHistory, useParams } from 'react-router-dom';
import { useSelector, useDispatch } from 'react-redux';
import { selectCandidates, currentCandidate, selectCurrentCandidate } from '../../redux/outstaffingSlice';
import style from './Candidate.module.css'; import style from './Candidate.module.css';
import arrow from '../../images/right-arrow.png'; import arrow from '../../images/right-arrow.png';
import rectangle from '../../images/rectangle_secondPage.png'; import rectangle from '../../images/rectangle_secondPage.png';
import Sidebar from '../Sidebar/Sidebar'; import Sidebar from '../Sidebar/Sidebar';
import SectionOne from './sections/SectionOne'; import SectionSkills from './SectionSkills';
import SectionTwo from './sections/SectionTwo';
import SectionThree from './sections/SectionThree';
import SectionFour from './sections/SectionFour';
import SectionFive from './sections/SectionFive';
import SectionSkills from './sections/SectionSkills';
const Candidate = ({ candidatesArr, getCandidateForCalendar }) => { const Candidate = () => {
const history = useHistory(); const history = useHistory();
const { id: candidateId } = useParams(); const { id: candidateId } = useParams();
const currentCandidate = candidatesArr.find((el) => Number(el.id) === Number(candidateId)); const dispatch = useDispatch();
const { name, skillsName, img } = currentCandidate; const candidatesArr = useSelector(selectCandidates);
dispatch(currentCandidate(candidatesArr.find((el) => Number(el.id) === Number(candidateId))));
const currentCandidateObj = useSelector(selectCurrentCandidate);
const { name, skillsName, img, skills } = currentCandidateObj;
let classes; let classes;
@ -66,24 +66,67 @@ const Candidate = ({ candidatesArr, getCandidateForCalendar }) => {
<div className={style.candidate__main}> <div className={style.candidate__main}>
<div className="row"> <div className="row">
<div className="col-12 col-xl-4"> <div className="col-12 col-xl-4">
<Sidebar getCandidateForCalendar={getCandidateForCalendar} currentCandidateObj={currentCandidate} /> <Sidebar />
</div> </div>
<div className="col-12 col-xl-8"> <div className="col-12 col-xl-8">
<div className={style.candidate__main__description}> <div className={style.candidate__main__description}>
<h2>{name}</h2> <h2>{name}</h2>
<img src={rectangle} alt="" /> <img src={rectangle} alt="" />
<p># Описание опыта</p> <p># Описание опыта</p>
<SectionOne /> <div className={style.SectionOne}>
<h3>SVM - сервис выездных менеджеров для банка ПСБ</h3>
<p>
Приложение, которое позволяет управлять работой т.н. выездных менеджеров (ВМ). Банк предоставляет их
услуги своим (потенциальным или реальным) клиентам, позволяя подключать расчетно-кассовое
обслуживание или регистрировать свой бизнес. Клиенту не нужно приходить в отделение/офис банка - все
необходимые бумаги ВМ подготовит заранее и принесет на согласование и подпись в удобное ему (клиент)
время и место.
</p>
<h4>Senior PHP/JS Developer</h4>
</div>
<p># Средства и инструменты:</p> <p># Средства и инструменты:</p>
<SectionTwo /> <div className={style.SectionTwo}>
<p>
- Разработал и внедрил веб приложения, а также программное обеспечение с использованием Node.js,
MySQL, JavaScript, HTML, CSS, React.js и Vue.JS. - Поддерживал существующий веб-сайт на базе PHP.
Перевел существующую платформу с Laravel на современную архитектуру React/Redux и Node.
</p>
<p>
- Проектировал и разрабатывал компоненты пользовательского интерфейса с использованием HTML, CSS и
JavaScript. - Повысил скорость загрузки веб-сайта и время безотказной работы за счете переписывания
всех основных компонентов и внедрения новой архетиктуры. - Разработал персональное APIs.
</p>
</div>
<p># Описание опыта</p> <p># Описание опыта</p>
<SectionThree /> <div className={style.SectionThree}>
<h3>Multitur - личный кабинет для сервиса поиска/подбора отелей</h3>
<p>
Личный кабинет для сотрудников отелей, который позволяет управлять информацией по отелю на сайте.
</p>
<h4>Senior PHP/JS Developer</h4>
</div>
<p># Средства и инструменты:</p> <p># Средства и инструменты:</p>
<SectionFour /> <div className={style.SectionFour}>
<p>Backend - REST API на PHP 7.1 с использованием фреймворка Laravel 5.8</p>
<p>Frontend - Vue.js</p>
<p>БД - MYSQL</p>
</div>
<p># Функционал:</p> <p># Функционал:</p>
<SectionFive /> <>
<SectionSkills /> <div className={style.SectionFive}>
<p>Регистрации/авторизации;</p>
<p>Управления правами менеджеров отеля, назначение поставщиков</p>
<p>Управления описанием и профилем отелей;</p>
<p>Управления финансами, ценообразованием, квотами;</p>
<p>Переписки со своими менеджерами, а также с вышестоящими инстанциями;</p>
<p>Управления новостями отеля;</p>
<p>Просмотра расширенной статистики по заявкам и людям;</p>
</div>
<button type="submit" className={style.SectionFive__btn}>
Выбрать к собеседованию
</button>
</>
<SectionSkills skillsArr={skills} />
</div> </div>
</div> </div>
</div> </div>

View File

@ -182,3 +182,162 @@
text-align: left; text-align: left;
margin: 20px 0px; margin: 20px 0px;
} }
.SectionOne > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 2.2em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionOne > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionOne > h4 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionTwo > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionThree > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 2.2em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionThree > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionThree > h4 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionFour > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 18px;
text-align: left;
}
.SectionFive > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 16px;
text-align: left;
}
@media (min-width: 576.98px) {
.SectionFive__btn {
display: none;
}
}
@media (max-width: 575.98px) {
.SectionFive__btn {
display: block;
width: 221px;
height: 49px;
box-shadow: 0 8px 20px rgba(82, 151, 34, 0.21);
border-radius: 24px;
background-color: #ffffff;
background-image: linear-gradient(to top, #6aaf5c 0%, #52b709 100%),
linear-gradient(
36deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.16) 47%,
rgba(255, 255, 255, 0.17) 50%,
rgba(255, 255, 255, 0) 100%
);
color: #ffffff;
font-family: 'Muller';
font-size: 1.3em;
letter-spacing: normal;
text-align: left;
border: none;
text-align: center;
margin: 28px auto;
}
}
.SectionSkills {
display: flex;
border: 1px solid #69bf2c;
padding: 28px 40px 16px 30px;
margin-top: 60px;
border-radius: 10px;
margin-bottom: 60px;
}
@media (max-width: 575.98px) {
.SectionSkills {
display: none;
}
}
.SectionSkills > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionSkills > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
margin-left: 20px;
}

View File

@ -0,0 +1,15 @@
import React from 'react';
import style from './Candidate.module.css';
const SectionSkills = ({ skillsArr }) => {
return (
<div className={style.SectionSkills}>
<h3>Навыки:</h3>
{skillsArr.map((skills) => (
<p key={skills.id}>{skills.skill.name}</p>
))}
</div>
);
};
export default SectionSkills;

View File

@ -1,156 +0,0 @@
.SectionOne > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 2.2em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionOne > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionOne > h4 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionTwo > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionThree > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 2.2em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionThree > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionThree > h4 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 36px;
text-align: left;
}
.SectionFour > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 18px;
text-align: left;
}
.SectionFive > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 400;
font-style: normal;
letter-spacing: normal;
line-height: 16px;
text-align: left;
}
@media (min-width: 576.98px) {
.SectionFive__btn {
display: none;
}
}
@media (max-width: 575.98px) {
.SectionFive__btn {
display: block;
width: 221px;
height: 49px;
box-shadow: 0 8px 20px rgba(82, 151, 34, 0.21);
border-radius: 24px;
background-color: #ffffff;
background-image: linear-gradient(to top, #6aaf5c 0%, #52b709 100%),
linear-gradient(
36deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0.16) 47%,
rgba(255, 255, 255, 0.17) 50%,
rgba(255, 255, 255, 0) 100%
);
color: #ffffff;
font-family: 'Muller';
font-size: 1.3em;
letter-spacing: normal;
text-align: left;
border: none;
text-align: center;
margin: 28px auto;
}
}
.SectionSkills {
border: 1px solid #69bf2c;
padding: 28px 40px 16px 30px;
margin-top: 60px;
border-radius: 10px;
margin-bottom: 60px;
}
@media (max-width: 575.98px) {
.SectionSkills {
display: none;
}
}
.SectionSkills > h3 {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 700;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}
.SectionSkills > p {
font-family: 'GT Eesti Pro Display';
font-size: 1.8em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 28px;
text-align: left;
}

View File

@ -1,23 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionFive = () => {
return (
<>
<div className={style.SectionFive}>
<p>Регистрации/авторизации;</p>
<p>Управления правами менеджеров отеля, назначение поставщиков</p>
<p>Управления описанием и профилем отелей;</p>
<p>Управления финансами, ценообразованием, квотами;</p>
<p>Переписки со своими менеджерами, а также с вышестоящими инстанциями;</p>
<p>Управления новостями отеля;</p>
<p>Просмотра расширенной статистики по заявкам и людям;</p>
</div>
<button type="submit" className={style.SectionFive__btn}>
Выбрать к собеседованию
</button>
</>
);
};
export default SectionFive;

View File

@ -1,14 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionFour = () => {
return (
<div className={style.SectionFour}>
<p>Backend - REST API на PHP 7.1 с использованием фреймворка Laravel 5.8</p>
<p>Frontend - Vue.js</p>
<p>БД - MYSQL</p>
</div>
);
};
export default SectionFour;

View File

@ -1,19 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionOne = () => {
return (
<div className={style.SectionOne}>
<h3>SVM - сервис выездных менеджеров для банка ПСБ</h3>
<p>
Приложение, которое позволяет управлять работой т.н. выездных менеджеров (ВМ). Банк предоставляет их услуги
своим (потенциальным или реальным) клиентам, позволяя подключать расчетно-кассовое обслуживание или
регистрировать свой бизнес. Клиенту не нужно приходить в отделение/офис банка - все необходимые бумаги ВМ
подготовит заранее и принесет на согласование и подпись в удобное ему (клиент) время и место.
</p>
<h4>Senior PHP/JS Developer</h4>
</div>
);
};
export default SectionOne;

View File

@ -1,18 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionSkills = () => {
return (
<div className={style.SectionSkills}>
<h3>Навыки:</h3>
<p>
PHP: Native, Laravel, Zend Framework, CodeIgniter, YII, Symfony. JavaScript: Native, jQuery, AngularJS, ExtJS,
BackboneJS, ReactJS + Redux, VueJS. Search Engines: Sphinx, Elastic Search. Cache: Memcache, Redis. Profiling:
Xdebug, XHProf. WebSockets: Ratchet, Socket.io. Очереди: RabbitMQ, Beanstalk. MySQL, PostgreSQL, Oracle, MsSQL,
Vertica, HBase, Cassandra, MongoDB, Redis, Tarantool. CSS 2/3 (Sass, Less). HTML 4/5.
</p>
</div>
);
};
export default SectionSkills;

View File

@ -1,14 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionThree = () => {
return (
<div className={style.SectionThree}>
<h3>Multitur - личный кабинет для сервиса поиска/подбора отелей</h3>
<p>Личный кабинет для сотрудников отелей, который позволяет управлять информацией по отелю на сайте.</p>
<h4>Senior PHP/JS Developer</h4>
</div>
);
};
export default SectionThree;

View File

@ -1,21 +0,0 @@
import React from 'react';
import style from './Section.module.css';
const SectionTwo = () => {
return (
<div className={style.SectionTwo}>
<p>
- Разработал и внедрил веб приложения, а также программное обеспечение с использованием Node.js, MySQL,
JavaScript, HTML, CSS, React.js и Vue.JS. - Поддерживал существующий веб-сайт на базе PHP. Перевел существующую
платформу с Laravel на современную архитектуру React/Redux и Node.
</p>
<p>
- Проектировал и разрабатывал компоненты пользовательского интерфейса с использованием HTML, CSS и JavaScript. -
Повысил скорость загрузки веб-сайта и время безотказной работы за счете переписывания всех основных компонентов
и внедрения новой архетиктуры. - Разработал персональное APIs.
</p>
</div>
);
};
export default SectionTwo;

View File

@ -1,12 +1,13 @@
import React from 'react'; import React, { useState } from 'react';
import style from './Description.module.css'; import style from './Description.module.css';
import dog from '../../images/dog.jpg'; import dog from '../../images/dog.jpg';
import rectangle from '../../images/rectangle_secondPage.png'; import rectangle from '../../images/rectangle_secondPage.png';
import arrowLeft from '../../images/arrow_left.png';
import arrowRight from '../../images/arrow_right.png';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { LEVELS } from '../constants/constants';
const Description = ({ candidatesListArr, onLoadMore }) => {
const [text, setText] = useState([]);
const Description = ({ candidatesListArr, getCandidate, onLoadMore }) => {
return ( return (
<section className={style.description}> <section className={style.description}>
<div className="container"> <div className="container">
@ -17,15 +18,24 @@ const Description = ({ candidatesListArr, getCandidate, onLoadMore }) => {
<img className={style.description__img} src={dog} alt="" /> <img className={style.description__img} src={dog} alt="" />
</div> </div>
<div className="col-12 col-xl-6"> <div className="col-12 col-xl-6">
<h3 className={style.description__title}>{el.header} разработчик</h3> <h3 className={style.description__title}>
<p className={style.description__text}> {el.skillsName} разработчик, {LEVELS[el.level]}
- 10 лет пишу приложения под IOS, отлично владею Objective-C и Swift. </h3>
</p>
<p className={style.description__text}>- 5 лет руковожу командами мобильной разработки.</p> {text.length > 0 ? (
<p className={style.description__text}>- 3 года преподаю в IOS-школе Сбера</p> <>
<p className={style.description__text}>
- 10 лет пишу приложения под IOS, отлично владею Objective-C и Swift.
</p>
<p className={style.description__text}>- 5 лет руковожу командами мобильной разработки.</p>
<p className={style.description__text}>- 3 года преподаю в IOS-школе Сбера</p>
</>
) : (
<p className={style.description__textSecondary}>Описание отсутствует</p>
)}
</div> </div>
<div className="col-12 col-xl-4"> <div className="col-12 col-xl-4">
<Link to={`/candidate/${el.id}`} onClick={() => getCandidate(candidatesListArr)}> <Link to={`/candidate/${el.id}`}>
<button className={style.description__button}>Подробное резюме</button> <button className={style.description__button}>Подробное резюме</button>
</Link> </Link>
</div> </div>
@ -49,7 +59,7 @@ const Description = ({ candidatesListArr, getCandidate, onLoadMore }) => {
<div className={style.description__footer__btn}> <div className={style.description__footer__btn}>
<button onClick={() => onLoadMore(2)}>Загрузить еще</button> <button onClick={() => onLoadMore(2)}>Загрузить еще</button>
</div> </div>
<div className={style.description__footer__box}> {/* <div className={style.description__footer__box}>
<div className={style.arrow__left}> <div className={style.arrow__left}>
<img src={arrowLeft} alt="" /> <img src={arrowLeft} alt="" />
</div> </div>
@ -57,7 +67,7 @@ const Description = ({ candidatesListArr, getCandidate, onLoadMore }) => {
<div className={style.arrow__right}> <div className={style.arrow__right}>
<img src={arrowRight} alt="" /> <img src={arrowRight} alt="" />
</div> </div>
</div> </div> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -84,6 +84,17 @@
line-height: 28px; line-height: 28px;
} }
.description__textSecondary {
font-family: 'GT Eesti Pro Display';
font-size: 1.7em;
font-weight: 100;
font-style: normal;
letter-spacing: normal;
line-height: 24px;
text-align: left;
line-height: 28px;
}
@media (max-width: 575.98px) { @media (max-width: 575.98px) {
.description__text { .description__text {
margin-left: 20px; margin-left: 20px;

View File

@ -2,22 +2,24 @@ 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 { fetchProfile, fetchSkills } from '../../server/server';
import front from '../../images/front_end.png'; import front from '../../images/front_end.png';
import back from '../../images/back_end.png'; import back from '../../images/back_end.png';
import design from '../../images/design.png'; import design from '../../images/design.png';
import { fetchProfile, fetchSkills } from '../../server/server';
import { profiles, selectProfiles, tags, candidates, selectCandidates, selectTab } from '../../redux/outstaffingSlice'; import { profiles, selectProfiles, tags, candidates, selectCandidates, selectTab } from '../../redux/outstaffingSlice';
const Home = ({ getCandidate }) => { const Home = () => {
const [count, setCount] = useState(2); const [index, setIndex] = useState(2);
const dispatch = useDispatch(); const dispatch = useDispatch();
const profilesArr = useSelector(selectProfiles); const profilesArr = useSelector(selectProfiles);
const candidatesArr = useSelector(selectCandidates); const candidatesArr = useSelector(selectCandidates);
const selectedTab = useSelector(selectTab); const selectedTab = useSelector(selectTab);
useEffect(() => { useEffect(() => {
fetchProfile('https://guild.craft-group.xyz/api/profile') fetchProfile(`https://guild.craft-group.xyz/api/profile?limit=`, index)
.then((profileArr) => dispatch(profiles(profileArr))) .then((profileArr) => dispatch(profiles(profileArr)))
.catch((e) => console.log(e)); .catch((e) => console.log(e));
@ -32,28 +34,25 @@ const Home = ({ getCandidate }) => {
); );
dispatch(tags(tempTags)); dispatch(tags(tempTags));
}); });
}, [dispatch]); }, [dispatch, index]);
useEffect(() => { useEffect(() => {
dispatch( dispatch(
candidates( candidates(
profilesArr.map((profile) => { profilesArr.map((profile) => {
let skillsName = ''; let skillsName = '';
let img;
let header; let header;
let img;
if (Number(profile.position_id) === 1) { if (Number(profile.position_id) === 1) {
skillsName = 'Frontend'; skillsName = 'Frontend';
img = front; img = front;
header = 'Фронтенд';
} else if (Number(profile.position_id) === 2) { } else if (Number(profile.position_id) === 2) {
skillsName = 'Backend'; skillsName = 'Backend';
img = back; img = back;
header = 'Бэкенд';
} else if (Number(profile.position_id) === 3) { } else if (Number(profile.position_id) === 3) {
skillsName = 'Marketer'; skillsName = 'Marketer';
img = design; img = design;
header = 'Маркетинг';
} }
return { return {
@ -61,19 +60,18 @@ const Home = ({ getCandidate }) => {
profileId: profile.position_id, profileId: profile.position_id,
name: profile.fio, name: profile.fio,
skills: profile.skillValues, skills: profile.skillValues,
level: profile.level,
skillsName, skillsName,
img,
header, header,
img,
}; };
}) })
) )
); );
}, [profilesArr, dispatch]); }, [profilesArr, dispatch]);
const shorthandArray = candidatesArr.slice(0, count);
const loadMore = (count) => { const loadMore = (count) => {
setCount((prev) => prev + count); setIndex((prev) => prev + count);
}; };
return ( return (
@ -81,9 +79,8 @@ const Home = ({ getCandidate }) => {
<Outstaffing /> <Outstaffing />
<Description <Description
candidatesListArr={ candidatesListArr={
selectedTab ? candidatesArr.filter((item) => item.skillsName === selectedTab) : shorthandArray selectedTab ? candidatesArr.filter((item) => item.skillsName === selectedTab) : candidatesArr
} }
getCandidate={getCandidate}
onLoadMore={loadMore} onLoadMore={loadMore}
/> />
</> </>

View File

@ -4,6 +4,9 @@ import style from './Outstaffing.module.css';
import OutstaffingBlock from './OutstaffingBlock'; import OutstaffingBlock from './OutstaffingBlock';
import TagSelect from '../Select/TagSelect'; import TagSelect from '../Select/TagSelect';
import { selectTags, selectTab, selectCandidates } from '../../redux/outstaffingSlice'; import { selectTags, selectTab, selectCandidates } from '../../redux/outstaffingSlice';
import front from '../../images/front_end.png';
import back from '../../images/back_end.png';
import design from '../../images/design.png';
const Outstaffing = () => { const Outstaffing = () => {
const tagsArr = useSelector(selectTags); const tagsArr = useSelector(selectTags);
@ -30,6 +33,8 @@ const Outstaffing = () => {
data={candidatesArr.find((item) => item.skillsName === 'Frontend')} data={candidatesArr.find((item) => item.skillsName === 'Frontend')}
dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_front')} dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_front')}
selected={selected === 'Frontend'} selected={selected === 'Frontend'}
img={front}
header="Фронтенд"
/> />
</div> </div>
<div className="col-12 col-xl-4"> <div className="col-12 col-xl-4">
@ -37,6 +42,8 @@ const Outstaffing = () => {
data={candidatesArr.find((item) => item.skillsName === 'Backend')} data={candidatesArr.find((item) => item.skillsName === 'Backend')}
dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_back')} dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_back')}
selected={selected === 'Backend'} selected={selected === 'Backend'}
img={back}
header="Бэкенд"
/> />
</div> </div>
<div className="col-12 col-xl-4"> <div className="col-12 col-xl-4">
@ -44,6 +51,8 @@ const Outstaffing = () => {
data={candidatesArr.find((item) => item.skillsName === 'Marketer')} data={candidatesArr.find((item) => item.skillsName === 'Marketer')}
dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_design')} dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_design')}
selected={selected === 'Marketer'} selected={selected === 'Marketer'}
img={design}
header="Маркетинг"
/> />
</div> </div>
</div> </div>

View File

@ -3,12 +3,12 @@ import { useDispatch, useSelector } from 'react-redux';
import { selectedTab, selectItems, selectedItems } from '../../redux/outstaffingSlice'; import { selectedTab, selectItems, selectedItems } from '../../redux/outstaffingSlice';
import style from './Outstaffing.module.css'; import style from './Outstaffing.module.css';
const OutstaffingBlock = ({ dataTags = [], data = {}, selected }) => { const OutstaffingBlock = ({ dataTags = [], data = {}, selected, img, header }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const itemsArr = useSelector(selectItems); const itemsArr = useSelector(selectItems);
const { header, img, skillsName } = data; const { skillsName } = data;
const handleBlockClick = (item) => { const handleBlockClick = (item) => {
if (!itemsArr.find((el) => item === el.value)) { if (!itemsArr.find((el) => item === el.value)) {

View File

@ -1,24 +1,22 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import dogBig from '../../images/dog.jpg'; import dogBig from '../../images/dog.jpg';
import arrowLeft from '../../images/arrow_left.png';
import arrowRight from '../../images/arrow_right.png';
import style from './Sidebar.module.css'; import style from './Sidebar.module.css';
const Sidebar = ({ getCandidateForCalendar, currentCandidateObj }) => { const Sidebar = () => {
return ( return (
<div className={style.candidateSidebar}> <div className={style.candidateSidebar}>
<div className={style.candidateSidebar__info}> <div className={style.candidateSidebar__info}>
<img src={dogBig} alt="" /> <img src={dogBig} alt="" />
<p className={style.candidateSidebar__info__e}>Опыт работы</p> <p className={style.candidateSidebar__info__e}>Опыт работы</p>
<p className={style.candidateSidebar__info__y}>4+ лет</p> <p className={style.candidateSidebar__info__y}>4+ лет</p>
<Link to={`/calendar`} onClick={() => getCandidateForCalendar(currentCandidateObj)}> <Link to={`/calendar`}>
<button className={style.candidateSidebar__info__btn}>Выбрать к собеседованию</button> <button className={style.candidateSidebar__info__btn}>Выбрать к собеседованию</button>
</Link> </Link>
<p className={style.candidateSidebar__info__l}>Посмотреть ещё</p> {/* <p className={style.candidateSidebar__info__l}>Посмотреть ещё</p> */}
</div> </div>
<div className={style.candidateSidebar__arrows}> {/* <div className={style.candidateSidebar__arrows}>
<div className={style.arrow__left}> <div className={style.arrow__left}>
<img src={arrowLeft} alt="" /> <img src={arrowLeft} alt="" />
</div> </div>
@ -26,7 +24,7 @@ const Sidebar = ({ getCandidateForCalendar, currentCandidateObj }) => {
<div className={style.arrow__right}> <div className={style.arrow__right}>
<img src={arrowRight} alt="" /> <img src={arrowRight} alt="" />
</div> </div>
</div> </div> */}
</div> </div>
); );
}; };

View File

@ -0,0 +1,6 @@
export const LEVELS = {
1: 'Junior',
2: 'Middle',
3: 'Middle+',
4: 'Senior',
};

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import AuthForDevelopers from '../components/Auth/AuthForDevelopers'; import AuthForDevelopers from '../components/Auth/AuthForDevelopers';
const AuthPageForDevelopers = ({ setAuth }) => { const AuthPageForDevelopers = () => {
return <AuthForDevelopers setAuthed={setAuth} />; return <AuthForDevelopers />;
}; };
export default AuthPageForDevelopers; export default AuthPageForDevelopers;

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import AuthForPartners from '../components/Auth/AuthForPartners'; import AuthForPartners from '../components/Auth/AuthForPartners';
const AuthPageForPartners = ({ setAuth }) => { const AuthPageForPartners = () => {
return <AuthForPartners setAuthed={setAuth} />; return <AuthForPartners />;
}; };
export default AuthPageForPartners; export default AuthPageForPartners;

View File

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

View File

@ -2,8 +2,6 @@ import React from 'react';
import Candidate from '../components/Candidate/Candidate'; import Candidate from '../components/Candidate/Candidate';
const CandidatePage = ({ candidatesArr, getCandidateForCalendar }) => ( const CandidatePage = () => <Candidate />;
<Candidate candidatesArr={candidatesArr} getCandidateForCalendar={getCandidateForCalendar} />
);
export default CandidatePage; export default CandidatePage;

View File

@ -2,6 +2,6 @@ import React from 'react';
import Home from '../components/Home/Home'; import Home from '../components/Home/Home';
const HomePage = ({ getCandidate }) => <Home getCandidate={getCandidate} />; const HomePage = () => <Home />;
export default HomePage; export default HomePage;

View File

@ -4,8 +4,10 @@ const initialState = {
tags: [], tags: [],
profiles: [], profiles: [],
candidates: [], candidates: [],
selectedTab: '',
selectedItems: [], selectedItems: [],
selectedTab: '',
currentCandidate: {},
auth: true,
}; };
export const outstaffingSlice = createSlice({ export const outstaffingSlice = createSlice({
@ -27,15 +29,24 @@ export const outstaffingSlice = createSlice({
selectedItems: (state, action) => { selectedItems: (state, action) => {
state.selectedItems = action.payload; state.selectedItems = action.payload;
}, },
currentCandidate: (state, action) => {
state.currentCandidate = action.payload;
},
auth: (state, action) => {
state.auth = action.payload;
},
}, },
}); });
export const { tags, profiles, candidates, selectedTab, selectedItems } = outstaffingSlice.actions; export const { tags, profiles, candidates, selectedTab, selectedItems, auth, currentCandidate } =
outstaffingSlice.actions;
export const selectProfiles = (state) => state.outstaffing.profiles; export const selectProfiles = (state) => state.outstaffing.profiles;
export const selectTags = (state) => state.outstaffing.tags; export const selectTags = (state) => state.outstaffing.tags;
export const selectCandidates = (state) => state.outstaffing.candidates; export const selectCandidates = (state) => state.outstaffing.candidates;
export const selectTab = (state) => state.outstaffing.selectedTab; export const selectTab = (state) => state.outstaffing.selectedTab;
export const selectItems = (state) => state.outstaffing.selectedItems; export const selectItems = (state) => state.outstaffing.selectedItems;
export const selectCurrentCandidate = (state) => state.outstaffing.currentCandidate;
export const selectAuth = (state) => state.outstaffing.auth;
export default outstaffingSlice.reducer; export default outstaffingSlice.reducer;

View File

@ -1,5 +1,5 @@
export const fetchProfile = async (link, index = '') => { export const fetchProfile = async (link, index) => {
const response = await fetch(`${link}/${index}`); const response = await fetch(`${link}${index}`);
let data = await response.json(); let data = await response.json();
return data; return data;