diff --git a/package-lock.json b/package-lock.json index d7abb128..4de78244 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,7 @@ "react-select": "^5.7.0", "react-slick": "^0.29.0", "react-syntax-highlighter": "^15.4.5", + "react-timer-hook": "^3.0.5", "react-yandex-metrika": "^2.6.0", "redux-devtools-extension": "^2.13.9", "resolve": "1.18.1", @@ -21571,6 +21572,15 @@ "react": ">= 0.14.0" } }, + "node_modules/react-timer-hook": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-timer-hook/-/react-timer-hook-3.0.5.tgz", + "integrity": "sha512-n+98SdmYvui2ne3KyWb3Ldu4k0NYQa3g/VzW6VEIfZJ8GAk/jJsIY700M8Nd2vNSTj05c7wKyQfJBqZ0x7zfiA==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", diff --git a/package.json b/package.json index 6ccfd8d8..2c10fbd6 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,7 @@ "react-select": "^5.7.0", "react-slick": "^0.29.0", "react-syntax-highlighter": "^15.4.5", + "react-timer-hook": "^3.0.5", "react-yandex-metrika": "^2.6.0", "redux-devtools-extension": "^2.13.9", "resolve": "1.18.1", diff --git a/src/App.js b/src/App.js index 9373a11f..bb1dbb4a 100644 --- a/src/App.js +++ b/src/App.js @@ -13,10 +13,7 @@ import { ProfileCalendar } from "./components/ProfileCalendar/ProfileCalendar"; import FormPage from "./pages/FormPage/FormPage.js"; import SingleReportPage from "./pages/SingleReportPage/SingleReportPage"; import { QuizPage } from "./pages/quiz/QuizPage"; -import { InterjacentPage } from "./pages/quiz/InterjacentPage"; -import { QuizTestPage } from "./pages/quiz/QuizTestPage"; -import { InstructionPage } from "./pages/quiz/InstructionPage"; -import { ResultPage } from "./pages/quiz/ResultPage"; +import {QuizReportPage} from './pages/quiz/QuizReportPage'; import { Profile } from "./pages/Profile/Profile.js"; import { Summary } from "./pages/Summary/Summary"; import { ViewReport } from "./pages/ViewReport/ViewReport"; @@ -32,9 +29,11 @@ import { PartnerEmployees } from "./pages/PartnerEmployees/PartnerEmployees"; import {AuthForCandidate} from "./pages/AuthForCandidate/AuthForCandidate"; import {RegistrationForCandidate} from "./pages/RegistrationForCandidate/RegistrationForCandidate"; - +import './assets/global.scss' import './fonts/stylesheet.css' import 'bootstrap/dist/css/bootstrap.min.css' +import { ProfileCandidate } from './pages/ProfileCandidate/ProfileCandidate'; +import { PassingTests } from './pages/quiz/PassingTests'; @@ -61,10 +60,8 @@ const App = () => { }/> - }/> - }/> - }/> - }/> + }/> + }/> @@ -83,6 +80,9 @@ const App = () => { }/> }/> + + }/> + }/> diff --git a/src/assets/global.scss b/src/assets/global.scss new file mode 100644 index 00000000..2566fbec --- /dev/null +++ b/src/assets/global.scss @@ -0,0 +1,25 @@ +a:hover { + text-decoration: none !important; +} +.main-title { + font-weight: 700; + font-size: 22px; + line-height: 145%; + color: #000000; + word-break: break-word; + span { + color: #52b709; + } +} +.btn-green { + background: #52b709; + border-radius: 44px; + width: 100%; + border: none; + font-weight: 400; + line-height: 178%; + color: #ffffff; + display: flex; + align-items: center; + justify-content: center; +} diff --git a/src/components/CardControl/CardControl.js b/src/components/CardControl/CardControl.js new file mode 100644 index 00000000..3458ebea --- /dev/null +++ b/src/components/CardControl/CardControl.js @@ -0,0 +1,20 @@ +import React from 'react' +import rightArrow from "../../images/arrowRight.png" +import { Link } from 'react-router-dom' +import './CardControl.scss' + +export const CardControl = ({title,path,description, img}) => { + return ( + +
+ itemImg +

{title}

+
+
+

