fix: skipping questions bug and overall UI and flow update
This commit is contained in:
+184
-512
@@ -64,7 +64,6 @@ let nextQuestionTimeoutCounter = 3000;
|
||||
let selectionQuestionTimeoutCounter = 6000;
|
||||
let closeResponseTimeoutCounter = 5000;
|
||||
let timeout;
|
||||
let responseCountdownInterval;
|
||||
|
||||
const mainImage = $(".main-image-container img");
|
||||
fetch(url_preset + "/configurations")
|
||||
@@ -76,7 +75,23 @@ fetch(url_preset + "/configurations")
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", ".beginButton", async function () {
|
||||
$(document).ready(function () {
|
||||
// Show Resume button if there is saved progress
|
||||
if (localStorage.getItem("answers")) {
|
||||
$("#resumeButton").show();
|
||||
} else {
|
||||
$("#resumeButton").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on("click", "#beginButton", async function () {
|
||||
// Clear progress and start fresh
|
||||
localStorage.removeItem("answers");
|
||||
dataToReturn = [];
|
||||
uniqueQuestionsShowed = [];
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
isExecuted = false;
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
@@ -89,6 +104,56 @@ $(document).on("click", ".beginButton", async function () {
|
||||
return nextQuestion();
|
||||
});
|
||||
|
||||
$(document).on("click", "#resumeButton", async function () {
|
||||
// Resume from last progress
|
||||
dataToReturn = localStorage.getItem("answers")
|
||||
? JSON.parse(localStorage.getItem("answers"))
|
||||
: [];
|
||||
uniqueQuestionsShowed = [];
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
isExecuted = false;
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
await getQuizzesApi();
|
||||
showQuizTitle();
|
||||
// Find last answered question
|
||||
let lastQ = null;
|
||||
let lastQuizIdx = 0;
|
||||
let lastQCounter = 0;
|
||||
if (dataToReturn.length > 0) {
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
const quiz = allItems[i];
|
||||
for (let j = 0; j < quiz.questions.length; j++) {
|
||||
const q = quiz.questions[j];
|
||||
if (dataToReturn.find((a) => a.question && a.question.id === q.id)) {
|
||||
lastQuizIdx = i;
|
||||
lastQCounter = j + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
currentQuizIndex = lastQuizIdx;
|
||||
currentQuestionCounter = lastQCounter;
|
||||
}
|
||||
// Go to the next unanswered question
|
||||
setTimeout(() => {
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "block");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
$("#progressBarSection").css("display", "block");
|
||||
nextQuestion();
|
||||
}, nextQuestionTimeoutCounter);
|
||||
});
|
||||
|
||||
$(document).on("click", ".goBottom", function () {
|
||||
$("html, body").animate({ scrollTop: $(document).height() }, "slow");
|
||||
});
|
||||
@@ -1023,22 +1088,26 @@ function showResponse(responseHead, responseBody, weatherQuestion) {
|
||||
if (weatherQuestion) {
|
||||
$("#page5 #weatherApi").css("display", "block");
|
||||
}
|
||||
// Countdown timer logic for Quiz 2
|
||||
clearInterval(responseCountdownInterval);
|
||||
let countdown = Math.ceil(closeResponseTimeoutCounter / 1000);
|
||||
$("#responseCountdown").show().text(`Closing in ${countdown} seconds...`);
|
||||
responseCountdownInterval = setInterval(function () {
|
||||
countdown--;
|
||||
if (countdown > 0) {
|
||||
$("#responseCountdown").text(`Closing in ${countdown} seconds...`);
|
||||
|
||||
// Countdown timer logic
|
||||
if (window.responseCountdownInterval) {
|
||||
clearInterval(window.responseCountdownInterval);
|
||||
}
|
||||
const timerDiv = $("#response-timer");
|
||||
let secondsLeft = Math.ceil(closeResponseTimeoutCounter / 1000);
|
||||
timerDiv.text(secondsLeft);
|
||||
timerDiv.show();
|
||||
window.responseCountdownInterval = setInterval(() => {
|
||||
secondsLeft--;
|
||||
if (secondsLeft > 0) {
|
||||
timerDiv.text(secondsLeft);
|
||||
} else {
|
||||
clearInterval(responseCountdownInterval);
|
||||
$("#responseCountdown").hide();
|
||||
timerDiv.text(0);
|
||||
clearInterval(window.responseCountdownInterval);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
closeResponseTimeout = setTimeout(() => {
|
||||
clearInterval(responseCountdownInterval);
|
||||
$("#responseCountdown").hide();
|
||||
closeResponse();
|
||||
}, closeResponseTimeoutCounter);
|
||||
}
|
||||
@@ -1047,11 +1116,15 @@ function showResponse(responseHead, responseBody, weatherQuestion) {
|
||||
function closeResponse() {
|
||||
responseOnGoing = false;
|
||||
hasNoResponse = true;
|
||||
clearInterval(responseCountdownInterval);
|
||||
$("#responseCountdown").hide();
|
||||
$("#page5").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page3").css("display", "block");
|
||||
// Clear the countdown timer
|
||||
if (window.responseCountdownInterval) {
|
||||
clearInterval(window.responseCountdownInterval);
|
||||
window.responseCountdownInterval = null;
|
||||
}
|
||||
$("#response-timer").hide();
|
||||
if (currentQuestionCounter < totalQuizQuestions.length) {
|
||||
return askQuestion(totalQuizQuestions, currentQuestionCounter);
|
||||
} else {
|
||||
@@ -1068,8 +1141,6 @@ function closeResponse() {
|
||||
} // function closeResponse ends here
|
||||
|
||||
async function askQuestion(totalQuizQuestions, counter, fromBack) {
|
||||
// Always hide all answer rows before showing the current one
|
||||
$(".answerRow").hide();
|
||||
clearTimeout(timeout);
|
||||
clearTimeout(closeResponseTimeout);
|
||||
|
||||
@@ -1420,10 +1491,10 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) {
|
||||
`);
|
||||
}
|
||||
});
|
||||
// Add 'None of the above' button
|
||||
// Add 'None of the above' option at the end
|
||||
$("#typeSelection .answerInner").append(`
|
||||
<div class="selectionOptions">
|
||||
<button class="selectionBtns selectionBtn noneOfTheAboveBtn" onclick="handleNoneOfTheAbove()">None of the above</button>
|
||||
<button class="selectionBtns selectionBtn none-of-the-above" onclick="handleNoneOfTheAbove()">None of the above</button>
|
||||
</div>
|
||||
`);
|
||||
|
||||
@@ -1483,8 +1554,6 @@ async function askQuestion(totalQuizQuestions, counter, fromBack) {
|
||||
$("#questionRow h1").html(ques.question);
|
||||
}
|
||||
currentQuestionCounter++;
|
||||
// At the end of askQuestion, always update the nav bar
|
||||
renderQuestionNavBar();
|
||||
}
|
||||
|
||||
async function storeAnswer(currentQuestion, currentActiveAnswerType) {
|
||||
@@ -1798,20 +1867,6 @@ async function storeAnswer(currentQuestion, currentActiveAnswerType) {
|
||||
}
|
||||
}
|
||||
localStorage.setItem("answers", JSON.stringify(dataToReturn));
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
localStorage.setItem(
|
||||
"answers_" + customerEmail.innerText,
|
||||
JSON.stringify(dataToReturn)
|
||||
);
|
||||
}
|
||||
let userKey = getUserProgressKey();
|
||||
localStorage.setItem(userKey, JSON.stringify(dataToReturn));
|
||||
checkResumeButtonVisibility();
|
||||
renderQuestionNavBar();
|
||||
}
|
||||
|
||||
let currentSuggestIndex;
|
||||
@@ -2115,508 +2170,125 @@ function handleImageMissing(self) {
|
||||
$(self).addClass("image-missing");
|
||||
}
|
||||
|
||||
// 1. Add checkAllergie function near the top (after variable declarations)
|
||||
function checkAllergie(btn) {
|
||||
clearTimeout(timeout);
|
||||
var val = $(btn).attr("data-val");
|
||||
// Quiz 4: Terminate if Banana, Olive, or Sunflowers is selected
|
||||
if (["Banana", "Olive", "Sunflowers"].includes(val)) {
|
||||
showTerminationScreen();
|
||||
// Implement checkAllergie for Quiz 4
|
||||
function checkAllergie(self) {
|
||||
const value = self.dataset.val || $(self).data("val");
|
||||
if (["Banana", "Olive", "Sunflowers"].includes(value)) {
|
||||
// Simulate API fetch for message and counter
|
||||
const terminationMessage =
|
||||
"You have an allergy to one of the main ingredients in our system. Our current system will not suit you.";
|
||||
const terminationTitle = "Quiz will now be terminated";
|
||||
let counter = 10; // seconds (simulate API value)
|
||||
$("#termination-overlay .termination-message").text(terminationMessage);
|
||||
$("#termination-overlay .termination-title").text(terminationTitle);
|
||||
$("#termination-overlay .termination-counter").text(counter);
|
||||
$("#termination-overlay").css("display", "flex");
|
||||
let interval = setInterval(() => {
|
||||
counter--;
|
||||
$("#termination-overlay .termination-counter").text(counter);
|
||||
if (counter <= 0) {
|
||||
clearInterval(interval);
|
||||
window.location.href = "/";
|
||||
}
|
||||
}, 1000);
|
||||
// Block all interaction
|
||||
$("body > *:not(#termination-overlay)").css("pointer-events", "none");
|
||||
return;
|
||||
}
|
||||
if ($(btn).hasClass("active")) {
|
||||
tempSelectionAns.splice(tempSelectionAns.indexOf(val), 1);
|
||||
$(btn).removeClass("active");
|
||||
$(btn).removeClass("highlight");
|
||||
} else {
|
||||
tempSelectionAns.push(val);
|
||||
if (!$(btn).hasClass("active")) $(btn).addClass("active");
|
||||
if (!$(btn).hasClass("highlight")) $(btn).addClass("highlight");
|
||||
}
|
||||
timeout = setTimeout(function () {
|
||||
nextQuestion();
|
||||
}, selectionQuestionTimeoutCounter);
|
||||
// If not terminating, proceed as normal (select/deselect logic)
|
||||
// (existing selection logic is handled by the .selectionBtn click handler)
|
||||
}
|
||||
|
||||
// Quiz 4: Show termination overlay and handle countdown/redirect
|
||||
function showTerminationScreen() {
|
||||
// Get message and counter from mainConfigurations (from /configurations API)
|
||||
var message =
|
||||
mainConfigurations && mainConfigurations.termination_message
|
||||
? mainConfigurations.termination_message
|
||||
: "You have selected an allergen. The quiz will now end.";
|
||||
var counter =
|
||||
mainConfigurations && mainConfigurations.termination_counter
|
||||
? parseInt(mainConfigurations.termination_counter)
|
||||
: 5;
|
||||
$("#terminationMessage").text(message);
|
||||
$("#terminationCountdown").text(counter);
|
||||
$("#terminationOverlay").css({ display: "flex" });
|
||||
var countdown = counter;
|
||||
var interval = setInterval(function () {
|
||||
countdown--;
|
||||
if (countdown > 0) {
|
||||
$("#terminationCountdown").text(countdown);
|
||||
} else {
|
||||
clearInterval(interval);
|
||||
window.location.href = "/";
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// Quiz 5: Show Resume Quiz button if progress exists, and handle resume logic
|
||||
$(document).ready(function () {
|
||||
// Use email as key if available, otherwise fallback to local
|
||||
let userKey = null;
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
userKey = "answers_" + customerEmail.innerText;
|
||||
}
|
||||
let savedAnswers = userKey
|
||||
? localStorage.getItem(userKey)
|
||||
: localStorage.getItem("answers");
|
||||
if (savedAnswers && JSON.parse(savedAnswers).length > 0) {
|
||||
$("#resumeButton").show();
|
||||
}
|
||||
|
||||
$("#resumeButton").on("click", async function () {
|
||||
// Load saved progress
|
||||
let answers = userKey
|
||||
? localStorage.getItem(userKey)
|
||||
: localStorage.getItem("answers");
|
||||
if (answers) {
|
||||
dataToReturn = JSON.parse(answers);
|
||||
// Find last answered question
|
||||
let lastQ = dataToReturn[dataToReturn.length - 1];
|
||||
// Set quiz and question index
|
||||
let found = false;
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
let idx = allItems[i].questions.findIndex(
|
||||
(q) => q.id === lastQ.question.id
|
||||
);
|
||||
if (idx !== -1) {
|
||||
currentQuizIndex = i;
|
||||
currentQuestionCounter = idx + 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
}
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
await getQuizzesApi();
|
||||
showQuizTitle();
|
||||
// Resume from next unanswered question
|
||||
return askQuestion(
|
||||
allItems[currentQuizIndex].questions,
|
||||
currentQuestionCounter
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Utility for user-specific progress key
|
||||
function getUserProgressKey() {
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
return "answers_" + customerEmail.innerText;
|
||||
}
|
||||
return "answers";
|
||||
}
|
||||
function clearAllProgress() {
|
||||
localStorage.removeItem("answers");
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
localStorage.removeItem("answers_" + customerEmail.innerText);
|
||||
}
|
||||
}
|
||||
|
||||
// Overwrite reset logic
|
||||
$(document).on("click", "#resetQuizButton", function () {
|
||||
$(document).on("click", "#resetQuizButton", async function () {
|
||||
if (
|
||||
confirm(
|
||||
"Are you sure you want to reset the quiz? All progress will be lost."
|
||||
)
|
||||
) {
|
||||
clearAllProgress();
|
||||
// Reload the page for a true fresh start (clears all in-memory state/UI)
|
||||
window.location.reload();
|
||||
localStorage.removeItem("answers");
|
||||
dataToReturn = [];
|
||||
uniqueQuestionsShowed = [];
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
isExecuted = false;
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
await getQuizzesApi();
|
||||
showQuizTitle();
|
||||
return nextQuestion();
|
||||
}
|
||||
});
|
||||
|
||||
// Overwrite resume logic
|
||||
$(document).ready(function () {
|
||||
let userKey = getUserProgressKey();
|
||||
let savedAnswers = localStorage.getItem(userKey);
|
||||
if (savedAnswers && JSON.parse(savedAnswers).length > 0) {
|
||||
$("#resumeButton").show();
|
||||
}
|
||||
$("#resumeButton")
|
||||
.off("click")
|
||||
.on("click", async function () {
|
||||
let userKey = getUserProgressKey();
|
||||
let answers = localStorage.getItem(userKey);
|
||||
let navState = localStorage.getItem("quiz_nav_state");
|
||||
await getQuizzesApi(); // Always load quizzes first
|
||||
let startFromBeginning = false;
|
||||
let found = false;
|
||||
if (answers) {
|
||||
try {
|
||||
dataToReturn = JSON.parse(answers);
|
||||
} catch (e) {
|
||||
dataToReturn = [];
|
||||
}
|
||||
if (Array.isArray(dataToReturn) && dataToReturn.length > 0) {
|
||||
let lastQ = dataToReturn[dataToReturn.length - 1];
|
||||
if (
|
||||
lastQ &&
|
||||
lastQ.question &&
|
||||
typeof lastQ.question.id !== "undefined"
|
||||
) {
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
let idx = allItems[i].questions.findIndex(
|
||||
(q) => q.id === lastQ.question.id
|
||||
);
|
||||
if (idx !== -1) {
|
||||
currentQuizIndex = i;
|
||||
currentQuestionCounter = idx + 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not found by answers, try nav state
|
||||
if (!found && navState) {
|
||||
try {
|
||||
const { quizIndex, questionCounter } = JSON.parse(navState);
|
||||
if (
|
||||
typeof quizIndex === "number" &&
|
||||
typeof questionCounter === "number"
|
||||
) {
|
||||
currentQuizIndex = quizIndex;
|
||||
currentQuestionCounter = questionCounter;
|
||||
found = true;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
// If still not found, start from beginning
|
||||
if (!found) {
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
}
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
showQuizTitle();
|
||||
askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter);
|
||||
});
|
||||
});
|
||||
|
||||
// In storeAnswer, always save to the correct user key
|
||||
async function storeAnswer(currentQuestion, currentActiveAnswerType) {
|
||||
// ... existing code ...
|
||||
let userKey = getUserProgressKey();
|
||||
localStorage.setItem(userKey, JSON.stringify(dataToReturn));
|
||||
checkResumeButtonVisibility();
|
||||
renderQuestionNavBar();
|
||||
}
|
||||
|
||||
function renderQuestionNavBar() {
|
||||
if (!allItems || allItems.length === 0 || !$("#page3").is(":visible")) {
|
||||
$("#questionNavBar").hide();
|
||||
// Hide on landing and final result pages
|
||||
if ($("#page1").is(":visible") || $("#page7").is(":visible")) {
|
||||
$("#question-nav-bar").hide();
|
||||
return;
|
||||
}
|
||||
let questions = [];
|
||||
allItems.forEach((quiz) => {
|
||||
quiz.questions.forEach((q) => {
|
||||
questions.push({ id: q.id, text: q.question });
|
||||
});
|
||||
});
|
||||
let answeredIds = (dataToReturn || [])
|
||||
.map((a) => a.question && a.question.id)
|
||||
.filter(Boolean);
|
||||
// Determine the current question id
|
||||
let currentId = null;
|
||||
$("#question-nav-bar").show();
|
||||
$("#question-nav-bar").html("");
|
||||
if (
|
||||
allItems[currentQuizIndex] &&
|
||||
allItems[currentQuizIndex].questions[currentQuestionCounter] // currentQuestionCounter points to the next question, so use currentQuestionCounter-1 if >0
|
||||
) {
|
||||
currentId =
|
||||
allItems[currentQuizIndex].questions[currentQuestionCounter]?.id;
|
||||
// If currentId is undefined (e.g., at end), fallback to previous
|
||||
if (!currentId && currentQuestionCounter > 0) {
|
||||
currentId =
|
||||
allItems[currentQuizIndex].questions[currentQuestionCounter - 1]?.id;
|
||||
}
|
||||
} else if (
|
||||
allItems[currentQuizIndex] &&
|
||||
allItems[currentQuizIndex].questions[currentQuestionCounter - 1]
|
||||
) {
|
||||
currentId =
|
||||
allItems[currentQuizIndex].questions[currentQuestionCounter - 1].id;
|
||||
}
|
||||
let html = "";
|
||||
questions.forEach((q, idx) => {
|
||||
let btnClass = "nav-btn";
|
||||
const isAnswered = answeredIds.includes(q.id);
|
||||
const isCurrent = q.id === currentId;
|
||||
if (isAnswered) btnClass += " answered";
|
||||
!allItems ||
|
||||
!allItems[currentQuizIndex] ||
|
||||
!allItems[currentQuizIndex].questions
|
||||
)
|
||||
return;
|
||||
const questions = allItems[currentQuizIndex].questions;
|
||||
let navHtml = '<div class="question-nav-inner">';
|
||||
for (let i = 0; i < questions.length; i++) {
|
||||
const q = questions[i];
|
||||
let answered = dataToReturn.find(
|
||||
(a) => a.question && a.question.id === q.id
|
||||
);
|
||||
let isCurrent = i === currentQuestionCounter - 1;
|
||||
let btnClass = "question-nav-btn";
|
||||
if (isCurrent) btnClass += " current";
|
||||
if (!isAnswered) btnClass += " unanswered";
|
||||
html += `<button class="${btnClass}" data-qid="${
|
||||
q.id
|
||||
}" style="margin:0 4px; min-width:32px; min-height:32px; border-radius:4px; border:none; font-weight:bold; cursor:pointer;">${
|
||||
idx + 1
|
||||
}</button>`;
|
||||
});
|
||||
$("#questionNavBar").html(html).show();
|
||||
else if (answered) btnClass += " answered";
|
||||
else btnClass += " unanswered";
|
||||
navHtml += `<button class="${btnClass}" data-qidx="${i}">${i + 1}</button>`;
|
||||
}
|
||||
navHtml += "</div>";
|
||||
$("#question-nav-bar").html(navHtml);
|
||||
}
|
||||
|
||||
// Handle nav bar button click
|
||||
$(document).on("click", "#questionNavBar .nav-btn", function () {
|
||||
let qid = parseInt($(this).attr("data-qid"));
|
||||
let found = false;
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
let idx = allItems[i].questions.findIndex((q) => q.id === qid);
|
||||
if (idx !== -1) {
|
||||
currentQuizIndex = i;
|
||||
currentQuestionCounter = idx;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
// Helper to jump to a specific question index in the current quiz
|
||||
function jumpToQuestion(index) {
|
||||
// Hide all answer rows and question row
|
||||
var divsToHide = document.getElementsByClassName("answerRow");
|
||||
for (let i = 0; i < divsToHide.length; i++) {
|
||||
divsToHide[i].style.display = "none";
|
||||
}
|
||||
if (found) {
|
||||
askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter);
|
||||
$("#questionRow").css("display", "none");
|
||||
// Set the counter and show the question
|
||||
currentQuestionCounter = index;
|
||||
askQuestion(allItems[currentQuizIndex].questions, index);
|
||||
}
|
||||
|
||||
// Handle nav bar click
|
||||
$(document).on("click", ".question-nav-btn", async function () {
|
||||
const idx = parseInt($(this).attr("data-qidx"));
|
||||
if (!isNaN(idx)) {
|
||||
jumpToQuestion(idx);
|
||||
}
|
||||
});
|
||||
|
||||
// Update nav bar on question change
|
||||
let origAskQuestion = askQuestion;
|
||||
const origAskQuestion = askQuestion;
|
||||
askQuestion = async function (...args) {
|
||||
let result = await origAskQuestion.apply(this, args);
|
||||
const result = await origAskQuestion.apply(this, args);
|
||||
renderQuestionNavBar();
|
||||
return result;
|
||||
};
|
||||
|
||||
// Show/hide nav bar on page changes
|
||||
function updateNavBarVisibility() {
|
||||
if (
|
||||
typeof renderQuestionNavBar === "function" &&
|
||||
$("#page3").is(":visible")
|
||||
) {
|
||||
renderQuestionNavBar();
|
||||
$("#questionNavBar").show();
|
||||
} else {
|
||||
$("#questionNavBar").hide();
|
||||
}
|
||||
}
|
||||
// Ensure nav bar is shown after every askQuestion
|
||||
if (!window._quizNavWrapped) {
|
||||
window._quizNavWrapped = true;
|
||||
const origAskQuestion = askQuestion;
|
||||
askQuestion = async function (...args) {
|
||||
let result = await origAskQuestion.apply(this, args);
|
||||
updateNavBarVisibility();
|
||||
saveNavState();
|
||||
return result;
|
||||
};
|
||||
}
|
||||
// On page load or resume, restore nav state and show nav bar if on question page
|
||||
$(document).ready(function () {
|
||||
loadNavState();
|
||||
updateNavBarVisibility();
|
||||
});
|
||||
|
||||
// Add minimal CSS for nav bar button states
|
||||
$(
|
||||
"<style>\
|
||||
#questionNavBar { display: flex !important; overflow-x: auto; }\
|
||||
#questionNavBar .nav-btn { background: #eee; color: #333; transition: background 0.2s; }\
|
||||
#questionNavBar .nav-btn.answered { background: #4caf50; color: #fff; }\
|
||||
#questionNavBar .nav-btn.current { background: #2196f3; color: #fff; border: 2px solid #1976d2; }\
|
||||
#questionNavBar .nav-btn.unanswered { background: #ccc; color: #888; }\
|
||||
</style>"
|
||||
).appendTo("head");
|
||||
|
||||
// Utility for nav state persistence
|
||||
function saveNavState() {
|
||||
localStorage.setItem(
|
||||
"quiz_nav_state",
|
||||
JSON.stringify({
|
||||
quizIndex: currentQuizIndex,
|
||||
questionCounter: currentQuestionCounter,
|
||||
})
|
||||
);
|
||||
}
|
||||
function loadNavState() {
|
||||
const state = localStorage.getItem("quiz_nav_state");
|
||||
if (state) {
|
||||
try {
|
||||
const { quizIndex, questionCounter } = JSON.parse(state);
|
||||
if (
|
||||
typeof quizIndex === "number" &&
|
||||
typeof questionCounter === "number"
|
||||
) {
|
||||
currentQuizIndex = quizIndex;
|
||||
currentQuestionCounter = questionCounter;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
// On reset, clear nav state
|
||||
function clearAllProgress() {
|
||||
localStorage.removeItem("answers");
|
||||
localStorage.removeItem("quiz_nav_state");
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
localStorage.removeItem("answers_" + customerEmail.innerText);
|
||||
}
|
||||
$("#resumeButton").hide();
|
||||
}
|
||||
|
||||
// BEGIN button: always start fresh and clear progress
|
||||
$(document).on("click", "#beginButton", async function () {
|
||||
clearAllProgress();
|
||||
$("#resumeButton").hide();
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
dataToReturn = [];
|
||||
uniqueQuestionsShowed = [];
|
||||
lastQuizResponseShown = null;
|
||||
lastShowedQuestionId = null;
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
isExecuted = false;
|
||||
await getQuizzesApi();
|
||||
showQuizTitle();
|
||||
askQuestion(allItems[currentQuizIndex].questions, 0);
|
||||
});
|
||||
|
||||
// Resume button logic: only show if there is progress
|
||||
function checkResumeButtonVisibility() {
|
||||
let userKey = getUserProgressKey();
|
||||
let savedAnswers = localStorage.getItem(userKey);
|
||||
let navState = localStorage.getItem("quiz_nav_state");
|
||||
if ((savedAnswers && JSON.parse(savedAnswers).length > 0) || navState) {
|
||||
$("#resumeButton").show();
|
||||
} else {
|
||||
$("#resumeButton").hide();
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
loadNavState();
|
||||
updateNavBarVisibility();
|
||||
checkResumeButtonVisibility();
|
||||
$("#resumeButton")
|
||||
.off("click")
|
||||
.on("click", async function () {
|
||||
let userKey = getUserProgressKey();
|
||||
let answers = localStorage.getItem(userKey);
|
||||
let navState = localStorage.getItem("quiz_nav_state");
|
||||
await getQuizzesApi(); // Always load quizzes first
|
||||
let startFromBeginning = false;
|
||||
let found = false;
|
||||
if (answers) {
|
||||
try {
|
||||
dataToReturn = JSON.parse(answers);
|
||||
} catch (e) {
|
||||
dataToReturn = [];
|
||||
}
|
||||
if (Array.isArray(dataToReturn) && dataToReturn.length > 0) {
|
||||
let lastQ = dataToReturn[dataToReturn.length - 1];
|
||||
if (
|
||||
lastQ &&
|
||||
lastQ.question &&
|
||||
typeof lastQ.question.id !== "undefined"
|
||||
) {
|
||||
for (let i = 0; i < allItems.length; i++) {
|
||||
let idx = allItems[i].questions.findIndex(
|
||||
(q) => q.id === lastQ.question.id
|
||||
);
|
||||
if (idx !== -1) {
|
||||
currentQuizIndex = i;
|
||||
currentQuestionCounter = idx + 1;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If not found by answers, try nav state
|
||||
if (!found && navState) {
|
||||
try {
|
||||
const { quizIndex, questionCounter } = JSON.parse(navState);
|
||||
if (
|
||||
typeof quizIndex === "number" &&
|
||||
typeof questionCounter === "number"
|
||||
) {
|
||||
currentQuizIndex = quizIndex;
|
||||
currentQuestionCounter = questionCounter;
|
||||
found = true;
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
// If still not found, start from beginning
|
||||
if (!found) {
|
||||
currentQuizIndex = 0;
|
||||
currentQuestionCounter = 0;
|
||||
}
|
||||
$("#page1").css("display", "none");
|
||||
$("#page2").css("display", "none");
|
||||
$("#page3").css("display", "none");
|
||||
$("#page4").css("display", "none");
|
||||
$("#page5").css("display", "none");
|
||||
$("#page6").css("display", "none");
|
||||
$("#page7").css("display", "none");
|
||||
showQuizTitle();
|
||||
askQuestion(allItems[currentQuizIndex].questions, currentQuestionCounter);
|
||||
});
|
||||
});
|
||||
|
||||
// After reset, hide resume button until new progress is made
|
||||
function clearAllProgress() {
|
||||
localStorage.removeItem("answers");
|
||||
localStorage.removeItem("quiz_nav_state");
|
||||
if (
|
||||
typeof customerEmail !== "undefined" &&
|
||||
customerEmail &&
|
||||
customerEmail.innerText
|
||||
) {
|
||||
localStorage.removeItem("answers_" + customerEmail.innerText);
|
||||
}
|
||||
$("#resumeButton").hide();
|
||||
}
|
||||
// Also update nav bar on nextQuestion
|
||||
const origNextQuestion = nextQuestion;
|
||||
nextQuestion = async function (...args) {
|
||||
const result = await origNextQuestion.apply(this, args);
|
||||
renderQuestionNavBar();
|
||||
return result;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user