diff --git a/lib/api/hooks.ts b/lib/api/hooks.ts index 13a5f03..93bebc3 100644 --- a/lib/api/hooks.ts +++ b/lib/api/hooks.ts @@ -31,7 +31,7 @@ export function useQuizData(quizId: string, preview: boolean) { page: currentPage, needConfig: true, }); - + //firstData.settings.status = "ai"; initDataManager({ status: firstData.settings.status, haveRoot: firstData.settings.cfg.haveRoot, @@ -39,7 +39,9 @@ export function useQuizData(quizId: string, preview: boolean) { setQuizData(firstData); // Определяем нужно ли загружать все данные - if (["line", "branch"].includes(firstData.settings.status)) { + console.log("Определяем нужно ли загружать все данные"); + console.log(firstData.settings.status); + if (!["ai"].includes(firstData.settings.status)) { setNeedFullLoad(true); // Триггерит новый запрос через изменение ключа return firstData; } @@ -59,7 +61,7 @@ export function useQuizData(quizId: string, preview: boolean) { return data; } - if (currentPage > questions.length) { + if (currentPage >= questions.length) { try { // Для AI режима - последовательная загрузка const data = await getAndParceData({ diff --git a/lib/components/QuizAnswerer.tsx b/lib/components/QuizAnswerer.tsx index 08b6d7b..da5d58f 100644 --- a/lib/components/QuizAnswerer.tsx +++ b/lib/components/QuizAnswerer.tsx @@ -21,7 +21,7 @@ import { HelmetProvider } from "react-helmet-async"; import "moment/dist/locale/ru"; import { useQuizStore, setQuizData, addquizid } from "@/stores/useQuizStore"; -import { initDataManager } from "@/utils/hooks/useQuestionFlowControl"; +import { initDataManager, statusOfQuiz } from "@/utils/hooks/useQuestionFlowControl"; moment.locale("ru"); const localeText = ruRU.components.MuiLocalizationProvider.defaultProps.localeText; @@ -99,13 +99,14 @@ function QuizAnswererInner({ console.log("settings"); console.log(settings); - if (isLoading) return ; + if (isLoading && !questions.length) return ; if (error) return ; if (Object.keys(settings).length == 0) return ; if (questions.length === 0) return ; - if (questions.length === 1 && settings.cfg.noStartPage) return ; + if (questions.length === 1 && settings.cfg.noStartPage && statusOfQuiz != "ai") + return ; if (!quizId) return ; const quizContainer = ( diff --git a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx index 70763eb..dfad75f 100644 --- a/lib/components/ViewPublicationPage/ViewPublicationPage.tsx +++ b/lib/components/ViewPublicationPage/ViewPublicationPage.tsx @@ -5,7 +5,7 @@ import { useYandexMetrics } from "@/utils/hooks/metrics/useYandexMetrics"; import { sendQuestionAnswer } from "@/utils/sendQuestionAnswer"; import { ThemeProvider, Typography } from "@mui/material"; import { useQuizViewStore } from "@stores/quizView"; -import { useQuestionFlowControl } from "@utils/hooks/useQuestionFlowControl"; +import { statusOfQuiz, useQuestionFlowControl } from "@utils/hooks/useQuestionFlowControl"; import { notReachable } from "@utils/notReachable"; import { quizThemes } from "@utils/themes/Publication/themePublication"; import { enqueueSnackbar } from "notistack"; @@ -18,7 +18,7 @@ import { StartPageViewPublication } from "./StartPageViewPublication"; import NextButton from "./tools/NextButton"; import PrevButton from "./tools/PrevButton"; import unscreen from "@/ui_kit/unscreen"; -import { useQuizStore } from "@/stores/useQuizStore"; +import { changeNextLoading, useQuizStore } from "@/stores/useQuizStore"; export default function ViewPublicationPage() { const { settings, recentlyCompleted, quizId, preview, changeFaviconAndTitle } = useQuizStore(); @@ -108,6 +108,7 @@ export default function ViewPublicationPage() { { + if (statusOfQuiz == "ai") changeNextLoading(true); if (!preview) { await sendQuestionAnswer(quizId, currentQuestion, currentAnswer, ownVariants)?.catch((e) => { enqueueSnackbar("Ошибка при отправке ответа"); diff --git a/lib/components/ViewPublicationPage/tools/NextButton.tsx b/lib/components/ViewPublicationPage/tools/NextButton.tsx index 5ed3b93..77376fc 100644 --- a/lib/components/ViewPublicationPage/tools/NextButton.tsx +++ b/lib/components/ViewPublicationPage/tools/NextButton.tsx @@ -1,5 +1,5 @@ import { useQuizStore } from "@/stores/useQuizStore"; -import { Button } from "@mui/material"; +import { Button, Skeleton } from "@mui/material"; import { quizThemes } from "@utils/themes/Publication/themePublication"; import { useTranslation } from "react-i18next"; @@ -9,10 +9,19 @@ interface Props { } export default function NextButton({ isNextButtonEnabled, moveToNextQuestion }: Props) { - const { settings } = useQuizStore(); + const { settings, nextLoading } = useQuizStore(); const { t } = useTranslation(); - return ( + return nextLoading ? ( + + ) : ( ); } diff --git a/lib/stores/useQuizStore.ts b/lib/stores/useQuizStore.ts index 4a98738..e56e56c 100644 --- a/lib/stores/useQuizStore.ts +++ b/lib/stores/useQuizStore.ts @@ -8,6 +8,7 @@ export type QuizStore = QuizSettings & { preview: boolean; changeFaviconAndTitle: boolean; quizStep: number; + nextLoading: boolean; }; export const useQuizStore = create(() => ({ @@ -20,6 +21,7 @@ export const useQuizStore = create(() => ({ recentlyCompleted: false, show_badge: false, quizStep: 0, + nextLoading: false, })); export const setQuizData = (data: QuizSettings) => { @@ -39,10 +41,29 @@ export const addquizid = (id: string) => state.quizId = id; }) ); -export const changeQuizStep = (step: number) => + +export const quizStepInc = () => useQuizStore.setState( produce((state: QuizStore) => { - //Дополнительная проверка что мы не вышли на более чем +1 вопрос - if (state.questions.length - step < 2) state.quizStep += step; + //Дополнительная проверка что мы не вышли за пределы массива вопросов + if (state.quizStep + 1 <= state.questions.length) { + state.quizStep += 1; + } + }) + ); +export const quizStepDec = () => + useQuizStore.setState( + produce((state: QuizStore) => { + //Дополнительная проверка что мы не вышли на менее чем 0 вопрос + if (state.quizStep > 0) { + state.quizStep--; + } + }) + ); + +export const changeNextLoading = (status: boolean) => + useQuizStore.setState( + produce((state: QuizStore) => { + state.nextLoading = status; }) ); diff --git a/lib/utils/hooks/FlowControlLogic/useAIQuiz.ts b/lib/utils/hooks/FlowControlLogic/useAIQuiz.ts index 9a2539e..5457a63 100644 --- a/lib/utils/hooks/FlowControlLogic/useAIQuiz.ts +++ b/lib/utils/hooks/FlowControlLogic/useAIQuiz.ts @@ -3,7 +3,7 @@ import { enqueueSnackbar } from "notistack"; import moment from "moment"; import { isResultQuestionEmpty } from "@/components/ViewPublicationPage/tools/checkEmptyData"; -import { useQuizStore } from "@/stores/useQuizStore"; +import { changeNextLoading, quizStepDec, quizStepInc, useQuizStore } from "@/stores/useQuizStore"; import { useQuizViewStore } from "@stores/quizView"; @@ -12,227 +12,79 @@ import { useYandexMetricsGoals } from "@/utils/hooks/metrics/useYandexMetricsGoa export function useAIQuiz() { //Получаем инфо о квизе и список вопросов. - const { settings, questions, quizId, cnt } = useQuizStore(); + const { settings, questions, quizId, cnt, quizStep } = useQuizStore(); useEffect(() => { console.log("useQuestionFlowControl useEffect"); console.log(questions); }, [questions]); - console.log(questions); - //Когда квиз линейный, не ветвящийся, мы идём по вопросам по их порядковому номеру. Это их page. - //За корректность page отвечает конструктор квизов. Интересный факт, если в конструкторе удалить из середины вопрос, то случится куча запросов изменения вопросов с изменением этого page - const sortedQuestions = useMemo(() => { - return [...questions].sort((a, b) => a.page - b.page); - }, [questions]); - //React сам будет менять визуал - главное говорить из какого вопроса ему брать инфо. Изменение этой переменной меняет визуал. - const [currentQuestionId, setCurrentQuestionId] = useState(getFirstQuestionId); - const [headAI, setHeadAI] = useState(0); //Список ответов на вопрос. Мы записываем ответы локально, параллельно отправляя на бек информацию о ответах const answers = useQuizViewStore((state) => state.answers); - //Список засчитанных баллов для балловых квизов - const pointsSum = useQuizViewStore((state) => state.pointsSum); + //Текущий шаг "startpage" | "question" | "contactform" const setCurrentQuizStep = useQuizViewStore((state) => state.setCurrentQuizStep); //Получение возможности управлять состоянием метрик const vkMetrics = useVkMetricsGoals(settings.cfg.vkMetricsNumber); const yandexMetrics = useYandexMetricsGoals(settings.cfg.yandexMetricsNumber); - //Изменение стейта (переменной currentQuestionId) ведёт к пересчёту что же за объект сейчас используется. Мы каждый раз просто ищем в списке - const currentQuestion = sortedQuestions.find((question) => question.id === currentQuestionId) ?? sortedQuestions[0]; + const currentQuestion = useMemo(() => { + console.log("выбор currentQuestion"); + console.log("quizStep ", quizStep); + console.log("questions[quizStep] ", questions[quizStep]); + const calcQuestion = questions[quizStep]; + if (calcQuestion) { + vkMetrics.questionPassed(calcQuestion.id); + yandexMetrics.questionPassed(calcQuestion.id); - //Индекс текущего вопроса только если квиз линейный - const linearQuestionIndex = //: number | null - currentQuestion && sortedQuestions.every(({ content }) => content.rule.parentId !== "root") // null when branching enabled - ? sortedQuestions.indexOf(currentQuestion) - : null; + return calcQuestion; + } else return questions[questions.length - 1]; + }, [questions, quizStep]); - //Индекс первого вопроса - function getFirstQuestionId() { - //: string | null - if (sortedQuestions.length === 0) return null; //Если нету сортированного списка, то и не рыпаемся - - if (settings.cfg.haveRoot) { - // Если есть ветвление, то settings.cfg.haveRoot будет заполнен - //Если заполнен, то дерево растёт с root и это 1 вопрос :) - const nextQuestion = sortedQuestions.find( - //Функция ищет первое совпадение по массиву - (question) => question.id === settings.cfg.haveRoot || question.content.id === settings.cfg.haveRoot - ); - if (!nextQuestion) return null; - - return nextQuestion.id; - } - - //Если не возникло исключительных ситуаций - первый вопрос - нулевой элемент сортированного массива - return sortedQuestions[0].id; - } - - const nextQuestionIdPointsLogic = useCallback(() => { - return sortedQuestions.find((question) => question.type === "result" && question.content.rule.parentId === "line"); - }, [sortedQuestions]); - - //Анализируем какой вопрос должен быть следующим. Это главная логика - const nextQuestionIdMainLogic = useCallback(() => { - //Список ответов данных этому вопросу. Вернёт QuestionAnswer | undefined - const questionAnswer = answers.find(({ questionId }) => questionId === currentQuestion.id); - - //Если questionAnswer не undefined и ответ на вопрос не является временем: - if (questionAnswer && !moment.isMoment(questionAnswer.answer)) { - //Вопрос типизации. Получаем список строк ответов на этот вопрос - const userAnswers = Array.isArray(questionAnswer.answer) ? questionAnswer.answer : [questionAnswer.answer]; - - //цикл. Перебираем список условий .main и обзываем их переменной branchingRule - for (const branchingRule of currentQuestion.content.rule.main) { - // Перебираем список ответов. Если хоть один ответ из списка совпадает с прописанным правилом из условий - этот вопрос нужный нам. Его и дадимкак следующий - if (userAnswers.some((answer) => branchingRule.rules[0].answers.includes(answer))) { - return branchingRule.next; - } - } - } - - //Не помню что это, но чёт при первом взгляде оно true только у результатов - if (!currentQuestion.required) { - //Готовим себе дефолтный путь - const defaultNextQuestionId = currentQuestion.content.rule.default; - - //Если строка не пустая и не пробел. (Обычно при получении данных мы сразу чистим пустые строки только с пробелом на просто пустые строки. Это прост доп защита) - if (defaultNextQuestionId.length > 1 && defaultNextQuestionId !== " ") return defaultNextQuestionId; - //Вопросы типа страница, ползунок, своё поле для ввода и дата не могут иметь больше 1 ребёнка. Пользователь не может настроить там дефолт - //Кинуть на ребёнка надо даже если там нет дефолта - if ( - ["date", "page", "text", "number"].includes(currentQuestion.type) && - currentQuestion.content.rule.children.length === 1 - ) - return currentQuestion.content.rule.children[0]; - } - - //ничё не нашли, ищем резулт - return sortedQuestions.find((q) => { - return q.type === "result" && q.content.rule.parentId === currentQuestion.content.id; - })?.id; - }, [answers, currentQuestion, sortedQuestions]); - - //Анализ следующего вопроса. Это логика для вопроса с баллами - const nextQuestionId = useMemo(() => { - if (settings.cfg.score) { - return nextQuestionIdPointsLogic(); - } - return nextQuestionIdMainLogic(); - }, [nextQuestionIdMainLogic, nextQuestionIdPointsLogic, settings.cfg.score, questions]); - - //Поиск предыдущго вопроса либо по индексу либо по id родителя - const prevQuestion = - linearQuestionIndex !== null - ? sortedQuestions[linearQuestionIndex - 1] - : sortedQuestions.find( - (q) => - q.id === currentQuestion?.content.rule.parentId || q.content.id === currentQuestion?.content.rule.parentId - ); - - //Анализ результата по количеству баллов - const findResultPointsLogic = useCallback(() => { - //Отбираем из массива только тип резулт И результы с информацией о ожидаемых баллах И те результы, чьи суммы баллов меньше или равны насчитанным баллам юзера - - const results = sortedQuestions.filter( - (e) => e.type === "result" && e.content.rule.minScore !== undefined && e.content.rule.minScore <= pointsSum - ); - //Создаём массив строк из результатов. У кого есть инфо о баллах - дают свои, остальные 0 - const numbers = results.map((e) => - e.type === "result" && e.content.rule.minScore !== undefined ? e.content.rule.minScore : 0 - ); - //Извлекаем самое большое число - const indexOfNext = Math.max(...numbers); - //Отдаём индекс нужного нам результата - return results[numbers.indexOf(indexOfNext)]; - }, [pointsSum, sortedQuestions]); - - //Ищем следующий вопрос (не его индекс, или id). Сам вопрос - const nextQuestion = useMemo(() => { - let next; - - if (settings.cfg.score) { - //Ессли квиз балловый - if (linearQuestionIndex !== null) { - next = sortedQuestions[linearQuestionIndex + 1]; //ищем по индексу - if (next?.type === "result" || next == undefined) next = findResultPointsLogic(); //если в поисках пришли к результату - считаем нужный - } - } else { - //иначе - if (linearQuestionIndex !== null) { - //для линейных ищем по индексу - next = - sortedQuestions[linearQuestionIndex + 1] ?? - sortedQuestions.find((question) => question.type === "result" && question.content.rule.parentId === "line"); - } else { - // для нелинейных ищем по вычесленному id - next = sortedQuestions.find((q) => q.id === nextQuestionId || q.content.id === nextQuestionId); - } - } - - return next; - }, [nextQuestionId, findResultPointsLogic, linearQuestionIndex, sortedQuestions, settings.cfg.score]); + useEffect(() => { + if (currentQuestion.type === "result") showResult(); + if (currentQuestion) changeNextLoading(false); + }, [currentQuestion, questions]); //Показать визуалом юзеру результат const showResult = useCallback(() => { - if (nextQuestion?.type !== "result") throw new Error("Current question is not result"); + if (currentQuestion?.type !== "result") throw new Error("Current question is not result"); - //Записать в переменную ид текущего вопроса - setCurrentQuestionId(nextQuestion.id); //Смотрим по настройкам показывать ли вообще форму контактов. Показывать ли страницу результатов до или после формы контактов (ФК) if ( settings.cfg.showfc !== false && - (settings.cfg.resultInfo.showResultForm === "after" || isResultQuestionEmpty(nextQuestion)) + (settings.cfg.resultInfo.showResultForm === "after" || isResultQuestionEmpty(currentQuestion)) ) setCurrentQuizStep("contactform"); - }, [nextQuestion, setCurrentQuizStep, settings.cfg.resultInfo.showResultForm, settings.cfg.showfc]); + }, [currentQuestion, setCurrentQuizStep, settings.cfg.resultInfo.showResultForm, settings.cfg.showfc]); + + //рычаг управления из визуала в этот контроллер - //рычаг управления из визуала в эту функцию const showResultAfterContactForm = useCallback(() => { if (currentQuestion?.type !== "result") throw new Error("Current question is not result"); - if (isResultQuestionEmpty(currentQuestion)) { - enqueueSnackbar("Данные отправлены"); - return; - } + if (isResultQuestionEmpty(currentQuestion)) return; setCurrentQuizStep("question"); }, [currentQuestion, setCurrentQuizStep]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToPrevQuestion = useCallback(() => { - if (!prevQuestion) throw new Error("Previous question not found"); + if (quizStep > 0 && !questions[quizStep - 1]) throw new Error("Previous question not found"); - if (settings.status === "ai" && headAI > 0) setHeadAI((old) => old--); - setCurrentQuestionId(prevQuestion.id); - }, [prevQuestion]); + if (settings.status === "ai" && quizStep > 0) quizStepDec(); + }, [quizStep]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToNextQuestion = useCallback(async () => { - // Если есть следующий вопрос в уже загруженных - используем его + changeNextLoading(true); + quizStepInc(); + }, [quizStep, changeNextLoading, quizStepInc]); - if (nextQuestion) { - vkMetrics.questionPassed(currentQuestion.id); - yandexMetrics.questionPassed(currentQuestion.id); - - if (nextQuestion.type === "result") return showResult(); - setCurrentQuestionId(nextQuestion.id); - return; - } - }, [currentQuestion.id, nextQuestion, showResult, vkMetrics, yandexMetrics, linearQuestionIndex, questions]); - - //рычаг управления из визуала в эту функцию - const setQuestion = useCallback( - (questionId: string) => { - const question = sortedQuestions.find((q) => q.id === questionId); - if (!question) return; - - setCurrentQuestionId(question.id); - }, - [sortedQuestions] - ); + //рычаг управления из визуала в этот контроллер + const setQuestion = useCallback((_: string) => {}, []); //Анализ дисаблить ли кнопки навигации - const isPreviousButtonEnabled = Boolean(prevQuestion); + const isPreviousButtonEnabled = quizStep > 0; //Анализ дисаблить ли кнопки навигации const isNextButtonEnabled = useMemo(() => { @@ -242,25 +94,20 @@ export function useAIQuiz() { return hasAnswer; } - console.log(linearQuestionIndex); - console.log(questions.length); - console.log(cnt); - if (linearQuestionIndex !== null && questions.length < cnt) return true; - return Boolean(nextQuestion); - }, [answers, currentQuestion, nextQuestion]); + return quizStep < cnt; + }, [answers, currentQuestion]); useDebugValue({ - linearQuestionIndex, + CurrentQuestionIndex: quizStep, currentQuestion: currentQuestion, - prevQuestion: prevQuestion, - nextQuestion: nextQuestion, + prevQuestion: questions[quizStep + 1], + nextQuestion: questions[quizStep - 1], }); return { currentQuestion, - currentQuestionStepNumber: - settings.status === "ai" ? null : linearQuestionIndex === null ? null : linearQuestionIndex + 1, - nextQuestion, + currentQuestionStepNumber: null, + nextQuestion: undefined, isNextButtonEnabled, isPreviousButtonEnabled, moveToPrevQuestion, diff --git a/lib/utils/hooks/FlowControlLogic/useBranchingQuiz.ts b/lib/utils/hooks/FlowControlLogic/useBranchingQuiz.ts index d7388fd..bc750cf 100644 --- a/lib/utils/hooks/FlowControlLogic/useBranchingQuiz.ts +++ b/lib/utils/hooks/FlowControlLogic/useBranchingQuiz.ts @@ -27,7 +27,6 @@ export function useBranchingQuiz() { }, [questions]); //React сам будет менять визуал - главное говорить из какого вопроса ему брать инфо. Изменение этой переменной меняет визуал. const [currentQuestionId, setCurrentQuestionId] = useState(getFirstQuestionId); - const [headAI, setHeadAI] = useState(0); //Список ответов на вопрос. Мы записываем ответы локально, параллельно отправляя на бек информацию о ответах const answers = useQuizViewStore((state) => state.answers); //Список засчитанных баллов для балловых квизов @@ -187,26 +186,22 @@ export function useBranchingQuiz() { setCurrentQuizStep("contactform"); }, [nextQuestion, setCurrentQuizStep, settings.cfg.resultInfo.showResultForm, settings.cfg.showfc]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const showResultAfterContactForm = useCallback(() => { if (currentQuestion?.type !== "result") throw new Error("Current question is not result"); - if (isResultQuestionEmpty(currentQuestion)) { - enqueueSnackbar("Данные отправлены"); - return; - } + if (isResultQuestionEmpty(currentQuestion)) return; setCurrentQuizStep("question"); }, [currentQuestion, setCurrentQuizStep]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToPrevQuestion = useCallback(() => { if (!prevQuestion) throw new Error("Previous question not found"); - if (settings.status === "ai" && headAI > 0) setHeadAI((old) => old--); setCurrentQuestionId(prevQuestion.id); }, [prevQuestion]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToNextQuestion = useCallback(async () => { // Если есть следующий вопрос в уже загруженных - используем его @@ -220,7 +215,7 @@ export function useBranchingQuiz() { } }, [currentQuestion.id, nextQuestion, showResult, vkMetrics, yandexMetrics, linearQuestionIndex, questions]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const setQuestion = useCallback( (questionId: string) => { const question = sortedQuestions.find((q) => q.id === questionId); diff --git a/lib/utils/hooks/FlowControlLogic/useLinearQuiz.ts b/lib/utils/hooks/FlowControlLogic/useLinearQuiz.ts index f0e1636..119b3a9 100644 --- a/lib/utils/hooks/FlowControlLogic/useLinearQuiz.ts +++ b/lib/utils/hooks/FlowControlLogic/useLinearQuiz.ts @@ -27,7 +27,6 @@ export function useLinearQuiz() { }, [questions]); //React сам будет менять визуал - главное говорить из какого вопроса ему брать инфо. Изменение этой переменной меняет визуал. const [currentQuestionId, setCurrentQuestionId] = useState(getFirstQuestionId); - const [headAI, setHeadAI] = useState(0); //Список ответов на вопрос. Мы записываем ответы локально, параллельно отправляя на бек информацию о ответах const answers = useQuizViewStore((state) => state.answers); //Список засчитанных баллов для балловых квизов @@ -187,26 +186,22 @@ export function useLinearQuiz() { setCurrentQuizStep("contactform"); }, [nextQuestion, setCurrentQuizStep, settings.cfg.resultInfo.showResultForm, settings.cfg.showfc]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const showResultAfterContactForm = useCallback(() => { if (currentQuestion?.type !== "result") throw new Error("Current question is not result"); - if (isResultQuestionEmpty(currentQuestion)) { - enqueueSnackbar("Данные отправлены"); - return; - } + if (isResultQuestionEmpty(currentQuestion)) return; setCurrentQuizStep("question"); }, [currentQuestion, setCurrentQuizStep]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToPrevQuestion = useCallback(() => { if (!prevQuestion) throw new Error("Previous question not found"); - if (settings.status === "ai" && headAI > 0) setHeadAI((old) => old--); setCurrentQuestionId(prevQuestion.id); }, [prevQuestion]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const moveToNextQuestion = useCallback(async () => { // Если есть следующий вопрос в уже загруженных - используем его @@ -220,7 +215,7 @@ export function useLinearQuiz() { } }, [currentQuestion.id, nextQuestion, showResult, vkMetrics, yandexMetrics, linearQuestionIndex, questions]); - //рычаг управления из визуала в эту функцию + //рычаг управления из визуала в этот контроллер const setQuestion = useCallback( (questionId: string) => { const question = sortedQuestions.find((q) => q.id === questionId); diff --git a/lib/utils/hooks/useQuestionFlowControl.ts b/lib/utils/hooks/useQuestionFlowControl.ts index 768bb98..53ea6de 100644 --- a/lib/utils/hooks/useQuestionFlowControl.ts +++ b/lib/utils/hooks/useQuestionFlowControl.ts @@ -13,12 +13,17 @@ let cachedManager: () => ReturnType; export let statusOfQuiz: "line" | "branch" | "ai"; function analyicStatus({ status, haveRoot }: StatusData) { - if (status === "ai") statusOfQuiz = "ai"; + if (status === "ai") { + statusOfQuiz = "ai"; + return; + } if (status === "start") { // Если есть ветвление, то settings.cfg.haveRoot будет заполнен if (haveRoot) statusOfQuiz = "branch"; else statusOfQuiz = "line"; - } else throw new Error("quiz is inactive"); + return; + } + throw new Error("quiz is inactive"); } export const initDataManager = (data: StatusData) => {