+
+ arrow +
+
+ ) +} diff --git a/src/components/CardControl/CardControl.scss b/src/components/CardControl/CardControl.scss new file mode 100644 index 00000000..df4d85a0 --- /dev/null +++ b/src/components/CardControl/CardControl.scss @@ -0,0 +1,73 @@ +.control-card{ + max-width: 353px; + width: 100%; + padding: 35px 45px 15px 30px; + background: #FFFFFF; + border-radius: 12px; + text-decoration: none; + cursor: pointer; + transition: all 0.3s ease; + + &:hover { + box-shadow: 6px 5px 20px rgb(87 98 80 / 21%); + transform: scale(1.02); + } + + @media (max-width: 1175px) { + width: 48%; + max-width: none; + } + + @media (max-width: 925px) { + width: 100%; + padding: 15px 25px; + } + + &__about { + display: flex; + column-gap: 20px; + align-items: center; + margin-bottom: 30px; + + @media (max-width: 925px) { + margin-bottom: 15px; + } + + h3 { + color: #000000; + font-weight: 500; + font-size: 18px; + line-height: 22px; + max-width: 125px; + margin-bottom: 0; + } + } + + &__info { + display: flex; + justify-content: space-between; + align-items: center; + + p { + font-weight: 700; + font-size: 12px; + line-height: 20px; + color: #000000; + margin-bottom: 0; + + span { + color: #52B709; + font-weight: 700; + } + } + &Link { + width: 48px; + height: 48px; + background: #DDEEC6; + border-radius: 50px; + display: flex; + justify-content: center; + align-items: center; + } + } + } \ No newline at end of file diff --git a/src/components/CategoriesItem/categoriesItem.scss b/src/components/CategoriesItem/categoriesItem.scss index 26cd6db8..55805cfd 100644 --- a/src/components/CategoriesItem/categoriesItem.scss +++ b/src/components/CategoriesItem/categoriesItem.scss @@ -2,7 +2,6 @@ display: flex; flex-direction: column; padding: 33px 32px 25px 28px; - width: 32%; background: #FFFFFF; border-radius: 12px; transition: all 0.3s ease; diff --git a/src/components/Footer/footer.scss b/src/components/Footer/footer.scss index 86b09463..59f2c49d 100644 --- a/src/components/Footer/footer.scss +++ b/src/components/Footer/footer.scss @@ -1,5 +1,5 @@ footer { - border-top: 1px solid #EBEBEB; + border-top: 1px solid #ebebeb; padding: 35px 0 50px; } diff --git a/src/components/Navigation/Navigation.js b/src/components/Navigation/Navigation.js new file mode 100644 index 00000000..45132792 --- /dev/null +++ b/src/components/Navigation/Navigation.js @@ -0,0 +1,103 @@ +import React, { useEffect, useState } from 'react' +import { NavLink } from 'react-router-dom' +import { urlForLocal } from '../../helper' +import { apiRequest } from '../../api/request'; +import { useDispatch, useSelector } from 'react-redux'; +import { getProfileInfo, setProfileInfo } from '../../redux/outstaffingSlice'; + +import avatarMok from "../../pages/PartnerTreaties/Images/avatarMok.png" + +export const Navigation = () => { + const dispatch = useDispatch(); + + + const profileInfo = useSelector(getProfileInfo); + const [user] = useState(localStorage.getItem('role_status') === '18' ? 'partner' : 'developer') + const [navInfo] = useState({ + developer: [ + { + path: '/summary', + name: 'Резюме' + }, + { + path: '/calendar', + name: 'Отчетность' + }, + { + path: '/tracker', + name: 'Трекер' + }, + { + path: '/payouts', + name: 'Выплаты' + }, + { + path: '/settings', + name: 'Настройки' + }, + ], + partner: [ + { + path: '/catalog', + name: 'Каталог' + }, + { + path: '/requests', + name: 'Запросы' + }, + { + path: '/categories', + name: 'Персонал' + }, + { + path: '/tracker', + name: 'Трекер' + }, + { + path: '/treaties', + name: 'Договора' + }, + { + path: '/settings', + name: 'Настройки' + }, + ] + }) + + useEffect(() => { + if (localStorage.getItem('role_status') === '18') { + return + } + apiRequest(`/profile/${localStorage.getItem('cardId')}`) + .then((profileInfo) => + dispatch(setProfileInfo(profileInfo)) + ); + + }, [dispatch]); + + return ( +
+
+ + +
+

+ {user === 'developer' ? + profileInfo?.fio : + '' + } +

+ + avatar + +
+
+
+ ) +} diff --git a/src/components/Navigation/Navigation.scss b/src/components/Navigation/Navigation.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/ProfileCalendar/ProfileCalendar.js b/src/components/ProfileCalendar/ProfileCalendar.js index 7bf845af..8eb07cf5 100644 --- a/src/components/ProfileCalendar/ProfileCalendar.js +++ b/src/components/ProfileCalendar/ProfileCalendar.js @@ -19,6 +19,7 @@ import {getRequestDates, setReportDate, setRequestDate} from "../../redux/report import 'moment/locale/ru' import './profileCalendar.scss' +import { Navigation } from '../Navigation/Navigation'; export const ProfileCalendar = () => { @@ -65,6 +66,7 @@ export const ProfileCalendar = () => { return (
+

