diff --git a/src/components/features/quiz/Task.js b/src/components/features/quiz/Task.js
index a07faa65..075bfe70 100644
--- a/src/components/features/quiz/Task.js
+++ b/src/components/features/quiz/Task.js
@@ -1,148 +1,158 @@
-import React, { useEffect, useState } from "react";
-import { useDispatch, useSelector } from "react-redux";
+import moment from "moment";
+import React, { useState } from "react";
+import { useSelector } from "react-redux";
+import { useNavigate, useParams } from "react-router-dom";
-import {
- answersSelector,
- fetchGetAnswers, // fetchUserAnswerOne,
- // fetchUserAnswersMany,
- questionsSelector,
- selectedTest, // setAnswers,
- setCompleteTest,
-} from "@redux/quizSlice";
+import { questionsSelector } from "@redux/quizSlice";
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 { GetOptionTask } from "./GetOptionTask";
-// import { HeaderQuiz } from "./HeaderQuiz";
-// import { Progressbar } from "./ProgressbarQuiz";
import "./quiz.scss";
-export const TaskQuiz = () => {
- const dispatch = useDispatch();
-
- const answers = useSelector(answersSelector);
+export const TaskQuiz = ({ timer }) => {
+ const navigate = useNavigate();
+ const { restart } = timer;
+ const { uuid } = useParams();
+ const userId = localStorage.getItem("id");
const questions = useSelector(questionsSelector);
-
- const dataTest = useSelector(selectedTest);
const [index, setIndex] = useState(0);
- const [checkedValues, setCheckedValues] = useState([]);
- //const [stripValue, setStripValue] = useState(0);
- const [inputValue, setInputValue] = useState("");
+ const [isLoadingSendAnswers] = useState(false);
+ const { showNotification } = useNotification();
- 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 { userResponses, handleChange } = useHandlerFieldTest({
+ questions,
+ indexQuestion: index,
+ });
const nextQuestion = async (e) => {
e.preventDefault();
- //Проверка на валидацию ответов
- if (!(checkedValues.length || inputValue)) {
+ //Проверка на существование овтетов
+ if (!userResponses[index]) {
alert("Вы не ответили на вопрос");
return;
}
- //отправка ответов на сервер
- if (questions[index].question_type_id != 3) {
- //dispatch(fetchUserAnswerOne(checkedValues));
- } else {
- console.log(checkedValues);
- // dispatch(fetchUserAnswersMany(checkedValues));
- }
+ // setLoadingSendAnswers(true);
+ // .finally(() => setLoadingSendAnswers(false));
- //Проверка на окончание теста
- if (!(index < questions.length - 1)) {
- dispatch(setCompleteTest());
- return;
- }
-
- dispatch(fetchGetAnswers(questions[index + 1].id));
- setIndex((prev) => prev + 1);
- setCheckedValues([]);
- setInputValue("");
- };
-
- const handleChange = (e) => {
- 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,
+ // отправка ответов на сервер
+ if (questions.length === userResponses.length) {
+ await apiRequest(`/user-response/set-responses`, {
+ method: "POST",
+ data: {
+ user_id: userId,
+ user_questionnaire_uuid: uuid,
+ userResponses: JSON.stringify(userResponses),
},
- ]);
- return;
+ }).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",
+ // });
+ // })
}
- 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),
- ]);
+ //установка таймера на вопрос если он существует
+ if (questions[index + 1]?.time_limit !== "00:00:00") setValueTimer();
+
+ // переход на следующий вопрос
+ setIndex((prev) => (questions[prev + 1] ? prev + 1 : prev));
};
- console.log("render task");
+ const complete = (e) => {
+ e.preventDefault();
+ };
+
+ const setValueTimer = () => {
+ 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 (
- {
+ {questions ? (
-
+
{questions[index].question_body}
-
- }
+ ) : (
+
ОШибка
+ )}
);
};
diff --git a/src/hooks/useHandlerFieldTest.js b/src/hooks/useHandlerFieldTest.js
new file mode 100644
index 00000000..e8fdadfd
--- /dev/null
+++ b/src/hooks/useHandlerFieldTest.js
@@ -0,0 +1,32 @@
+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 };
+};
diff --git a/src/pages/quiz/PassingTests.js b/src/pages/quiz/PassingTests.js
index a5cfc43a..da68eab0 100644
--- a/src/pages/quiz/PassingTests.js
+++ b/src/pages/quiz/PassingTests.js
@@ -1,24 +1,43 @@
-import React, { useState } from "react";
+import moment from "moment";
+import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
-import { Link } from "react-router-dom";
+import { Link, useNavigate, useParams } from "react-router-dom";
+import { useTimer } from "react-timer-hook";
import { completedTestSelector } from "@redux/quizSlice";
import { Footer } from "@components/Common/Footer/Footer";
+import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
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 { CardIntroduction } from "@components/features/quiz/Card-introduction";
import { QuizPassingInformation } from "@components/features/quiz/Quiz-passing-information";
import { TaskQuiz } from "@components/features/quiz/Task";
export const PassingTests = () => {
- const time = new Date();
- time.setSeconds(time.getSeconds() + 600); //600 - кол-во секунд для прохождения теста
-
const [startTest, setStartTest] = useState(false);
+ const navigate = useNavigate();
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 = [
{
@@ -38,10 +57,30 @@ 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 (
-
+
+ {/*
*/}
{
]}
/>
- Тестирование в позиции Junior разработчик{" "}
+ Тестирование в позиции Junior разработчик
@@ -68,7 +108,7 @@ export const PassingTests = () => {
)}
{startTest ? (
-
+
) : (
{introduction.map((item, i) => (
@@ -98,6 +138,11 @@ export const PassingTests = () => {
)}
+ {/*
*/}
);
};
diff --git a/src/pages/quiz/QuizPage.js b/src/pages/quiz/QuizPage.js
index dac31b9f..66a89f7d 100644
--- a/src/pages/quiz/QuizPage.js
+++ b/src/pages/quiz/QuizPage.js
@@ -2,15 +2,15 @@ import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
-import { questionnairesSelector, setQuestionnaires } from "@redux/quizSlice";
-
+// import { questionnairesSelector, setQuestionnaires } from "@redux/quizSlice";
import { apiRequest } from "@api/request";
import CategoriesItem from "@components/CategoriesItem/CategoriesItem";
import { Footer } from "@components/Common/Footer/Footer";
+import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
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 { SelectedCategory } from "@components/features/quiz/SelectedCategory";
@@ -27,7 +27,7 @@ import BackEndImg from "assets/images/partnerProfile/personalBackEnd.svg";
import "./quiz-page.scss";
export const QuizPage = () => {
- const questionnaires = useSelector(questionnairesSelector);
+ const [questionnaires, setQuestionnaires] = useState([]);
const dispatch = useDispatch();
const [personalInfoItems] = useState([
{
@@ -99,18 +99,19 @@ export const QuizPage = () => {
},
]);
const userId = localStorage.getItem("id");
- const [selectedCategory, setsetSelectedCategory] = useState(false);
+ const [selectedCategory, setSetSelectedCategory] = useState(false);
useEffect(() => {
- apiRequest(
- `/user-questionnaire/questionnaires-list?user_id=${userId}`
- ).then((res) => dispatch(setQuestionnaires(res)));
+ apiRequest(`/user-questionnaire/questionnaires-list?user_id=${userId}`)
+ .then((res) => setQuestionnaires(res))
+ .catch((e) => console.log(e));
}, []);
return (
-
+
+ {/*
*/}
{
{!selectedCategory && (
<>
-
+
Доступные тесты
{questionnaires.length ? (
questionnaires.map((item, index) => (
{
>
)}
-
{selectedCategory && (
{personalInfoItems.map((item, index) => {
diff --git a/src/pages/quiz/QuizReportPage.js b/src/pages/quiz/QuizReportPage.js
index 4373462f..f27936bd 100644
--- a/src/pages/quiz/QuizReportPage.js
+++ b/src/pages/quiz/QuizReportPage.js
@@ -1,28 +1,43 @@
-import React from "react";
+import React, { useEffect, useState } from "react";
import { useSelector } from "react-redux";
-import { useNavigate } from "react-router-dom";
+import { useNavigate, useParams } from "react-router-dom";
import { selectedTest } from "@redux/quizSlice";
+import { apiRequest } from "@api/request";
+
import { Footer } from "@components/Common/Footer/Footer";
+import { Navigation } from "@components/Navigation/Navigation";
import { ProfileBreadcrumbs } from "@components/ProfileBreadcrumbs/ProfileBreadcrumbs";
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 { QuizReport } from "@components/features/quiz/QuizReport";
export const QuizReportPage = () => {
const test = useSelector(selectedTest);
+ const params = useParams();
let navigate = useNavigate();
if (!test) {
navigate("/quiz");
}
+ useEffect(() => {
+ apiRequest(
+ `/user-questionnaire/questionnaire-completed?user_questionnaire_uuid=${params.uuid}`
+ ).then((res) => {
+ setTestInfo(res);
+ });
+ }, []);
+
+ const [testInfo, setTestInfo] = useState({});
+
return (
-
+
+ {/*
*/}
{
]}
/>
- Отчет по тестированию позиции Junior разработчик{" "}
+ Отчет по тестированию позиции {testInfo.questionnaire_title}
-
+
-
-
+
diff --git a/src/pages/quiz/quiz-page.scss b/src/pages/quiz/quiz-page.scss
index 04c2311f..7b34b243 100644
--- a/src/pages/quiz/quiz-page.scss
+++ b/src/pages/quiz/quiz-page.scss
@@ -7,7 +7,7 @@
flex-direction: column;
&__container {
max-width: 1160px;
- margin: 0 auto 42px auto;
+ margin: 23px auto 42px auto;
flex: 1 1 auto;
width: 100%;
padding: 0 15px;
@@ -68,7 +68,7 @@
}
&__container {
max-width: 1160px;
- margin: 0 auto 42px auto;
+ margin: 23px auto 42px auto;
flex: 1 1 auto;
width: 100%;
padding: 0 15px;
@@ -90,7 +90,7 @@
flex-direction: column;
&__container {
max-width: 1160px;
- margin: 0 auto 42px auto;
+ margin: 23px auto 42px auto;
flex: 1 1 auto;
width: 100%;
padding: 0 15px;
@@ -125,7 +125,7 @@
flex-direction: column;
&__container {
max-width: 1160px;
- margin: 0 auto 42px auto;
+ margin: 23px auto 42px auto;
flex: 1 1 auto;
width: 100%;
padding: 0 15px;
diff --git a/src/redux/quizSlice.js b/src/redux/quizSlice.js
index 79264f9b..8cc33100 100644
--- a/src/redux/quizSlice.js
+++ b/src/redux/quizSlice.js
@@ -1,105 +1,15 @@
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
+import moment from "moment";
-import { apiRequest } from "../api/request";
+import { apiRequest } from "@api/request";
const initialState = {
- 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 ",
- },
- ],
+ questions: null,
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,
+ selectedTest: {},
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) =>
apiRequest(
@@ -111,41 +21,27 @@ export const quizSlice = createSlice({
name: "quiz",
initialState,
reducers: {
- setQuestionnaires: (state, action) => {
- state.questionnaires = action.payload;
- },
- setSelectedTest: (state, action) => {
- state.selectedTest = action.payload;
+ setQuestions: (state, action) => {
+ state.questions = action.payload;
},
setCompleteTest: (state) => {
state.completedTest = true;
},
},
extraReducers: {
- [setUserInfo.fulfilled]: (state, action) => {
- state.userInfo = action.payload;
- },
- [fetchGetAnswers.fulfilled]: (state, action) => {
- state.answer = action.payload;
- },
[fetchResultTest.fulfilled]: (state, action) => {
state.result = action.payload;
},
},
});
-export const { setQuestionnaires, setSelectedTest, setCompleteTest } =
- quizSlice.actions;
+export const { setQuestions } = quizSlice.actions;
-export const answersSelector = (state) => state.quiz.answers;
export const questionnairesSelector = (state) => state.quiz.questionnaires;
-export const selectedAnswersSelector = (state) => state.quiz.selectedAnswers;
export const questionsSelector = (state) => state.quiz.questions;
export const completedTestSelector = (state) => state.quiz.completedTest;
export const selectResult = (state) => state.quiz.result;
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;