UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

850 lines (849 loc) 32.6 kB
// src/components/Quiz/useQuizStore.ts import { create } from "zustand"; import { devtools } from "zustand/middleware"; var QUESTION_DIFFICULTY = /* @__PURE__ */ ((QUESTION_DIFFICULTY2) => { QUESTION_DIFFICULTY2["FACIL"] = "FACIL"; QUESTION_DIFFICULTY2["MEDIO"] = "MEDIO"; QUESTION_DIFFICULTY2["DIFICIL"] = "DIFICIL"; return QUESTION_DIFFICULTY2; })(QUESTION_DIFFICULTY || {}); var QUIZ_TYPE = /* @__PURE__ */ ((QUIZ_TYPE2) => { QUIZ_TYPE2["SIMULADO"] = "SIMULADO"; QUIZ_TYPE2["QUESTIONARIO"] = "QUESTIONARIO"; QUIZ_TYPE2["ATIVIDADE"] = "ATIVIDADE"; QUIZ_TYPE2["AULA_RECOMENDADA"] = "AULA_RECOMENDADA"; return QUIZ_TYPE2; })(QUIZ_TYPE || {}); var QUESTION_TYPE = /* @__PURE__ */ ((QUESTION_TYPE2) => { QUESTION_TYPE2["ALTERNATIVA"] = "ALTERNATIVA"; QUESTION_TYPE2["DISSERTATIVA"] = "DISSERTATIVA"; QUESTION_TYPE2["MULTIPLA_ESCOLHA"] = "MULTIPLA_ESCOLHA"; QUESTION_TYPE2["VERDADEIRO_FALSO"] = "VERDADEIRO_FALSO"; QUESTION_TYPE2["RELACIONAR"] = "RELACIONAR"; QUESTION_TYPE2["PREENCHER_LACUNAS"] = "PREENCHER_LACUNAS"; QUESTION_TYPE2["IMAGEM"] = "IMAGEM"; return QUESTION_TYPE2; })(QUESTION_TYPE || {}); var hasMeaningfulAnswer = (answer) => { if (!answer) return false; if (answer.questionType === "MULTIPLA_ESCOLHA" /* MULTIPLA_ESCOLHA */) { return Array.isArray(answer.selectedOptionIds) && answer.selectedOptionIds.length > 0 || Boolean(answer.optionId); } const freeTextTypes = [ "DISSERTATIVA" /* DISSERTATIVA */, "RELACIONAR" /* RELACIONAR */, "PREENCHER_LACUNAS" /* PREENCHER_LACUNAS */, "IMAGEM" /* IMAGEM */, "VERDADEIRO_FALSO" /* VERDADEIRO_FALSO */ ]; if (freeTextTypes.includes(answer.questionType)) { if (!answer.answer || answer.answer.trim() === "") return false; if (answer.questionType === "RELACIONAR" /* RELACIONAR */ || answer.questionType === "PREENCHER_LACUNAS" /* PREENCHER_LACUNAS */ || answer.questionType === "VERDADEIRO_FALSO" /* VERDADEIRO_FALSO */) { try { const parsed = JSON.parse(answer.answer); return typeof parsed === "object" && Object.keys(parsed).length > 0; } catch { return false; } } return true; } return answer.optionId !== null && answer.optionId !== ""; }; var QUESTION_STATUS = /* @__PURE__ */ ((QUESTION_STATUS2) => { QUESTION_STATUS2["PENDENTE_AVALIACAO"] = "PENDENTE_AVALIACAO"; QUESTION_STATUS2["RESPOSTA_CORRETA"] = "RESPOSTA_CORRETA"; QUESTION_STATUS2["RESPOSTA_INCORRETA"] = "RESPOSTA_INCORRETA"; QUESTION_STATUS2["NAO_RESPONDIDO"] = "NAO_RESPONDIDO"; return QUESTION_STATUS2; })(QUESTION_STATUS || {}); var ANSWER_STATUS = /* @__PURE__ */ ((ANSWER_STATUS2) => { ANSWER_STATUS2["RESPOSTA_CORRETA"] = "RESPOSTA_CORRETA"; ANSWER_STATUS2["RESPOSTA_INCORRETA"] = "RESPOSTA_INCORRETA"; ANSWER_STATUS2["PENDENTE_AVALIACAO"] = "PENDENTE_AVALIACAO"; ANSWER_STATUS2["NAO_RESPONDIDO"] = "NAO_RESPONDIDO"; return ANSWER_STATUS2; })(ANSWER_STATUS || {}); var SUBTYPE_ENUM = /* @__PURE__ */ ((SUBTYPE_ENUM2) => { SUBTYPE_ENUM2["PROVA"] = "PROVA"; SUBTYPE_ENUM2["ENEM_PROVA_1"] = "ENEM_PROVA_1"; SUBTYPE_ENUM2["ENEM_PROVA_2"] = "ENEM_PROVA_2"; SUBTYPE_ENUM2["VESTIBULAR"] = "VESTIBULAR"; SUBTYPE_ENUM2["SIMULADO"] = "SIMULADO"; SUBTYPE_ENUM2["SIMULADAO"] = "SIMULADAO"; return SUBTYPE_ENUM2; })(SUBTYPE_ENUM || {}); var MINUTE_INTERVAL_MS = 6e4; var useQuizStore = create()( devtools( (set, get) => { let timerInterval = null; let minuteCallbackInterval = null; let timerStartedAt = null; let timerBaseElapsed = 0; const clampElapsed = (elapsed) => { const { timeLimit } = get(); return timeLimit === null ? elapsed : Math.min(elapsed, timeLimit); }; const handleVisibilityChange = () => { if (document.visibilityState === "visible" && timerStartedAt !== null) { const now = Date.now(); const elapsed = clampElapsed( timerBaseElapsed + Math.floor((now - timerStartedAt) / 1e3) ); set({ timeElapsed: elapsed }); checkTimeLimit(elapsed); } }; const checkTimeLimit = (elapsed) => { const { timeLimit, isFinished, onTimeUp } = get(); if (timeLimit !== null && elapsed >= timeLimit && !isFinished) { get().finishQuiz(); onTimeUp?.(); } }; const startTimer = () => { if (get().isFinished) { return; } if (timerInterval) { clearInterval(timerInterval); } timerStartedAt = Date.now(); timerBaseElapsed = get().timeElapsed; document.addEventListener("visibilitychange", handleVisibilityChange); timerInterval = setInterval(() => { if (timerStartedAt === null) return; const now = Date.now(); const elapsed = clampElapsed( timerBaseElapsed + Math.floor((now - timerStartedAt) / 1e3) ); set({ timeElapsed: elapsed }); checkTimeLimit(elapsed); }, 1e3); }; const stopTimer = () => { if (timerInterval) { clearInterval(timerInterval); timerInterval = null; } timerStartedAt = null; timerBaseElapsed = 0; document.removeEventListener( "visibilitychange", handleVisibilityChange ); }; const setMinuteCallback = (callback) => { set({ minuteCallback: callback }); }; const startMinuteCallback = () => { const { minuteCallback, isFinished } = get(); if (isFinished || !minuteCallback) { return; } if (minuteCallbackInterval) { clearInterval(minuteCallbackInterval); } minuteCallbackInterval = setInterval(() => { const { minuteCallback: currentCallback, isFinished: currentIsFinished } = get(); if (currentIsFinished || !currentCallback) { stopMinuteCallback(); return; } currentCallback(); }, MINUTE_INTERVAL_MS); }; const stopMinuteCallback = () => { if (minuteCallbackInterval) { clearInterval(minuteCallbackInterval); minuteCallbackInterval = null; } }; return { // Initial State quiz: null, currentQuestionIndex: 0, selectedAnswers: {}, userAnswers: [], timeElapsed: 0, isStarted: false, isFinished: false, userId: "", variant: "default" /* DEFAULT */, minuteCallback: null, dissertativeCharLimit: void 0, timeLimit: null, onTimeUp: null, questionsResult: null, currentQuestionResult: null, draftApiClient: null, lastSavedDraftPayload: "", isSavingDraft: false, activityFeedback: null, // Setters setQuiz: (quiz) => set({ quiz }), setUserId: (userId) => set({ userId }), setUserAnswers: (userAnswers) => set({ userAnswers }), getUserId: () => get().userId, setVariant: (variant) => set({ variant }), setQuestionResult: (questionsResult) => set({ questionsResult }), setDissertativeCharLimit: (limit) => set({ dissertativeCharLimit: limit }), getDissertativeCharLimit: () => get().dissertativeCharLimit, setDraftApiClient: (client) => set({ draftApiClient: client }), // Draft save - called automatically on navigation saveDraft: async () => { const { draftApiClient, quiz, hasDraftChanges, prepareDraftPayload, lastSavedDraftPayload, isSavingDraft } = get(); if (!draftApiClient || !quiz) return; if (isSavingDraft) return; if (!hasDraftChanges()) return; const payload = prepareDraftPayload(); const payloadString = JSON.stringify(payload); if (payloadString === lastSavedDraftPayload) return; try { set({ isSavingDraft: true }); await draftApiClient.saveDraft(quiz.id, payload); set({ lastSavedDraftPayload: payloadString }); } catch (error) { console.warn("Erro ao salvar rascunho:", error); } finally { set({ isSavingDraft: false }); } }, // Load draft and apply to quiz, navigate to first unanswered question loadAndApplyDraft: async () => { const { draftApiClient, quiz, applyDraftAnswers, prepareDraftPayload } = get(); if (!draftApiClient || !quiz) return; try { const draftData = await draftApiClient.loadDraft(quiz.id); if (draftData?.hasDraft && draftData.answers?.length > 0) { applyDraftAnswers(draftData.answers); const payload = prepareDraftPayload(); set({ lastSavedDraftPayload: JSON.stringify(payload) }); const questions = get().quiz?.questions || []; const updatedAnswers = get().userAnswers; const firstUnansweredIndex = questions.findIndex((question) => { const answer = updatedAnswers.find( (a) => a.questionId === question.id ); if (!answer) return true; if (answer.optionId) return false; if (answer.selectedOptionIds && answer.selectedOptionIds.length > 0) return false; if (answer.answer && answer.answer.trim() !== "") return false; return true; }); if (firstUnansweredIndex > 0) { set({ currentQuestionIndex: firstUnansweredIndex }); } } } catch (error) { console.warn("Erro ao carregar rascunho:", error); } }, // Navigation goToNextQuestion: () => { const { currentQuestionIndex, getTotalQuestions, saveDraft } = get(); const totalQuestions = getTotalQuestions(); if (currentQuestionIndex < totalQuestions - 1) { saveDraft(); set({ currentQuestionIndex: currentQuestionIndex + 1 }); } }, goToPreviousQuestion: () => { const { currentQuestionIndex, saveDraft } = get(); if (currentQuestionIndex > 0) { saveDraft(); set({ currentQuestionIndex: currentQuestionIndex - 1 }); } }, goToQuestion: (index) => { const { getTotalQuestions, currentQuestionIndex, saveDraft } = get(); const totalQuestions = getTotalQuestions(); if (index >= 0 && index < totalQuestions && index !== currentQuestionIndex) { saveDraft(); set({ currentQuestionIndex: index }); } }, selectAnswer: (questionId, answerId) => { const { quiz, userAnswers } = get(); if (!quiz) return; const activityId = quiz.id; const userId = get().getUserId(); if (!userId || userId === "") { return; } const question = quiz.questions.find((q) => q.id === questionId); if (!question) return; const existingAnswerIndex = userAnswers.findIndex( (answer) => answer.questionId === questionId ); const newUserAnswer = { questionId, activityId, userId, answer: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId : null, optionId: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? null : answerId, questionType: question.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; let updatedUserAnswers; if (existingAnswerIndex !== -1) { updatedUserAnswers = [...userAnswers]; updatedUserAnswers[existingAnswerIndex] = newUserAnswer; } else { updatedUserAnswers = [...userAnswers, newUserAnswer]; } set({ userAnswers: updatedUserAnswers }); }, selectMultipleAnswer: (questionId, answerIds) => { const { quiz, userAnswers } = get(); if (!quiz) return; const activityId = quiz.id; const userId = get().getUserId(); if (!userId || userId === "") { return; } const question = quiz.questions.find((q) => q.id === questionId); if (!question) return; const filteredUserAnswers = userAnswers.filter( (answer) => answer.questionId !== questionId ); if (answerIds.length === 0) { set({ userAnswers: filteredUserAnswers }); return; } const newUserAnswer = { questionId, activityId, userId, answer: null, optionId: answerIds.length > 0 ? answerIds[0] : null, selectedOptionIds: answerIds, questionType: question.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; const updatedUserAnswers = [...filteredUserAnswers, newUserAnswer]; set({ userAnswers: updatedUserAnswers }); }, selectDissertativeAnswer: (questionId, answer) => { const { quiz, userAnswers, dissertativeCharLimit } = get(); if (!quiz) return; const activityId = quiz.id; const userId = get().getUserId(); if (!userId || userId === "") { return; } const question = quiz.questions.find((q) => q.id === questionId); const allowedTypes = [ "DISSERTATIVA" /* DISSERTATIVA */, "RELACIONAR" /* RELACIONAR */, "PREENCHER_LACUNAS" /* PREENCHER_LACUNAS */, "IMAGEM" /* IMAGEM */, "VERDADEIRO_FALSO" /* VERDADEIRO_FALSO */ ]; if (!question || !allowedTypes.includes(question.questionType)) { return; } let validatedAnswer = answer; if (question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ && dissertativeCharLimit !== void 0 && answer.length > dissertativeCharLimit) { validatedAnswer = answer.substring(0, dissertativeCharLimit); } const existingAnswerIndex = userAnswers.findIndex( (answerItem) => answerItem.questionId === questionId ); const newUserAnswer = { questionId, activityId, userId, answer: validatedAnswer, optionId: null, questionType: question.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; let updatedUserAnswers; if (existingAnswerIndex !== -1) { updatedUserAnswers = [...userAnswers]; updatedUserAnswers[existingAnswerIndex] = newUserAnswer; } else { updatedUserAnswers = [...userAnswers, newUserAnswer]; } set({ userAnswers: updatedUserAnswers }); }, skipQuestion: () => { const { getCurrentQuestion, userAnswers, quiz } = get(); const currentQuestion = getCurrentQuestion(); if (!quiz) return; if (currentQuestion) { const activityId = quiz.id; const userId = get().getUserId(); if (!userId || userId === "") { return; } const existingAnswerIndex = userAnswers.findIndex( (answer) => answer.questionId === currentQuestion.id ); const existingAnswer = existingAnswerIndex === -1 ? null : userAnswers[existingAnswerIndex]; if (hasMeaningfulAnswer(existingAnswer)) { return; } const newUserAnswer = { questionId: currentQuestion.id, activityId, userId, answer: null, optionId: null, questionType: currentQuestion.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; let updatedUserAnswers; if (existingAnswerIndex !== -1) { updatedUserAnswers = [...userAnswers]; updatedUserAnswers[existingAnswerIndex] = newUserAnswer; } else { updatedUserAnswers = [...userAnswers, newUserAnswer]; } set({ userAnswers: updatedUserAnswers }); } }, skipCurrentQuestionIfUnanswered: () => { const { getCurrentQuestion, getCurrentAnswer, skipQuestion } = get(); const currentQuestion = getCurrentQuestion(); const currentAnswer = getCurrentAnswer(); if (!currentQuestion) return; if (!currentAnswer || currentAnswer.optionId === null && currentAnswer.answer === null && (!currentAnswer.selectedOptionIds || currentAnswer.selectedOptionIds.length === 0)) { skipQuestion(); } }, addUserAnswer: (questionId, answerId) => { const { quiz, userAnswers } = get(); if (!quiz) return; const activityId = quiz.id; const userId = get().getUserId(); if (!userId || userId === "") { return; } const question = quiz.questions.find((q) => q.id === questionId); if (!question) return; const existingAnswerIndex = userAnswers.findIndex( (answer) => answer.questionId === questionId ); const newUserAnswer = { questionId, activityId, userId, answer: question.questionType === "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null, optionId: question.questionType !== "DISSERTATIVA" /* DISSERTATIVA */ ? answerId || null : null, questionType: question.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; if (existingAnswerIndex !== -1) { const updatedUserAnswers = [...userAnswers]; updatedUserAnswers[existingAnswerIndex] = newUserAnswer; set({ userAnswers: updatedUserAnswers }); } else { set({ userAnswers: [...userAnswers, newUserAnswer] }); } }, startQuiz: () => { set({ isStarted: true, timeElapsed: 0 }); startTimer(); startMinuteCallback(); }, finishQuiz: () => { set({ isFinished: true }); stopTimer(); stopMinuteCallback(); }, resetQuiz: () => { stopTimer(); stopMinuteCallback(); set({ quiz: null, currentQuestionIndex: 0, selectedAnswers: {}, userAnswers: [], timeElapsed: 0, isStarted: false, isFinished: false, userId: "", variant: "default" /* DEFAULT */, minuteCallback: null, dissertativeCharLimit: void 0, timeLimit: null, onTimeUp: null, questionsResult: null, currentQuestionResult: null, // Note: draftApiClient is NOT reset here - it's managed by useDraftAutoSave hook lastSavedDraftPayload: "", isSavingDraft: false, activityFeedback: null }); }, // Timer updateTime: (time) => { timerBaseElapsed = time; if (timerStartedAt !== null) { timerStartedAt = Date.now(); } set({ timeElapsed: time }); checkTimeLimit(time); }, startTimer, stopTimer, setTimeLimit: (seconds) => set({ timeLimit: seconds }), setOnTimeUp: (callback) => set({ onTimeUp: callback }), getRemainingTime: () => { const { timeLimit, timeElapsed } = get(); if (timeLimit === null) return null; return Math.max(0, timeLimit - timeElapsed); }, // Minute Callback setMinuteCallback, startMinuteCallback, stopMinuteCallback, // Getters getCurrentQuestion: () => { const { currentQuestionIndex, quiz } = get(); if (!quiz) { return null; } return quiz.questions[currentQuestionIndex]; }, getTotalQuestions: () => { const { quiz } = get(); return quiz?.questions?.length || 0; }, getAnsweredQuestions: () => { const { userAnswers } = get(); const answeredQuestionIds = new Set( userAnswers.filter((answer) => hasMeaningfulAnswer(answer)).map((answer) => answer.questionId) ); return answeredQuestionIds.size; }, getUnansweredQuestions: () => { const { quiz, userAnswers } = get(); if (!quiz) return []; const unansweredQuestions = []; quiz.questions.forEach((question, index) => { const userAnswer = userAnswers.find( (answer) => answer.questionId === question.id ); const isAnswered = hasMeaningfulAnswer(userAnswer); const isSkipped = userAnswer && !hasMeaningfulAnswer(userAnswer); if (!isAnswered && !isSkipped) { unansweredQuestions.push(index + 1); } }); return unansweredQuestions; }, getSkippedQuestions: () => { const { userAnswers } = get(); const skippedQuestionIds = new Set( userAnswers.filter((answer) => !hasMeaningfulAnswer(answer)).map((answer) => answer.questionId) ); return skippedQuestionIds.size; }, getProgress: () => { const { getTotalQuestions, getAnsweredQuestions } = get(); const total = getTotalQuestions(); const answered = getAnsweredQuestions(); return total > 0 ? answered / total * 100 : 0; }, isQuestionAnswered: (questionId) => { const { userAnswers } = get(); const userAnswer = userAnswers.find( (answer) => answer.questionId === questionId ); return hasMeaningfulAnswer(userAnswer); }, isQuestionSkipped: (questionId) => { const { userAnswers } = get(); const userAnswer = userAnswers.find( (answer) => answer.questionId === questionId ); return userAnswer ? !hasMeaningfulAnswer(userAnswer) : false; }, getCurrentAnswer: () => { const { getCurrentQuestion, userAnswers } = get(); const currentQuestion = getCurrentQuestion(); if (!currentQuestion) return void 0; const userAnswer = userAnswers.find( (answer) => answer.questionId === currentQuestion.id ); if (!hasMeaningfulAnswer(userAnswer)) { return void 0; } return userAnswer; }, getAllCurrentAnswer: () => { const { getCurrentQuestion, userAnswers } = get(); const currentQuestion = getCurrentQuestion(); if (!currentQuestion) return void 0; const userAnswer = userAnswers.filter( (answer) => answer.questionId === currentQuestion.id ); return userAnswer; }, getQuizTitle: () => { const { quiz } = get(); return quiz?.title || "Quiz"; }, formatTime: (seconds) => { const minutes = Math.floor(seconds / 60); const remainingSeconds = seconds % 60; return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`; }, getUserAnswers: () => { const { userAnswers } = get(); return userAnswers; }, getUnansweredQuestionsFromUserAnswers: () => { const { quiz, userAnswers } = get(); if (!quiz) return []; const unansweredQuestions = []; quiz.questions.forEach((question, index) => { const userAnswer = userAnswers.find( (answer) => answer.questionId === question.id ); const hasAnswer = hasMeaningfulAnswer(userAnswer); const isSkipped = userAnswer && !hasMeaningfulAnswer(userAnswer); if (!hasAnswer || isSkipped) { unansweredQuestions.push(index + 1); } }); return unansweredQuestions; }, getQuestionsGroupedBySubject: () => { const { getQuestionResult, quiz, variant } = get(); const questions = variant == "result" ? getQuestionResult()?.answers : quiz?.questions; if (!questions) return {}; const groupedQuestions = {}; questions.forEach((question) => { const subjectId = question.knowledgeMatrix?.[0]?.subject?.id || "Sem mat\xE9ria"; if (!groupedQuestions[subjectId]) { groupedQuestions[subjectId] = []; } groupedQuestions[subjectId].push(question); }); return groupedQuestions; }, // New methods for userAnswers getUserAnswerByQuestionId: (questionId) => { const { userAnswers } = get(); return userAnswers.find((answer) => answer.questionId === questionId) || null; }, isQuestionAnsweredByUserAnswers: (questionId) => { const { userAnswers } = get(); const answer = userAnswers.find( (answer2) => answer2.questionId === questionId ); return hasMeaningfulAnswer(answer); }, getQuestionStatusFromUserAnswers: (questionId) => { const { userAnswers } = get(); const answer = userAnswers.find( (answer2) => answer2.questionId === questionId ); if (!answer) return "unanswered"; if (hasMeaningfulAnswer(answer)) return "answered"; return "skipped"; }, getUserAnswersForActivity: () => { const { userAnswers } = get(); return userAnswers; }, setCurrentQuestion: (question) => { const { quiz, variant, questionsResult } = get(); if (!quiz) return; let questionIndex; if (variant == "result") { if (!questionsResult) return; const questionResult = questionsResult.answers.find((q) => q.id === question.id) ?? questionsResult.answers.find((q) => q.questionId === question.id); if (!questionResult) return; questionIndex = quiz.questions.findIndex( (q) => q.id === questionResult.questionId ); } else { questionIndex = quiz.questions.findIndex( (q) => q.id === question.id ); } if (questionIndex === -1) { return; } set({ currentQuestionIndex: questionIndex }); }, setAnswerStatus: (questionId, status) => { const { userAnswers } = get(); const existingAnswerIndex = userAnswers.findIndex( (answer) => answer.questionId === questionId ); if (existingAnswerIndex !== -1) { const updatedUserAnswers = [...userAnswers]; updatedUserAnswers[existingAnswerIndex] = { ...updatedUserAnswers[existingAnswerIndex], answerStatus: status }; set({ userAnswers: updatedUserAnswers }); } }, getAnswerStatus: (questionId) => { const { userAnswers } = get(); const userAnswer = userAnswers.find( (answer) => answer.questionId === questionId ); return userAnswer ? userAnswer.answerStatus : null; }, getQuestionIndex: (questionId) => { const { questionsResult, variant, quiz } = get(); if (variant == "result") { if (!questionsResult) return 0; let idx = questionsResult.answers.findIndex( (q) => q.questionId === questionId ); if (idx === -1) { idx = questionsResult.answers.findIndex( (q) => q.id === questionId ); } return idx !== -1 ? idx + 1 : 0; } else { if (!quiz) return 0; const idx = quiz.questions.findIndex((q) => q.id === questionId); return idx !== -1 ? idx + 1 : 0; } }, // Question Result getQuestionResultByQuestionId: (questionId) => { const { questionsResult } = get(); const question = questionsResult?.answers.find( (answer) => answer.questionId === questionId ); return question || null; }, getQuestionResultStatistics: () => { const { questionsResult } = get(); return questionsResult?.statistics || null; }, getQuestionResult: () => { const { questionsResult } = get(); return questionsResult; }, setQuestionsResult: (questionsResult) => { set({ questionsResult }); }, setCurrentQuestionResult: (currentQuestionResult) => { set({ currentQuestionResult }); }, getCurrentQuestionResult: () => { const { currentQuestionResult } = get(); return currentQuestionResult; }, // Draft management applyDraftAnswers: (draftAnswers) => { const { quiz, userId } = get(); if (!quiz || !draftAnswers || draftAnswers.length === 0) return; const activityId = quiz.id; const newUserAnswers = []; for (const draft of draftAnswers) { const question = quiz.questions.find( (q) => q.id === draft.questionId ); if (!question) continue; let parsedAnswer = draft.answer; let selectedOptionIds = draft.selectedOptionIds; if (draft.answer && !draft.optionId) { try { const parsed = JSON.parse(draft.answer); if (parsed.selectedOptionIds) { selectedOptionIds = parsed.selectedOptionIds; parsedAnswer = null; } } catch { } } const userAnswer = { questionId: draft.questionId, activityId, userId, answer: parsedAnswer, optionId: draft.optionId || null, selectedOptionIds: selectedOptionIds || null, questionType: question.questionType, answerStatus: "PENDENTE_AVALIACAO" /* PENDENTE_AVALIACAO */ }; newUserAnswers.push(userAnswer); } set({ userAnswers: newUserAnswers }); }, prepareDraftPayload: () => { const { userAnswers } = get(); const answers = userAnswers.filter((answer) => hasMeaningfulAnswer(answer)).map((answer) => { const draftAnswer = { questionId: answer.questionId }; if (answer.optionId) { draftAnswer.optionId = answer.optionId; } if (answer.answer) { draftAnswer.answer = answer.answer; } if (answer.selectedOptionIds && answer.selectedOptionIds.length > 0) { draftAnswer.selectedOptionIds = answer.selectedOptionIds; } return draftAnswer; }); return { answers }; }, hasDraftChanges: () => { const { userAnswers } = get(); return userAnswers.some((answer) => hasMeaningfulAnswer(answer)); }, // Activity Feedback setActivityFeedback: (feedback) => set({ activityFeedback: feedback }), getActivityFeedback: () => get().activityFeedback }; }, { name: "quiz-store" } ) ); export { QUESTION_DIFFICULTY, QUIZ_TYPE, QUESTION_TYPE, hasMeaningfulAnswer, QUESTION_STATUS, ANSWER_STATUS, SUBTYPE_ENUM, MINUTE_INTERVAL_MS, useQuizStore }; //# sourceMappingURL=chunk-G7IP4VLI.mjs.map