From f2d7730214d16b1fe5af108df9df9c2a7384449e Mon Sep 17 00:00:00 2001 From: Dmitry220 Date: Wed, 19 Apr 2023 20:22:06 +0300 Subject: [PATCH 1/3] quiz + lk-candidate --- package-lock.json | 10 + package.json | 1 + src/App.js | 20 +- src/assets/global.scss | 25 + src/components/CardControl/CardControl.js | 20 + src/components/CardControl/CardControl.scss | 73 ++ .../CategoriesItem/categoriesItem.scss | 1 - src/components/Footer/footer.scss | 4 +- src/components/Navigation/Navigation.js | 101 ++ src/components/Navigation/Navigation.scss | 0 .../ProfileCalendar/ProfileCalendar.js | 2 + src/components/ProfileHeader/ProfileHeader.js | 76 +- src/components/ReportForm/ReportForm.js | 2 + src/components/StarRating/StarRating.js | 44 + src/components/StarRating/StarRating.scss | 45 + .../features/Candidate-lk/HeadBottom.js | 14 + src/components/features/quiz/AlertResult.js | 21 + .../features/quiz/BlockCompletedTest.js | 24 + .../features/quiz/Card-introduction.js | 19 + .../features/quiz/CardAviableTest.js | 34 + src/components/features/quiz/GetOptionTask.js | 56 +- src/components/features/quiz/HeaderQuiz.js | 4 +- .../features/quiz/Quiz-passing-information.js | 80 ++ src/components/features/quiz/QuizReport.js | 27 + .../features/quiz/SelectedCategory.js | 20 + src/components/features/quiz/Task.js | 199 ++- src/components/features/quiz/quiz.scss | 1086 +++++++++++------ src/images/icon-specialization.png | Bin 0 -> 2272 bytes src/images/note.png | Bin 0 -> 547 bytes src/images/question.png | Bin 0 -> 803 bytes src/images/quiz/accempt.png | Bin 0 -> 1185 bytes src/images/quiz/compltedImage.png | Bin 0 -> 2864 bytes src/images/quiz/success.png | Bin 0 -> 2298 bytes src/images/quiz/timer.png | Bin 0 -> 1125 bytes src/index.css | 2 +- .../AuthForCandidate/authForCandidate.scss | 22 +- src/pages/Home/Home.js | 2 + .../PartnerAddRequest/PartnerAddRequest.js | 2 + src/pages/PartnerBid/PartnerBid.js | 2 + src/pages/PartnerRequests/PartnerRequests.js | 2 + src/pages/PartnerSettings/PartnerSettings.js | 2 + src/pages/PartnerTreaties/PartnerTreaties.js | 2 + .../PartnerСategories/PartnerСategories.js | 2 + src/pages/Payouts/Payouts.js | 2 + src/pages/Profile/Profile.js | 40 +- src/pages/Profile/profile.scss | 128 +- .../ProfileCandidate/ProfileCandidate.js | 94 ++ .../ProfileCandidate/ProfileCandidate.scss | 166 +++ src/pages/Summary/Summary.js | 2 + src/pages/Tracker/Tracker.js | 2 + src/pages/ViewReport/ViewReport.js | 2 + src/pages/quiz/InstructionPage.js | 24 - src/pages/quiz/InterjacentPage.js | 26 - src/pages/quiz/PassingTests.js | 83 ++ src/pages/quiz/QuizPage.js | 147 ++- src/pages/quiz/QuizReportPage.js | 42 + src/pages/quiz/QuizTestPage.js | 24 - src/pages/quiz/ResultPage.js | 24 - src/pages/quiz/quiz-page.scss | 143 +++ src/redux/quizSlice.js | 89 +- 60 files changed, 2272 insertions(+), 812 deletions(-) create mode 100644 src/assets/global.scss create mode 100644 src/components/CardControl/CardControl.js create mode 100644 src/components/CardControl/CardControl.scss create mode 100644 src/components/Navigation/Navigation.js create mode 100644 src/components/Navigation/Navigation.scss create mode 100644 src/components/StarRating/StarRating.js create mode 100644 src/components/StarRating/StarRating.scss create mode 100644 src/components/features/Candidate-lk/HeadBottom.js create mode 100644 src/components/features/quiz/AlertResult.js create mode 100644 src/components/features/quiz/BlockCompletedTest.js create mode 100644 src/components/features/quiz/Card-introduction.js create mode 100644 src/components/features/quiz/CardAviableTest.js create mode 100644 src/components/features/quiz/Quiz-passing-information.js create mode 100644 src/components/features/quiz/QuizReport.js create mode 100644 src/components/features/quiz/SelectedCategory.js create mode 100644 src/images/icon-specialization.png create mode 100644 src/images/note.png create mode 100644 src/images/question.png create mode 100644 src/images/quiz/accempt.png create mode 100644 src/images/quiz/compltedImage.png create mode 100644 src/images/quiz/success.png create mode 100644 src/images/quiz/timer.png create mode 100644 src/pages/ProfileCandidate/ProfileCandidate.js create mode 100644 src/pages/ProfileCandidate/ProfileCandidate.scss delete mode 100644 src/pages/quiz/InstructionPage.js delete mode 100644 src/pages/quiz/InterjacentPage.js create mode 100644 src/pages/quiz/PassingTests.js create mode 100644 src/pages/quiz/QuizReportPage.js delete mode 100644 src/pages/quiz/QuizTestPage.js delete mode 100644 src/pages/quiz/ResultPage.js create mode 100644 src/pages/quiz/quiz-page.scss 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 738fec5f..97a29402 100644 --- a/src/App.js +++ b/src/App.js @@ -12,10 +12,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' @@ -30,9 +27,11 @@ import {PartnerTreaties} from "./pages/PartnerTreaties/PartnerTreaties"; 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'; @@ -57,11 +56,9 @@ const App = () => { }/> - }/> - }/> - }/> - }/> - }/> + }/> + }/> + }/> @@ -80,6 +77,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 5b46f629..e8842808 100644 --- a/src/components/Footer/footer.scss +++ b/src/components/Footer/footer.scss @@ -1,5 +1,5 @@ .footer { - margin-top: -3rem; + //margin-top: -3rem; &__left { display: flex; @@ -74,7 +74,7 @@ @media (max-width: 575.98px) { .footer { &__left { - margin-top: 80px; + // margin-top: 80px; } &__description { diff --git a/src/components/Navigation/Navigation.js b/src/components/Navigation/Navigation.js new file mode 100644 index 00000000..71449c78 --- /dev/null +++ b/src/components/Navigation/Navigation.js @@ -0,0 +1,101 @@ +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 } from '../../redux/outstaffingSlice'; + +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 270ad839..d6ede4b0 100644 --- a/src/components/ProfileHeader/ProfileHeader.js +++ b/src/components/ProfileHeader/ProfileHeader.js @@ -10,6 +10,7 @@ import {getRole} from "../../redux/roleSlice"; import {urlForLocal} from "../../helper"; import './profileHeader.scss' +import { Navigation } from '../Navigation/Navigation'; @@ -20,58 +21,8 @@ export const ProfileHeader = () => { 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); @@ -111,29 +62,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 ( -
-