Ваши отчеты

diff --git a/src/components/ProfileHeader/ProfileHeader.js b/src/components/ProfileHeader/ProfileHeader.js index 8bbca704..d17872e2 100644 --- a/src/components/ProfileHeader/ProfileHeader.js +++ b/src/components/ProfileHeader/ProfileHeader.js @@ -4,76 +4,19 @@ import {useDispatch, useSelector} from "react-redux"; import {Loader} from '../Loader/Loader' import {apiRequest} from "../../api/request"; -import {auth, getProfileInfo, setProfileInfo} from "../../redux/outstaffingSlice"; +import {auth, setProfileInfo} from "../../redux/outstaffingSlice"; import {getRole} from "../../redux/roleSlice"; - -import {urlForLocal} from "../../helper"; - -import avatarMok from "../../pages/PartnerTreaties/Images/avatarMok.png" - import './profileHeader.scss' - export const ProfileHeader = () => { const navigate = useNavigate(); const dispatch = useDispatch(); const userRole = useSelector(getRole); - const profileInfo = useSelector(getProfileInfo); const [user] = useState(localStorage.getItem('role_status') === '18' ? 'partner' : 'developer') - const [navInfo] = useState({ - developer: [ - { - path: '/summary', - name: 'Резюме' - }, - { - path: '/calendar', - name: 'Отчетность' - }, - { - path: '/tracker', - name: 'Трекер' - }, - { - path: '/payouts', - name: 'Выплаты' - }, - { - path: '/settings', - name: 'Настройки' - }, - ], - partner: [ - { - path: '/catalog', - name: 'Каталог' - }, - { - path: '/requests', - name: 'Запросы' - }, - { - path: '/categories', - name: 'Персонал' - }, - { - path: '/tracker', - name: 'Трекер' - }, - { - path: '/treaties', - name: 'Договора' - }, - { - path: '/settings', - name: 'Настройки' - }, - ] - }) const [isLoggingOut, setIsLoggingOut] = useState(false); @@ -113,29 +56,6 @@ export const ProfileHeader = () => {
-
-
- - -
-

- {user === 'developer' ? - profileInfo?.fio : - '' - } -

- - avatar - -
-
-
) }; diff --git a/src/components/ReportForm/ReportForm.js b/src/components/ReportForm/ReportForm.js index 20a6e550..b1a5f3f8 100644 --- a/src/components/ReportForm/ReportForm.js +++ b/src/components/ReportForm/ReportForm.js @@ -22,6 +22,7 @@ import arrow from "../../images/right-arrow.png"; import './reportForm.scss' import "react-datepicker/dist/react-datepicker.css"; +import { Navigation } from '../Navigation/Navigation' const ReportForm = () => { if(localStorage.getItem('role_status') === '18') { @@ -99,6 +100,7 @@ const ReportForm = () => { return (
+
{ + const [shadedStars, setShadedStars] = useState([]) + const [noShadedStars, setNoShadedStars] = useState([]) + const percent = (Math.abs(countActiveStars)) >= countStars ? 100 : (countActiveStars * 100 / countStars) + useEffect(() => { + for (let index = 0; index < countStars; index++) { + setShadedStars(prev => [...prev, '★']) + setNoShadedStars(prev => [...prev, '☆']) + } + }, []) + + const ratingStyle = { + "--size": size+'px' + } + const activeStyle = { + "--width": percent + '%', + "--color": color, + "--content": shadedStars.join('') + } + const bodyStyle = { + "--content": noShadedStars.join(''), + "--color": color + } + + return ( +
+
+
+
+ + + + + +
+
+
+ ) +} + +export default React.memo(StarRating); \ No newline at end of file diff --git a/src/components/StarRating/StarRating.scss b/src/components/StarRating/StarRating.scss new file mode 100644 index 00000000..913b35b6 --- /dev/null +++ b/src/components/StarRating/StarRating.scss @@ -0,0 +1,45 @@ +.rating{ + display: flex; + align-items: center; + font-size: var(--size); + line-height: 0.75; + &__body{ + position: relative; + &::before{ + content: attr(data-content); + display: block; + color: var(--color); + } + } + &__active{ + position: absolute; + height: 100%; + width: var(--width); + top: 0; + left: 0; + overflow: hidden; + &::before{ + content: attr(data-content); + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + color: var(--color); + } + } + &__items{ + display: flex; + position: absolute; + width: 100%; + height: 100%; + left: 0; + top: 0; + } + &__item{ + flex: 0 0 20%; + height: 100%; + opacity: 0; + } +} + diff --git a/src/components/features/Candidate-lk/HeadBottom.js b/src/components/features/Candidate-lk/HeadBottom.js new file mode 100644 index 00000000..b9a56e50 --- /dev/null +++ b/src/components/features/Candidate-lk/HeadBottom.js @@ -0,0 +1,14 @@ +import React from 'react' +import medium_male from "../../../images/medium_male.png" + +export const HeadBottom = () => { + return ( +
+
+
Мои тесты
+
+
+ +
+ ) +} diff --git a/src/components/features/quiz/AlertResult.js b/src/components/features/quiz/AlertResult.js new file mode 100644 index 00000000..ea796156 --- /dev/null +++ b/src/components/features/quiz/AlertResult.js @@ -0,0 +1,21 @@ +import React from 'react' +import suucessIcon from '../../../images/quiz/success.png' + +export const AlertResult = () => { + + const successTest = false + + return ( +
+
+ suucessIcon +
+ Благодарим Вас за прохождение теста "Junior разработчик". Ваши результаты проверены, готовы пригласить Вас в команду +
+
+ {!successTest &&
+ +
} +
+ ) +} diff --git a/src/components/features/quiz/BlockCompletedTest.js b/src/components/features/quiz/BlockCompletedTest.js new file mode 100644 index 00000000..0ca143ed --- /dev/null +++ b/src/components/features/quiz/BlockCompletedTest.js @@ -0,0 +1,24 @@ +import React from 'react' +import compltedImage from "../../../images/quiz/compltedImage.png" +import { Link } from 'react-router-dom' + +export const BlockCompletedTest = () => { + const id = localStorage.getItem('id') + return ( +
+
+
+ +
+
+ Спасибо!
+ Ваши ответы получены +
+
+ В течении дня в вашем кабинете будет отображены данные о прохождении тестирования +
+ В кабинет +
+
+ ) +} diff --git a/src/components/features/quiz/Card-introduction.js b/src/components/features/quiz/Card-introduction.js new file mode 100644 index 00000000..50dc9aa7 --- /dev/null +++ b/src/components/features/quiz/Card-introduction.js @@ -0,0 +1,19 @@ +import React from 'react' +import questionIcon from "../../../images/question.png" +import './quiz.scss' + +export const CardIntroduction = ({ title, description }) => { + return ( +
+
{title}
+
+
+ +
+
+ {description} +
+
+
+ ) +} diff --git a/src/components/features/quiz/CardAviableTest.js b/src/components/features/quiz/CardAviableTest.js new file mode 100644 index 00000000..cae6eff0 --- /dev/null +++ b/src/components/features/quiz/CardAviableTest.js @@ -0,0 +1,34 @@ +import React from 'react' +import { Link } from 'react-router-dom' +import rightArrow from "../../../images/arrowRight.png" +import StarRating from '../../StarRating/StarRating' + + +export const CardAvailableTest = ({ title, description, path, passedTest }) => { + + + return ( +
+ +
+ +

{title}

+
+
+

+
+ arrow +
+
+ + + {passedTest &&
+

+ Получить отчет по тестированию +

+ Отчет по тесту +
} +
+ ) +} + diff --git a/src/components/features/quiz/GetOptionTask.js b/src/components/features/quiz/GetOptionTask.js index d70f486b..8e35fc17 100644 --- a/src/components/features/quiz/GetOptionTask.js +++ b/src/components/features/quiz/GetOptionTask.js @@ -1,38 +1,38 @@ -import React from 'react'; +import React, { useEffect } from 'react'; +import { useSelector } from 'react-redux'; +import { selectedAnswersSelector, selectedTest } from '../../../redux/quizSlice'; + +export const GetOptionTask = ({ type, answer, handleChange, inputValue}) => { + + const id = localStorage.getItem('id'); + const dataTest = useSelector(selectedTest); + -export const GetOptionTask = ({type, answer, handleChange, inputValue}) => { switch (type) { - case "3": - return ( -
- - -
- ) - case "2": - case "4": - return ( -
- - -
- ) case "1": return ( -
-