diff --git a/lib/utils/hooks/useQuestionFlowControl.ts b/lib/utils/hooks/useQuestionFlowControl.ts index 9d08059..ddc7122 100644 --- a/lib/utils/hooks/useQuestionFlowControl.ts +++ b/lib/utils/hooks/useQuestionFlowControl.ts @@ -8,50 +8,47 @@ import { enqueueSnackbar } from "notistack"; export function useQuestionFlowControl() { const { settings, questions } = useQuizData(); + const sortedQuestions = useMemo(() => { + return [...questions].sort((a, b) => a.page - b.page); + }, [questions]); const [currentQuestionId, setCurrentQuestionId] = useState(getFirstQuestionId); const answers = useQuizViewStore(state => state.answers); const pointsSum = useQuizViewStore(state => state.pointsSum); const setCurrentQuizStep = useQuizViewStore(state => state.setCurrentQuizStep); - const currentQuestion = questions.find(question => question.id === currentQuestionId) ?? null; + const currentQuestion = sortedQuestions.find(question => question.id === currentQuestionId) ?? sortedQuestions[0]; - const linearQuestionIndex = currentQuestion && questions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled - ? questions.indexOf(currentQuestion) + const linearQuestionIndex = currentQuestion && sortedQuestions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled + ? sortedQuestions.indexOf(currentQuestion) : null; function getFirstQuestionId() { - if (questions.length === 0) return null; + if (sortedQuestions.length === 0) return null; if (settings.cfg.haveRoot) { - const nextQuestion = questions.find( + const nextQuestion = sortedQuestions.find( question => question.id === settings.cfg.haveRoot || question.content.id === settings.cfg.haveRoot ); - if (!nextQuestion) throw new Error("Root question not found"); + if (!nextQuestion) return null; return nextQuestion.id; } - return questions[0].id; + return sortedQuestions[0].id; } - - const nextQuestionIdPointsLogic = () => { - return questions.find(question => + const nextQuestionIdPointsLogic = useCallback(() => { + return sortedQuestions.find(question => question.type === "result" && question.content.rule.parentId === "line" ); - }; - - const nextQuestionIdMainLogic = () => { - if (!currentQuestion) return null; + }, [sortedQuestions]); + const nextQuestionIdMainLogic = useCallback(() => { const questionAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id); - //Если ответ существует и не является объектом момента if (questionAnswer && !moment.isMoment(questionAnswer.answer)) { - //Ответы должны храниться в массиве const userAnswers = Array.isArray(questionAnswer.answer) ? questionAnswer.answer : [questionAnswer.answer]; - //Сравниваем список условий ветвления и выбираем подходящее for (const branchingRule of currentQuestion.content.rule.main) { if (userAnswers.some(answer => branchingRule.rules[0].answers.includes(answer))) { return branchingRule.next; @@ -59,7 +56,7 @@ export function useQuestionFlowControl() { } } - if (!currentQuestion.required) {//вопрос не обязателен и не нашли совпадений между ответами и условиями ветвления + if (!currentQuestion.required) { const defaultNextQuestionId = currentQuestion.content.rule.default; if (defaultNextQuestionId.length > 1 && defaultNextQuestionId !== " ") return defaultNextQuestionId; //Вопросы типа страница, ползунок, своё поле для ввода и дата не могут иметь больше 1 ребёнка. Пользователь не может настроить там дефолт @@ -71,79 +68,57 @@ export function useQuestionFlowControl() { } //ничё не нашли, ищем резулт - return questions.find(q => { + return sortedQuestions.find(q => { return q.type === "result" && q.content.rule.parentId === currentQuestion.content.id; })?.id; - }; - const calculateNextQuestionId = useMemo(() => { + }, [answers, currentQuestion, sortedQuestions]); + + const nextQuestionId = useMemo(() => { if (settings.cfg.score) { return nextQuestionIdPointsLogic(); } return nextQuestionIdMainLogic(); - }, [answers, currentQuestion, questions]); + }, [nextQuestionIdMainLogic, nextQuestionIdPointsLogic, settings.cfg.score]); const prevQuestion = linearQuestionIndex !== null - ? questions[linearQuestionIndex - 1] - : questions.find(q => + ? sortedQuestions[linearQuestionIndex - 1] + : sortedQuestions.find(q => q.id === currentQuestion?.content.rule.parentId || q.content.id === currentQuestion?.content.rule.parentId ); - const findResultPointsLogic = () => { - const results = questions - .filter(e => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum); - const numbers = results.map(e => e.type === "result" && e.content.rule.minScore !== undefined ? e.content.rule.minScore : 0); + const findResultPointsLogic = useCallback(() => { + const results = sortedQuestions.filter( + e => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum + ); + const numbers = results.map( + e => e.type === "result" && e.content.rule.minScore !== undefined ? e.content.rule.minScore : 0 + ); const indexOfNext = Math.max(...numbers); - console.log(results); - console.log(numbers); - console.log(indexOfNext); + return results[numbers.indexOf(indexOfNext)]; - }; + }, [pointsSum, sortedQuestions]); - const getNextQuestion = () => { + const nextQuestion = useMemo(() => { let next; - console.log(11111111111); - //Искать можно двумя логиками. Основной и балловой if (settings.cfg.score) { - //Балловая - console.log(222222222); - - - //Ищем линейно if (linearQuestionIndex !== null) { - console.log(33333333333); - - - next = questions[linearQuestionIndex + 1]; - console.log(4444444); - console.log("перед ифом", next); + next = sortedQuestions[linearQuestionIndex + 1]; if (next?.type === "result" || next == undefined) next = findResultPointsLogic(); - console.log(5555555555); - - } - - } else { - console.log(6666666); - //Основная if (linearQuestionIndex !== null) { - console.log(777777777); - //Ищем линейно - next = questions[linearQuestionIndex + 1] ?? questions.find(question => + next = sortedQuestions[linearQuestionIndex + 1] ?? sortedQuestions.find(question => question.type === "result" && question.content.rule.parentId === "line" ); } else { - console.log(88888888888888); - //Ищем ветвлением - next = questions.find(q => q.id === calculateNextQuestionId || q.content.id === calculateNextQuestionId); + next = sortedQuestions.find(q => q.id === nextQuestionId || q.content.id === nextQuestionId); } } - console.log("next", next); - if (!next && currentQuestion?.type !== "result") throw new Error("Не найден следующий вопрос"); + return next; - }; - const nextQuestion = getNextQuestion(); + }, [nextQuestionId, findResultPointsLogic, linearQuestionIndex, sortedQuestions, settings.cfg.score]); + const showResult = useCallback(() => { if (nextQuestion?.type !== "result") throw new Error("Current question is not result"); @@ -179,17 +154,15 @@ export function useQuestionFlowControl() { }, [nextQuestion, showResult]); const setQuestion = useCallback((questionId: string) => { - const question = questions.find(q => q.id === questionId); + const question = sortedQuestions.find(q => q.id === questionId); if (!question) return; setCurrentQuestionId(question.id); - }, [questions]); + }, [sortedQuestions]); const isPreviousButtonEnabled = Boolean(prevQuestion); const isNextButtonEnabled = useMemo(() => { - if (!currentQuestion) return false; - const hasAnswer = answers.some(({ questionId }) => questionId === currentQuestion.id); if ("required" in currentQuestion.content && currentQuestion.content.required) { diff --git a/package.json b/package.json index 363aae6..2a3411f 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@frontend/squzanswerer", - "version": "1.0.29", + "version": "1.0.36", "type": "module", "main": "./dist-package/index.js", "module": "./dist-package/index.js",