Compare commits

..

No commits in common. "0134ab9662f9eb4daeb775555a94385061c390d5" and "fa01cf15551beed6530d35e30129782b3fc3de11" have entirely different histories.

15 changed files with 374 additions and 399 deletions

View File

@ -106,8 +106,8 @@ const App = () => {
<Route exact path="quiz"> <Route exact path="quiz">
<Route index element={<QuizPage />} /> <Route index element={<QuizPage />} />
<Route exact path="test/:uuid" element={<PassingTests />} /> <Route exact path="test" element={<PassingTests />} />
<Route exact path="report/:uuid" element={<QuizReportPage />} /> <Route exact path="report" element={<QuizReportPage />} />
</Route> </Route>
<Route exact path="profile"> <Route exact path="profile">
@ -133,7 +133,7 @@ const App = () => {
element={<PartnerEmployees />} element={<PartnerEmployees />}
/> />
</Route> </Route>
<Route exact path="profile-candidate/:id"> <Route exact path="profile-candidate/:id">
<Route index element={<ProfileCandidate />} /> <Route index element={<ProfileCandidate />} />

View File

@ -36,10 +36,6 @@ export const Navigation = () => {
path: "/payouts", path: "/payouts",
name: "Выплаты", name: "Выплаты",
}, },
{
path: "/quiz",
name: "Тесты",
},
{ {
path: "/settings", path: "/settings",
name: "Настройки", name: "Настройки",
@ -95,11 +91,7 @@ export const Navigation = () => {
<nav className="profileHeader__nav"> <nav className="profileHeader__nav">
{navInfo[user].map((link, index) => { {navInfo[user].map((link, index) => {
return ( return (
<NavLink <NavLink key={index} end to={`/profile${link.path}`}>
key={index}
end
to={link.path === "/quiz" ? link.path : `/profile${link.path}`}
>
{link.name} {link.name}
</NavLink> </NavLink>
); );

View File

@ -2,7 +2,7 @@ import React from "react";
import suucessIcon from "assets/images/quiz/success.png"; import suucessIcon from "assets/images/quiz/success.png";
export const AlertResult = ({ info }) => { export const AlertResult = () => {
const successTest = false; const successTest = false;
return ( return (
@ -17,7 +17,7 @@ export const AlertResult = ({ info }) => {
className="alert-result__text" className="alert-result__text"
style={{ color: successTest ? "#52B709" : "#5B6871" }} style={{ color: successTest ? "#52B709" : "#5B6871" }}
> >
Благодарим Вас за прохождение теста "{info.questionnaire_title}". Ваши Благодарим Вас за прохождение теста "Junior разработчик". Ваши
результаты проверены, готовы пригласить Вас в команду результаты проверены, готовы пригласить Вас в команду
</div> </div>
</div> </div>

View File

@ -5,19 +5,16 @@ import StarRating from "@components/StarRating/StarRating";
import rightArrow from "assets/icons/arrows/arrowRight.svg"; import rightArrow from "assets/icons/arrows/arrowRight.svg";
export const CardAvailableTest = ({ title, description, path, status }) => { export const CardAvailableTest = ({ title, description, path, passedTest }) => {
return ( return (
<div className="card-available-test"> <div className="card-available-test">
<Link <Link
to={status === 2 ? `/quiz/report/${path}` : `/quiz/test/${path}`} to={`/${path}`}
aria-disabled={true}
className="card-available-test__container" className="card-available-test__container"
style={ style={{
{ opacity: passedTest ? 0.3 : 1,
// opacity: status !== 1 ? 0.3 : 1, pointerEvents: passedTest ? "none" : "all",
// pointerEvents: status !== 1 ? "none" : "all", }}
}
}
> >
<div className="card-available-test__top-head"> <div className="card-available-test__top-head">
<StarRating /> <StarRating />
@ -30,10 +27,11 @@ export const CardAvailableTest = ({ title, description, path, status }) => {
</div> </div>
</div> </div>
</Link> </Link>
{status === 2 && (
{passedTest && (
<div className="card-available-test__finished"> <div className="card-available-test__finished">
<p>Получить отчет по тестированию</p> <p>Получить отчет по тестированию</p>
<Link to={`/quiz/report/${path}`}>Отчет по тесту</Link> <Link to={"/quiz/report"}>Отчет по тесту</Link>
</div> </div>
)} )}
</div> </div>

View File

@ -1,18 +1,44 @@
import React from "react"; import React from "react";
export const GetOptionTask = ({ type, answer, handleChange }) => { export const GetOptionTask = ({ type, answer, handleChange, inputValue }) => {
const { answer_body, id } = answer; switch (type) {
return ( case "1":
<div className="form-task__group" key={id}> return (
<input <div className="form-task__group">
className="form-task__check" <textarea
type={+type === 3 ? "checkbox" : "radio"} className="form-task__field"
value={answer_body} value={inputValue}
name={+type === 3 ? "checkbox" : "radio"} onChange={handleChange}
id={id} />
onChange={handleChange} </div>
/> );
<label htmlFor={id}>{answer_body}</label> case "3":
</div> return (
); <div className="form-task__group" key={answer.id}>
<input
className="form-task__check"
type="checkbox"
value={answer.answer_body}
id={answer.id}
onChange={handleChange}
/>
<label htmlFor={answer.id}>{answer.answer_body}</label>
</div>
);
default:
return (
<div className="form-task__group" key={answer.id}>
<input
className="form-task__check"
type="radio"
value={answer.answer_body}
name={"radio"}
id={answer.id}
onChange={handleChange}
/>
<label htmlFor={answer.id}>{answer.answer_body}</label>
</div>
);
}
}; };

View File

@ -1,7 +1,7 @@
import React from "react"; import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { selectUserInfo } from "@redux/quizSlice"; import { selectUserInfo, setUserInfo } from "@redux/quizSlice";
import { urlForLocal } from "@utils/helper"; import { urlForLocal } from "@utils/helper";
@ -13,6 +13,15 @@ export const HeaderQuiz = ({ header }) => {
const userId = localStorage.getItem("id"); const userId = localStorage.getItem("id");
const userInfo = useSelector(selectUserInfo); const userInfo = useSelector(selectUserInfo);
useEffect(() => {
dispatch(setUserInfo(userId));
}, [userId, dispatch]);
useEffect(() => {
// apiRequest(`/user-questionnaire/questionnaires-list?user_id=${userId}`)
// .then(res => dispatch(setQuestionnairesList(res)))
}, [userId, dispatch]);
return ( return (
<div> <div>
{userInfo?.status === 500 ? ( {userInfo?.status === 500 ? (

View File

@ -1,71 +1,36 @@
import moment from "moment";
import React, { useEffect } from "react"; import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useNavigate } from "react-router-dom"; import { useTimer } from "react-timer-hook";
import { setQuestions } from "@redux/quizSlice"; import { completedTestSelector } from "@redux/quizSlice";
import { apiRequest } from "@api/request";
import { useNotification } from "@hooks/useNotification";
import StarRating from "@components/StarRating/StarRating"; import StarRating from "@components/StarRating/StarRating";
import accempt from "assets/images/quiz/accempt.png"; import accempt from "assets/images/quiz/accempt.png";
import iconTomer from "assets/images/quiz/timer.png"; import timer from "assets/images/quiz/timer.png";
export const QuizPassingInformation = ({ setStartTest, uuid, timer }) => { export const QuizPassingInformation = ({ expiryTimestamp, setStartTest }) => {
const { restart, pause, hours, minutes, seconds, isRunning } = timer; const { seconds, minutes, isRunning, start, restart } = useTimer({
const navigate = useNavigate(); expiryTimestamp,
const { showNotification } = useNotification(); autoStart: false,
const dispatch = useDispatch(); onExpire: () => {
console.warn("onExpire called");
},
});
const completedTest = useSelector(completedTestSelector);
const startTesting = () => { const startTesting = () => {
apiRequest(`/question/get-questions?uuid=${uuid}`) setStartTest(true);
.then((res) => { start();
if (res.status === 400) {
dispatch(setQuestions(null));
showNotification({
show: true,
text: res?.message || "",
type: "error",
});
return;
}
dispatch(setQuestions(res));
setStartTest(true);
restart(
moment()
.add(res[0]?.time_limit.split(":")[0], "hours")
.add(res[0]?.time_limit.split(":")[1], "minutes")
.add(res[0]?.time_limit.split(":")[2], "seconds"),
true
);
})
.catch((e) => {
dispatch(setQuestions(null));
});
}; };
const checkTest = () => useEffect(() => {
apiRequest( if (completedTest) {
`user-questionnaire/questionnaire-completed?user_questionnaire_uuid=${uuid}` const time = new Date();
); time.setSeconds(time.getSeconds() + 0); //600 - кол-во секунд для прохождения теста
restart(time, false);
const completeTest = () => }
apiRequest("/user-questionnaire/questionnaire-completed", { }, [completedTest]);
method: "POST",
});
const finishQuiz = async () => {
Promise.all([checkTest, completeTest])
.then(function () {
pause();
})
.catch((e) => {
console.log(e);
});
};
return ( return (
<div className="quiz-passing-information"> <div className="quiz-passing-information">
@ -83,38 +48,32 @@ export const QuizPassingInformation = ({ setStartTest, uuid, timer }) => {
разработчик разработчик
</div> </div>
</div> </div>
{isRunning && ( <div className="quiz-passing-information__timer timer-quiz">
<div className="quiz-passing-information__timer timer-quiz"> <div className="quiz-passing-information__icon">
<div className="quiz-passing-information__icon"> <img src={timer} alt="" />
<img src={iconTomer} alt="" />
</div>
<div className="quiz-passing-information__text">
Время на прохождение теста:
<br />
<span>
{hours.toString().padStart(2, "0") +
":" +
minutes.toString().padStart(2, "0") +
":" +
seconds.toString().padStart(2, "0")}
секунд
</span>
</div>
</div> </div>
)} <div className="quiz-passing-information__text">
{!isRunning && ( {completedTest ? "Время вышло" : "Время на прохождение теста:"}{" "}
<div className="quiz-passing-information__attempt"> <br />
<div className="quiz-passing-information__icon"> <span>
<img src={accempt} alt="" /> {minutes.toString().padStart(2, "0") +
</div> ":" +
<div className="quiz-passing-information__text"> seconds.toString().padStart(2, "0")}{" "}
Попыток прохождения: <br /> секунд
<span>1 попытка</span> </span>
</div>
</div> </div>
)} </div>
<div className="quiz-passing-information__attempt">
<div className="quiz-passing-information__icon">
<img src={accempt} alt="" />
</div>
<div className="quiz-passing-information__text">
Попыток прохождения: <br />
<span>1 попытка</span>
</div>
</div>
<div> <div>
{!isRunning && ( {!completedTest && !isRunning && (
<button <button
className="quiz-passing-information__button btn-green" className="quiz-passing-information__button btn-green"
onClick={startTesting} onClick={startTesting}
@ -123,15 +82,9 @@ export const QuizPassingInformation = ({ setStartTest, uuid, timer }) => {
</button> </button>
)} )}
</div> </div>
{isRunning && (
<button
className="quiz-passing-information__button quiz-btn"
onClick={finishQuiz}
>
Завершить
</button>
)}
</div> </div>
{/* {isRunning && <button className="quiz-passing-information__button quiz-btn" onClick={pause}>Завершить</button>} */}
</div> </div>
</div> </div>
); );

View File

@ -2,13 +2,7 @@ import React from "react";
import StarRating from "@components/StarRating/StarRating"; import StarRating from "@components/StarRating/StarRating";
export const QuizReport = ({ info }) => { export const QuizReport = () => {
function correctAnswers() {
return info.number_questions * info.percent_correct_answers;
}
function correctWrongAnswers() {
return info.number_questions * (1 - info.percent_correct_answers);
}
return ( return (
<div className="report"> <div className="report">
<div className="report__row"> <div className="report__row">
@ -19,18 +13,16 @@ export const QuizReport = ({ info }) => {
countActiveStars={0.5} countActiveStars={0.5}
size={61} size={61}
/> />
<div className="report__job-title">{info.questionnaire_title}</div> <div className="report__job-title">
Junior <br /> разработчик
</div>
</div> </div>
<div className="report__column"> <div className="report__column">
<div className="report__value"> <div className="report__value">22</div>
{Boolean(correctAnswers()) ? correctAnswers() : 0}
</div>
<div className="report__text">Правильных ответов</div> <div className="report__text">Правильных ответов</div>
</div> </div>
<div className="report__column"> <div className="report__column">
<div className="report__value report__value_false"> <div className="report__value report__value_false">02</div>
{Boolean(correctWrongAnswers()) ? correctWrongAnswers() : 0}
</div>
<div className="report__text">Не правильных ответов</div> <div className="report__text">Не правильных ответов</div>
</div> </div>
<div className="report__column"> <div className="report__column">

View File

@ -1,158 +1,148 @@
import moment from "moment"; import React, { useEffect, useState } from "react";
import React, { useState } from "react"; import { useDispatch, useSelector } from "react-redux";
import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import { questionsSelector } from "@redux/quizSlice"; import {
answersSelector,
fetchGetAnswers, // fetchUserAnswerOne,
// fetchUserAnswersMany,
questionsSelector,
selectedTest, // setAnswers,
setCompleteTest,
} from "@redux/quizSlice";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import { useHandlerFieldTest } from "@hooks/useHandlerFieldTest";
import { useNotification } from "@hooks/useNotification";
import { Loader } from "@components/Common/Loader/Loader";
import questionIcon from "assets/images/question.png"; import questionIcon from "assets/images/question.png";
import { GetOptionTask } from "./GetOptionTask"; import { GetOptionTask } from "./GetOptionTask";
// import { HeaderQuiz } from "./HeaderQuiz";
// import { Progressbar } from "./ProgressbarQuiz";
import "./quiz.scss"; import "./quiz.scss";
export const TaskQuiz = ({ timer }) => { export const TaskQuiz = () => {
const navigate = useNavigate(); const dispatch = useDispatch();
const { restart } = timer;
const { uuid } = useParams();
const userId = localStorage.getItem("id");
const questions = useSelector(questionsSelector);
const [index, setIndex] = useState(0);
const [isLoadingSendAnswers] = useState(false);
const { showNotification } = useNotification();
const { userResponses, handleChange } = useHandlerFieldTest({ const answers = useSelector(answersSelector);
questions, const questions = useSelector(questionsSelector);
indexQuestion: index,
}); 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");
useEffect(() => {
// fetch('https://itguild.info/api/user-questionnaire/questionnaires-list?user_id=110').then(response => response.json())
// .then(json => console.log(json))
apiRequest(`/question/get-questions?uuid=${dataTest.uuid}`).then(
(response) => {
dispatch(fetchGetAnswers(response[0].id));
setStripValue(((+index + 1) * 100) / response.length);
}
);
}, [dispatch]);
const nextQuestion = async (e) => { const nextQuestion = async (e) => {
e.preventDefault(); e.preventDefault();
//Проверка на существование овтетов //Проверка на валидацию ответов
if (!userResponses[index]) { if (!(checkedValues.length || inputValue)) {
alert("Вы не ответили на вопрос"); alert("Вы не ответили на вопрос");
return; return;
} }
// setLoadingSendAnswers(true); //отправка ответов на сервер
// .finally(() => setLoadingSendAnswers(false)); if (questions[index].question_type_id != 3) {
//dispatch(fetchUserAnswerOne(checkedValues));
// отправка ответов на сервер } else {
if (questions.length === userResponses.length) { console.log(checkedValues);
await apiRequest(`/user-response/set-responses`, { // dispatch(fetchUserAnswersMany(checkedValues));
method: "POST",
data: {
user_id: userId,
user_questionnaire_uuid: uuid,
userResponses: JSON.stringify(userResponses),
},
}).then(() => {
showNotification({
show: true,
text: "Тест успешно пройден",
type: "success",
});
navigate("/quiz");
// if (String(res?.status)[0] !== "2") {
// showNotification({
// show: true,
// text: res?.message || "",
// type: "error",
// });
// return;
// }
});
// .catch((e) => {
// showNotification({
// show: true,
// text: e?.message || "",
// type: "error",
// });
// })
} }
//установка таймера на вопрос если он существует //Проверка на окончание теста
if (questions[index + 1]?.time_limit !== "00:00:00") setValueTimer(); if (!(index < questions.length - 1)) {
dispatch(setCompleteTest());
return;
}
// переход на следующий вопрос dispatch(fetchGetAnswers(questions[index + 1].id));
setIndex((prev) => (questions[prev + 1] ? prev + 1 : prev)); setIndex((prev) => prev + 1);
setCheckedValues([]);
setInputValue("");
}; };
const complete = (e) => { const handleChange = (e) => {
e.preventDefault(); const checked = e.target.checked;
if (questions[index].question_type_id != 3) {
setCheckedValues([
{
user_id: id,
user_questionnaire_uuid: dataTest.uuid,
question_id: questions[index].id,
response_body: e.target.value,
},
]);
return;
}
checked
? setCheckedValues((prev) => [
...prev,
{
user_id: id,
user_questionnaire_uuid: dataTest.uuid,
question_id: questions[index].id,
response_body: e.target.value,
},
])
: setCheckedValues((prev) => [
...prev.filter((item) => item.response_body !== e.target.value),
]);
}; };
const setValueTimer = () => { console.log("render task");
const time_limit = questions[index + 1].time_limit.split(":");
restart(
moment()
.add(time_limit[0], "hours")
.add(time_limit[1], "minutes")
.add(time_limit[2], "seconds")
);
};
return ( return (
<div className="task"> <div className="task">
{questions ? ( {
<div className="task__container"> <div className="task__container">
<div className="task__header"> <div className="task__header">
<img src={questionIcon} alt="questionIcon" /> <img src={questionIcon} alt="" />
<h3 className="task__title quiz-title_h3"> <h3 className="task__title quiz-title_h3">
{questions[index].question_body} {questions[index].question_body}
</h3> </h3>
</div> </div>
<div className="task__body"> <div className="task__body">
<form <form className="task__form form-task" onSubmit={nextQuestion}>
className="task__form form-task" {answers.map((answer) => (
onSubmit={ <GetOptionTask
index !== questions.length - 1 ? nextQuestion : complete key={answer.id}
} type={questions[index].question_type_id}
> handleChange={handleChange}
{questions[index].question_type_id === 1 ? ( answer={answer}
<div className="form-task__group"> />
<textarea ))}
className="form-task__field"
onChange={handleChange}
/>
</div>
) : (
questions[index]?.answers?.map((answer) => (
<GetOptionTask
key={answer.id}
type={questions[index].question_type_id}
handleChange={handleChange}
answer={answer}
/>
))
)}
<div className="form-task__buttons"> <div className="form-task__buttons">
<button {/* {
onClick={nextQuestion} index != 0 && <button type='submit' className='form-task__btn quiz-btn quiz-btn_back'
// disabled={isLoadingSendAnswers} onClick={prevQuestion}>Назад</button>
className="form-task__btn quiz-btn" } */}
> {index != questions.length && (
{isLoadingSendAnswers ? ( <button
<Loader width={25} height={25} /> onClick={nextQuestion}
) : index !== questions.length - 1 ? ( className="form-task__btn quiz-btn"
"Далее" >
) : ( Далее
"Завершить" </button>
)} )}
</button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
) : ( }
<h1>ОШибка</h1>
)}
</div> </div>
); );
}; };

View File

@ -1,32 +0,0 @@
import { useState } from "react";
export const useHandlerFieldTest = ({ questions, indexQuestion }) => {
const [userResponses, setUserResponses] = useState([]);
const handleChangeCheckbox = (e) => {
setUserResponses((prev) => [
...prev.filter(
(item) => item.question_id !== questions[indexQuestion].id
),
{
question_id: questions[indexQuestion].id,
response_body: e.target.value,
answer_id: e.target.id ? e.target.id : questions[indexQuestion].id,
},
]);
};
// const handleFieldsForm = (e) => {
// setValues([
// {
// user_id: id,
// user_questionnaire_uuid: uuid,
// question_id: questions[indexQuestion].id,
// response_body: e.target.value,
// },
// ]);
// };
const handleChange = (e) => {
handleChangeCheckbox(e);
};
return { handleChange, userResponses };
};

View File

@ -1,43 +1,24 @@
import moment from "moment"; import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { Link, useNavigate, useParams } from "react-router-dom"; import { Link } from "react-router-dom";
import { useTimer } from "react-timer-hook";
import { completedTestSelector } from "@redux/quizSlice"; import { completedTestSelector } from "@redux/quizSlice";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader"; import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
// import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom"; import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom";
import { BlockCompletedTest } from "@components/features/quiz/BlockCompletedTest"; import { BlockCompletedTest } from "@components/features/quiz/BlockCompletedTest";
import { CardIntroduction } from "@components/features/quiz/Card-introduction"; import { CardIntroduction } from "@components/features/quiz/Card-introduction";
import { QuizPassingInformation } from "@components/features/quiz/Quiz-passing-information"; import { QuizPassingInformation } from "@components/features/quiz/Quiz-passing-information";
import { TaskQuiz } from "@components/features/quiz/Task"; import { TaskQuiz } from "@components/features/quiz/Task";
export const PassingTests = () => { export const PassingTests = () => {
const time = new Date();
time.setSeconds(time.getSeconds() + 600); //600 - кол-во секунд для прохождения теста
const [startTest, setStartTest] = useState(false); const [startTest, setStartTest] = useState(false);
const navigate = useNavigate();
const completedTest = useSelector(completedTestSelector); const completedTest = useSelector(completedTestSelector);
const { uuid } = useParams();
const timer = useTimer({
expiryTimestamp: moment(),
autoStart: false,
onExpire: () => {
navigate("/quiz");
},
});
const onCloseWindow = (e) => {
e.preventDefault();
if (startTest) {
let confirmationMessage = "o/";
(e || window.e).returnValue = confirmationMessage;
return confirmationMessage;
}
};
const introduction = [ const introduction = [
{ {
@ -57,30 +38,10 @@ export const PassingTests = () => {
}, },
]; ];
function onSwitchTab(e) {
console.log(e, document.visibilityState);
if (document.visibilityState === "hidden" && startTest) {
alert(
"Убедительная просьба не покидать страницу и не переключаться. Рассчитывайте только на свои знания и умения!!!"
);
}
}
useEffect(() => {
window.addEventListener("beforeunload", onCloseWindow);
window.addEventListener("visibilitychange", onSwitchTab);
window.onblur = onSwitchTab;
return () => {
window.removeEventListener("beforeunload", onCloseWindow);
window.removeEventListener("visibilitychange", onSwitchTab);
};
}, [startTest]);
return ( return (
<div className="passing-tests-page"> <div className="passing-tests-page">
<ProfileHeader /> <ProfileHeader />
<Navigation /> <HeadBottom />
{/*<HeadBottom />*/}
<div className="passing-tests-page__container"> <div className="passing-tests-page__container">
<ProfileBreadcrumbs <ProfileBreadcrumbs
links={[ links={[
@ -90,13 +51,12 @@ export const PassingTests = () => {
]} ]}
/> />
<div className="passing-tests-page__title main-title"> <div className="passing-tests-page__title main-title">
Тестирование в позиции Junior разработчик Тестирование в позиции Junior разработчик{" "}
</div> </div>
<div className="passing-tests-page__passing-information"> <div className="passing-tests-page__passing-information">
<QuizPassingInformation <QuizPassingInformation
timer={timer} expiryTimestamp={time}
setStartTest={setStartTest} setStartTest={setStartTest}
uuid={uuid}
/> />
</div> </div>
@ -108,7 +68,7 @@ export const PassingTests = () => {
</div> </div>
)} )}
{startTest ? ( {startTest ? (
<TaskQuiz timer={timer} /> <TaskQuiz />
) : ( ) : (
<div className="passing-tests-page__introduction"> <div className="passing-tests-page__introduction">
{introduction.map((item, i) => ( {introduction.map((item, i) => (
@ -138,11 +98,6 @@ export const PassingTests = () => {
)} )}
</div> </div>
<Footer /> <Footer />
{/*<Prompt*/}
{/* when={showPrompt}*/}
{/* message="Unsaved changes detected, continue?"*/}
{/* beforeUnload={true}*/}
{/*/>*/}
</div> </div>
); );
}; };

View File

@ -2,15 +2,15 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
// import { questionnairesSelector, setQuestionnaires } from "@redux/quizSlice"; import { questionnairesSelector, setQuestionnaires } from "@redux/quizSlice";
import { apiRequest } from "@api/request"; import { apiRequest } from "@api/request";
import CategoriesItem from "@components/CategoriesItem/CategoriesItem"; import CategoriesItem from "@components/CategoriesItem/CategoriesItem";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader"; import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
// import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom"; import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom";
import { CardAvailableTest } from "@components/features/quiz/CardAviableTest"; import { CardAvailableTest } from "@components/features/quiz/CardAviableTest";
import { SelectedCategory } from "@components/features/quiz/SelectedCategory"; import { SelectedCategory } from "@components/features/quiz/SelectedCategory";
@ -27,7 +27,7 @@ import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg";
import "./quiz-page.scss"; import "./quiz-page.scss";
export const QuizPage = () => { export const QuizPage = () => {
const [questionnaires, setQuestionnaires] = useState([]); const questionnaires = useSelector(questionnairesSelector);
const dispatch = useDispatch(); const dispatch = useDispatch();
const [personalInfoItems] = useState([ const [personalInfoItems] = useState([
{ {
@ -99,19 +99,18 @@ export const QuizPage = () => {
}, },
]); ]);
const userId = localStorage.getItem("id"); const userId = localStorage.getItem("id");
const [selectedCategory, setSetSelectedCategory] = useState(false); const [selectedCategory, setsetSelectedCategory] = useState(false);
useEffect(() => { useEffect(() => {
apiRequest(`/user-questionnaire/questionnaires-list?user_id=${userId}`) apiRequest(
.then((res) => setQuestionnaires(res)) `/user-questionnaire/questionnaires-list?user_id=${userId}`
.catch((e) => console.log(e)); ).then((res) => dispatch(setQuestionnaires(res)));
}, []); }, []);
return ( return (
<div className="quiz-page"> <div className="quiz-page">
<ProfileHeader /> <ProfileHeader />
<Navigation /> <HeadBottom />
{/*<HeadBottom />*/}
<div className="quiz-page__container"> <div className="quiz-page__container">
<ProfileBreadcrumbs <ProfileBreadcrumbs
links={[ links={[
@ -125,15 +124,17 @@ export const QuizPage = () => {
{!selectedCategory && ( {!selectedCategory && (
<> <>
<div className="quiz-page__specialization"> <div className="quiz-page__specialization">
<SelectedCategory setSelectedCategory={setSetSelectedCategory} /> <SelectedCategory setSelectedCategory={setsetSelectedCategory} />
</div> </div>
<div className="quiz-page__block">Доступные тесты</div> <div className="quiz-page__block">Доступные тесты</div>
<div className="quiz-page__cards-test"> <div className="quiz-page__cards-test">
{questionnaires.length ? ( {questionnaires.length ? (
questionnaires.map((item, index) => ( questionnaires.map((item, index) => (
<CardAvailableTest <CardAvailableTest
description={item.description} description={
path={item.uuid} "Вы новичок с реальным опытом работы до 1 года, или без опыта"
}
path={"quiz/test"}
status={item.status} status={item.status}
title={item.questionnaire_title} title={item.questionnaire_title}
passedTest={item.passedTest} passedTest={item.passedTest}
@ -150,6 +151,7 @@ export const QuizPage = () => {
</div> </div>
</> </>
)} )}
{selectedCategory && ( {selectedCategory && (
<div className="quiz-page__categories-items"> <div className="quiz-page__categories-items">
{personalInfoItems.map((item, index) => { {personalInfoItems.map((item, index) => {

View File

@ -1,43 +1,28 @@
import React, { useEffect, useState } from "react"; import React from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { selectedTest } from "@redux/quizSlice"; import { selectedTest } from "@redux/quizSlice";
import { apiRequest } from "@api/request";
import { Footer } from "@components/Common/Footer/Footer"; import { Footer } from "@components/Common/Footer/Footer";
import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs"; import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader"; import { ProfileHeader } from "@components/ProfileHeader/ProfileHeader";
// import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom"; import { HeadBottom } from "@components/features/Candidate-lk/HeadBottom";
import { AlertResult } from "@components/features/quiz/AlertResult"; import { AlertResult } from "@components/features/quiz/AlertResult";
import { QuizReport } from "@components/features/quiz/QuizReport"; import { QuizReport } from "@components/features/quiz/QuizReport";
export const QuizReportPage = () => { export const QuizReportPage = () => {
const test = useSelector(selectedTest); const test = useSelector(selectedTest);
const params = useParams();
let navigate = useNavigate(); let navigate = useNavigate();
if (!test) { if (!test) {
navigate("/quiz"); navigate("/quiz");
} }
useEffect(() => {
apiRequest(
`/user-questionnaire/questionnaire-completed?user_questionnaire_uuid=${params.uuid}`
).then((res) => {
setTestInfo(res);
});
}, []);
const [testInfo, setTestInfo] = useState({});
return ( return (
<div className="quiz-report-page"> <div className="quiz-report-page">
<ProfileHeader /> <ProfileHeader />
<Navigation /> <HeadBottom />
{/*<HeadBottom />*/}
<div className="quiz-report-page__container"> <div className="quiz-report-page__container">
<ProfileBreadcrumbs <ProfileBreadcrumbs
links={[ links={[
@ -47,12 +32,13 @@ export const QuizReportPage = () => {
]} ]}
/> />
<div className="quiz-report-page__title main-title"> <div className="quiz-report-page__title main-title">
Отчет по тестированию позиции {testInfo.questionnaire_title} Отчет по тестированию позиции Junior разработчик{" "}
</div> </div>
<div className="quiz-report-page__report-quiz"> <div className="quiz-report-page__report-quiz">
<QuizReport info={testInfo} /> <QuizReport />
</div> </div>
<AlertResult info={testInfo} />
<AlertResult />
</div> </div>
<Footer /> <Footer />
</div> </div>

View File

@ -7,7 +7,7 @@
flex-direction: column; flex-direction: column;
&__container { &__container {
max-width: 1160px; max-width: 1160px;
margin: 23px auto 42px auto; margin: 0 auto 42px auto;
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;
padding: 0 15px; padding: 0 15px;
@ -68,7 +68,7 @@
} }
&__container { &__container {
max-width: 1160px; max-width: 1160px;
margin: 23px auto 42px auto; margin: 0 auto 42px auto;
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;
padding: 0 15px; padding: 0 15px;
@ -90,7 +90,7 @@
flex-direction: column; flex-direction: column;
&__container { &__container {
max-width: 1160px; max-width: 1160px;
margin: 23px auto 42px auto; margin: 0 auto 42px auto;
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;
padding: 0 15px; padding: 0 15px;
@ -125,7 +125,7 @@
flex-direction: column; flex-direction: column;
&__container { &__container {
max-width: 1160px; max-width: 1160px;
margin: 23px auto 42px auto; margin: 0 auto 42px auto;
flex: 1 1 auto; flex: 1 1 auto;
width: 100%; width: 100%;
padding: 0 15px; padding: 0 15px;

View File

@ -1,15 +1,105 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit"; import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import moment from "moment";
import { apiRequest } from "@api/request"; import { apiRequest } from "../api/request";
const initialState = { const initialState = {
questions: null, answers: [
{
id: "12",
question_id: "7",
answer_body:
"Нsdf sfd fds sdf sf sfsdf sdfеск вsdffsdfsdf sf sdf sdfsdfsdfsdfdsjknsdkf dssdjf sdfbsdhf sd hjdsfv sdhjvар1 отв1 истина",
},
{
id: "23",
question_id: "7",
answer_body: "Неск вар1 отв1 истина",
},
{
id: "233",
question_id: "7",
answer_body: "lorem sdfdsf dfs sdf ",
},
],
questionnaires: [], questionnaires: [],
questions: [
{
id: "4",
question_type_id: "3",
question_body:
"Для чего в Python используется встроенная функция enumerate()?",
question_priority: null,
next_question: null,
time_limit: "00:22:00",
},
{
id: "24",
question_type_id: "3",
question_body: "Для чего в Python dfsf троенная функция enumerate()?",
question_priority: null,
next_question: null,
time_limit: "00:22:00",
},
{
id: "41",
question_type_id: "3",
question_body: "Для чегоsdfsdfя функция enumerate()?",
question_priority: null,
next_question: null,
time_limit: "00:22:00",
},
{
id: "5",
question_type_id: "2",
question_body: "Один ответ2",
question_priority: null,
next_question: null,
time_limit: "00:22:00",
},
],
selectedTest: {
user_id: 1,
uuid: "d222f858-60fd-47fb-8731-dc9d5fc384c5",
score: 11,
status: 2,
percent_correct_answers: 0.25,
testing_date: "2022-03-17 11:14:22",
questionnaire_title: "Кат1 Анкета 1 активна",
},
selectedAnswers: {},
completedTest: false, completedTest: false,
selectedTest: {},
result: null, result: null,
isLoading: false,
dataQuestionnairesOfUser: [],
passedTests: [],
userInfo: null,
}; };
export const setUserInfo = createAsyncThunk("userInfo", (id) =>
apiRequest(`/profile/get-main-data?user_id=${id}`)
);
export const fetchUserAnswersMany = createAsyncThunk(
"answersUserMany",
(checkedValues) =>
apiRequest("/user-response/set-responses", {
method: "POST",
data: { userResponses: checkedValues },
})
);
export const fetchUserAnswerOne = createAsyncThunk(
"answersUserOne",
(checkedValues) =>
apiRequest("/user-response/set-response", {
method: "POST",
data: checkedValues[0],
})
);
export const fetchGetAnswers = createAsyncThunk("answers", (question_id) =>
apiRequest(`/answer/get-answers?question_id=${question_id}`)
);
export const fetchResultTest = createAsyncThunk("result", (uuid) => export const fetchResultTest = createAsyncThunk("result", (uuid) =>
apiRequest( apiRequest(
@ -21,27 +111,41 @@ export const quizSlice = createSlice({
name: "quiz", name: "quiz",
initialState, initialState,
reducers: { reducers: {
setQuestions: (state, action) => { setQuestionnaires: (state, action) => {
state.questions = action.payload; state.questionnaires = action.payload;
},
setSelectedTest: (state, action) => {
state.selectedTest = action.payload;
}, },
setCompleteTest: (state) => { setCompleteTest: (state) => {
state.completedTest = true; state.completedTest = true;
}, },
}, },
extraReducers: { extraReducers: {
[setUserInfo.fulfilled]: (state, action) => {
state.userInfo = action.payload;
},
[fetchGetAnswers.fulfilled]: (state, action) => {
state.answer = action.payload;
},
[fetchResultTest.fulfilled]: (state, action) => { [fetchResultTest.fulfilled]: (state, action) => {
state.result = action.payload; state.result = action.payload;
}, },
}, },
}); });
export const { setQuestions } = quizSlice.actions; export const { setQuestionnaires, setSelectedTest, setCompleteTest } =
quizSlice.actions;
export const answersSelector = (state) => state.quiz.answers;
export const questionnairesSelector = (state) => state.quiz.questionnaires; export const questionnairesSelector = (state) => state.quiz.questionnaires;
export const selectedAnswersSelector = (state) => state.quiz.selectedAnswers;
export const questionsSelector = (state) => state.quiz.questions; export const questionsSelector = (state) => state.quiz.questions;
export const completedTestSelector = (state) => state.quiz.completedTest; export const completedTestSelector = (state) => state.quiz.completedTest;
export const selectResult = (state) => state.quiz.result; export const selectResult = (state) => state.quiz.result;
export const selectedTest = (state) => state.quiz.selectedTest; export const selectedTest = (state) => state.quiz.selectedTest;
export const selectPassedTests = (state) => state.quiz.passedTests;
export const selectUserInfo = (state) => state.quiz.userInfo;
export default quizSlice.reducer; export default quizSlice.reducer;