2022-04-12 08:57:07 -04:00
let url _preset = "" ;
let finalActives = [ ] ;
2025-07-24 22:56:01 +01:00
let dataToReturn = localStorage . getItem ( "answers" )
? JSON . parse ( localStorage . getItem ( "answers" ) )
: [ ] ;
2022-04-12 08:57:07 -04:00
let uniqueQuestionsShowed = [ ] ;
let lastQuizResponseShown ;
let lastShowedQuestionId = null ;
let emailFieldInProgress = false ;
let minRangeVal = null ;
let maxRangeVal = null ;
let blank _active _count = 0 ;
let data = "" ;
let items = "" ;
let allItems = "" ;
let UserName = "" ;
let UserBirth = "" ;
let currentActiveAnswerType = null ;
let currentQuestion = null ;
let answer = "" ;
let currentQuizIndex = 0 ;
let totalQuizQuestions = [ ] ;
let currentQuestionCounter = 0 ;
let saveResponseInto = null ;
let ans = "" ;
let city _id = "" ;
let tempMcqAns = "" ;
let tempMcqAnsValue = 0 ;
let tempMcqiBLActives = [ ] ;
let tempMcqBLActives = [ ] ;
let tempMcqiAns = "" ;
let tempMcqiAnsValue = 0 ;
let sliderAns = "" ;
let sliderBLActives = [ ] ;
let sliderVal = "" ;
let tempSelectionAns = [ ] ;
let isSkipStoreAnswer = false ;
let isExecuted = false ;
let nextBtnClicked = false ;
let argument = [ ] ;
let weights = { } ;
let apiQues = null ;
let quesResponse = null ;
let responseHeader = null ;
let responseBody = null ;
let flag = false ;
let age = "" ;
let allLength = "" ;
let eachLength = 0 ;
let totalQ = 0 ;
let increase = 0 ;
let progress = 0 ;
let timerStart = false ;
let ranges = [ ] ;
let lastCurrentQuizQuesInProgress = false ;
let responseOnGoing = false ;
let hasNoResponse = false ;
let responseClosed = false ;
let closeResponseTimeout ;
let mainConfigurations ;
let profile _characteristics = { } ;
let nextQuestionTimeoutCounter = 3000 ;
let selectionQuestionTimeoutCounter = 6000 ;
let closeResponseTimeoutCounter = 5000 ;
let timeout ;
2025-07-24 22:56:01 +01:00
let responseCountdownInterval ;
2022-04-12 08:57:07 -04:00
const mainImage = $ ( ".main-image-container img" ) ;
fetch ( url _preset + "/configurations" )
. then ( ( res ) => res . json ( ) )
. then ( ( data ) => {
if ( data . success ) {
mainConfigurations = data . payload ;
mainImage . attr ( "src" , url _preset + mainConfigurations . image . url ) ;
}
} ) ;
$ ( document ) . on ( "click" , ".beginButton" , async function ( ) {
$ ( "#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 ( ) ;
} ) ;
$ ( document ) . on ( "click" , ".goBottom" , function ( ) {
$ ( "html, body" ) . animate ( { scrollTop : $ ( document ) . height ( ) } , "slow" ) ;
} ) ;
$ ( document ) . on ( "click" , ".nextBtn" , function ( ) {
nextBtnClicked = true ;
} ) ;
let firstTime = true ;
let oldAnswers = [ ] ;
const customerId = document . getElementById ( "customer-id" ) ;
const customerEmail = document . getElementById ( "customer-email" ) ;
if ( customerId || customerEmail ) {
2025-07-24 22:56:01 +01:00
fetch (
url _preset +
"/v1/api/order/customer?id=" +
customerId ? . innerText +
"&email=" +
customerEmail ? . innerText
)
2022-04-12 08:57:07 -04:00
. then ( ( res ) => res . json ( ) )
. then ( ( data ) => {
if ( data . success && data . data ) {
oldAnswers = data . data ;
firstTime = false ;
}
} ) ;
}
function getQuizzesApi ( ) {
return new Promise ( function ( resolve , reject ) {
$ . ajax ( {
url : url _preset + "/admin/api/quizzes?limit=0" ,
type : "GET" ,
success : function ( response ) {
data = response . data ; //all data in the api
allItems = data . items ; // items in the api
allLength = allItems . length ;
for ( i = 0 ; i < allLength ; i ++ ) {
var eachName = allItems [ i ] . name ;
eachLength = allItems [ i ] . questions . length ;
totalQ = totalQ + eachLength ;
$ ( "#progressBarSection .progressBar .progressColumnsDiv" ) . append ( `
<button class="progressColumns">
<p> ${ eachName } </p>
</button>
` ) ;
}
return resolve ( ) ;
} ,
error : function ( error ) {
return reject ( error ) ;
} ,
} ) ;
} ) ;
}
// function to show all quiz title page
function showQuizTitle ( ) {
$ ( "#page1" ) . css ( "display" , "none" ) ;
$ ( "#page3" ) . css ( "display" , "none" ) ;
$ ( "#page5" ) . css ( "display" , "none" ) ;
$ ( "#page6" ) . css ( "display" , "none" ) ;
$ ( "#page7" ) . css ( "display" , "none" ) ;
$ ( "#page2" ) . css ( "display" , "block" ) ;
$ ( "#page2 .container .row" ) . html ( "" ) ;
$ ( "#progressBarSection" ) . css ( "display" , "none" ) ;
$ ( "#page2 .container .row" ) . append ( `
<h4>Part ${ allItems [ currentQuizIndex ] . id } : ${ allItems [ currentQuizIndex ] . name } </h4>
<h1> ${ allItems [ currentQuizIndex ] . description } </h1>
` ) ;
setTimeout ( function ( ) {
$ ( "#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" ) ;
} , nextQuestionTimeoutCounter ) ;
}
function showPreparingPage ( ) {
clearTimeout ( closeResponseTimeout ) ;
$ ( "#page1" ) . css ( "display" , "none" ) ;
$ ( "#page2" ) . css ( "display" , "none" ) ;
$ ( "#page3" ) . css ( "display" , "none" ) ;
$ ( "#page4" ) . css ( "display" , "none" ) ;
$ ( "#page5" ) . css ( "display" , "none" ) ;
$ ( "#page7" ) . css ( "display" , "none" ) ;
$ ( "#page6" ) . css ( "display" , "block" ) ;
$ ( "#progressBarSection" ) . css ( "display" , "none" ) ;
showResults ( ) ;
}
async function showResults ( ) {
2025-07-24 22:56:01 +01:00
const { accumlatedUniqueWeights , sortedWeightsArray } =
getUniqueAccumlatedWeights ( dataToReturn ) ;
2022-04-12 08:57:07 -04:00
const accumlatedBLActives = getUniqueBlackListActives ( dataToReturn ) ;
2025-07-24 22:56:01 +01:00
const { activesToAdd , activesToRemove } = await getEngineRules (
accumlatedUniqueWeights
) ;
const { sortedFinalActiveslist , sortedFinalActiveslistWithScores } =
await calculatePrioritySelection ( accumlatedUniqueWeights ) ;
const filteredActivesListInitial = filterBlacklistActives (
sortedFinalActiveslistWithScores
) ;
finalActives = applyFinalCalculations (
filteredActivesListInitial ,
activesToAdd ,
activesToRemove ,
dataToReturn
) ;
2022-04-12 08:57:07 -04:00
console . log ( "accumlated weights" , accumlatedUniqueWeights ) ;
console . log ( "black listed actives" , accumlatedBLActives ) ;
console . log ( "full actives list" , sortedFinalActiveslist ) ;
2025-07-24 22:56:01 +01:00
console . log (
"full actives list with scores" ,
sortedFinalActiveslistWithScores
) ;
2022-04-12 08:57:07 -04:00
console . log ( "after first filter" , filteredActivesListInitial ) ;
console . log ( "final actives List" , finalActives ) ;
if ( accumlatedUniqueWeights ) {
await createProfile ( accumlatedUniqueWeights ) ;
}
$ ( "#page6" ) . css ( "display" , "none" ) ;
$ ( "#page7 .nameDiv h5" ) . html ( localStorage . getItem ( "name" ) ) ;
$ ( "#page7" ) . css ( "display" , "block" ) ;
} // showResults function ends here
2025-07-24 22:56:01 +01:00
function applyFinalCalculations (
blFilterdActiveList ,
activesToAdd ,
activesToRemove ,
answersArray
) {
2022-04-12 08:57:07 -04:00
//select top 5
//checkup here to see if it is first time or not
let finalActivesList = [ ] ;
blFilterdActiveList . forEach ( ( active , index ) => {
if ( index < 5 ) {
finalActivesList . push ( active ) ;
} else {
if ( active [ 1 ] >= 22 ) {
finalActivesList . push ( active ) ;
}
}
} ) ;
if ( activesToRemove && activesToRemove . length ) {
finalActivesList . filter ( ( active ) => ! activesToRemove . includes ( active [ 0 ] ) ) ;
}
if ( activesToAdd && activesToAdd . length ) {
activesToAdd . forEach ( ( activeToAdd ) => {
finalActivesList . push ( [ activeToAdd , 0 ] ) ;
} ) ;
}
//second bl active list removal
finalActivesList = finalActivesList . slice ( 0 , 10 ) ;
const blackListedActives = getUniqueBlackListActives ( answersArray ) ;
finalActivesList = finalActivesList . filter ( ( active ) => {
return ! blackListedActives . includes ( active ) ;
} ) ;
// if (finalActivesList.length < 10) {
// for (let i = finalActivesList.length; i < 11; i++) {
// finalActivesList.push("Blank");
// blank_active_count++;
// }
// }
if ( firstTime ) {
finalActivesList . unshift ( [ "Base" , 100 ] ) ;
} else {
finalActivesList . unshift ( [ "Base Refill" , 100 ] ) ;
}
return finalActivesList ;
}
async function getEngineRules ( uniqueWeights ) {
let activesToAdd = [ ] ;
let activesToRemove = [ ] ;
const rules = await getRules ( ) ;
rules . forEach ( function ( rule ) {
const operator = rule . operator ;
const compareValue = rule . compare _value ;
const ruleOutputVariable = rule . output _variable _name ;
const actionTaken = rule . action ;
const activesInQuestion = JSON . parse ( rule . actives ) ;
if ( uniqueWeights [ ruleOutputVariable ] ) {
if ( operator == 0 ) {
// = eq
if ( uniqueWeights [ ruleOutputVariable ] == compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 1 ) {
// < less than
if ( uniqueWeights [ ruleOutputVariable ] < compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 2 ) {
// <= less than or equal
if ( uniqueWeights [ ruleOutputVariable ] <= compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 3 ) {
// > greater than
if ( uniqueWeights [ ruleOutputVariable ] > compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 4 ) {
// >= greater than or equal
if ( uniqueWeights [ ruleOutputVariable ] >= compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 5 ) {
// != not
if ( uniqueWeights [ ruleOutputVariable ] != compareValue ) {
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
} else if ( operator == 6 ) {
//between
let min = rule . min ;
let max = rule . max ;
2025-07-24 22:56:01 +01:00
if (
uniqueWeights [ ruleOutputVariable ] >= min &&
uniqueWeights [ ruleOutputVariable ] <= max
) {
2022-04-12 08:57:07 -04:00
if ( actionTaken == 1 ) {
//add
activesInQuestion . forEach ( ( aiq ) => {
activesToAdd . push ( aiq ) ;
} ) ;
} else if ( actionTaken == 2 ) {
//remove
activesInQuestion . forEach ( ( aiq ) => {
activesToRemove . push ( aiq ) ;
} ) ;
}
}
}
}
} ) ;
return { activesToAdd , activesToRemove } ;
}
function filterBlacklistActives ( sortedActivesListWithScores ) {
//remove blActives
const blackListedActives = getUniqueBlackListActives ( dataToReturn ) ;
sortedActivesListWithScores = sortedActivesListWithScores . filter ( ( active ) => {
return ! blackListedActives . includes ( active [ 0 ] ) ;
} ) ;
return sortedActivesListWithScores ;
}
function getUniqueAccumlatedWeights ( answersArray ) {
//create array of unique weight and accumlated value
let weightsArray = [ ] ;
let accumlatedUniqueWeightsWihBase = { } ;
answersArray . forEach ( function ( answer ) {
2025-07-24 22:56:01 +01:00
if ( answer . weights && Object . keys ( answer . weights ) . length )
weightsArray . push ( answer . weights ) ;
2022-04-12 08:57:07 -04:00
} ) ;
if ( weightsArray . length == 0 ) {
return { accumlatedUniqueWeightsWihBase , sortedWeightsArray : [ ] } ;
}
weightsArray . forEach ( function ( weight ) {
Object . keys ( weight ) . forEach ( function ( key ) {
if ( accumlatedUniqueWeightsWihBase . hasOwnProperty ( key ) ) {
accumlatedUniqueWeightsWihBase [ key ] = {
2025-07-24 22:56:01 +01:00
value :
parseFloat ( accumlatedUniqueWeightsWihBase [ key ] . value ) +
parseFloat ( weight [ key ] . value ) ,
base :
parseFloat ( accumlatedUniqueWeightsWihBase [ key ] . base ) +
parseFloat ( weight [ key ] . base ) ,
2022-04-12 08:57:07 -04:00
} ;
} else {
accumlatedUniqueWeightsWihBase [ key ] = {
value : parseFloat ( weight [ key ] . value ) ,
base : parseFloat ( weight [ key ] . base ) ,
} ;
}
} ) ;
} ) ;
let accumlatedUniqueWeights = { } ;
2025-07-24 22:56:01 +01:00
Object . entries ( accumlatedUniqueWeightsWihBase ) . forEach (
( [ variableName , { value , base } ] ) => {
accumlatedUniqueWeights [ variableName ] =
parseFloat ( value ) / parseFloat ( base ) ;
}
) ;
let sortedEntries = Object . entries ( accumlatedUniqueWeights ) . sort ( function (
a ,
b
) {
2022-04-12 08:57:07 -04:00
return b [ 1 ] - a [ 1 ] ;
} ) ;
return { accumlatedUniqueWeights , sortedWeightsArray : sortedEntries } ;
}
async function calculatePrioritySelection ( accumlatedUniqueWeights ) {
2025-07-24 22:56:01 +01:00
const outputVariableList = await getFullOutputVariablesList ( ) . then (
( data ) => data . output _variables
) ;
2022-04-12 08:57:07 -04:00
const activesList = await getFullActivesList ( ) . then ( ( data ) => data . actives ) ;
const finalActiveScores = { } ;
for ( const active of activesList ) {
//equation
const activeName = active . name ;
2025-07-24 22:56:01 +01:00
let activesListWeightsScores = active . variables _scores
? JSON . parse ( active . variables _scores )
: { } ;
2022-04-12 08:57:07 -04:00
//filter empty active weights score
2025-07-24 22:56:01 +01:00
activesListWeightsScores = Object . entries ( activesListWeightsScores ) . filter (
( [ outputVarName , score ] ) => {
return score ;
}
) ;
let filteredActivesWeightScores = Object . fromEntries (
activesListWeightsScores
) ;
2022-04-12 08:57:07 -04:00
Object . entries ( filteredActivesWeightScores ) . forEach ( ( [ name , score ] ) => {
const outputVariableAccumlatedWeight = accumlatedUniqueWeights [ name ] ;
if ( outputVariableAccumlatedWeight ) {
2025-07-24 22:56:01 +01:00
const outputVariablePriority = outputVariableList . find (
( ovar ) => ovar . name == name
) . priority ;
2022-04-12 08:57:07 -04:00
if ( finalActiveScores . hasOwnProperty ( activeName ) ) {
2025-07-24 22:56:01 +01:00
finalActiveScores [ activeName ] =
parseFloat ( finalActiveScores [ activeName ] ) +
parseFloat ( outputVariableAccumlatedWeight ) *
parseFloat ( outputVariablePriority / 100 ) *
parseFloat ( score ) ;
2022-04-12 08:57:07 -04:00
} else {
2025-07-24 22:56:01 +01:00
finalActiveScores [ activeName ] =
parseFloat ( outputVariableAccumlatedWeight ) *
parseFloat ( outputVariablePriority / 100 ) *
parseFloat ( score ) ;
2022-04-12 08:57:07 -04:00
}
}
} ) ;
}
//
const finalDividedList = { } ;
Object . entries ( finalActiveScores ) . forEach ( ( [ active , score ] ) => {
if ( ! isNaN ( score ) ) {
finalDividedList [ active ] = parseFloat ( score / 1000 ) ;
}
} ) ;
2025-07-24 22:56:01 +01:00
let sortedFinalActiveslistWithScores = Object . entries ( finalDividedList ) . sort (
( [ , a ] , [ , b ] ) => b - a
) ;
let sortedFinalActiveslist = Object . keys ( finalDividedList ) . sort (
( a , b ) => finalDividedList [ b ] - finalDividedList [ a ]
) ;
2022-04-12 08:57:07 -04:00
return { sortedFinalActiveslist , sortedFinalActiveslistWithScores } ;
}
function getUniqueBlackListActives ( answersArray ) {
let accumlatedBLActives = [ ] ;
answersArray . forEach ( function ( answer ) {
if ( answer . black _list _actives ) {
for ( const blActive of answer . black _list _actives ) {
if ( ! accumlatedBLActives . includes ( blActive ) ) {
accumlatedBLActives . push ( blActive ) ;
}
}
}
} ) ;
return accumlatedBLActives ;
}
async function createProfile ( uniqueWeights ) {
const sections = await getProfileSections ( ) ;
const container = $ ( "#profile-result-container" ) ;
for ( const section of sections ) {
const sectionTitle = section . section _title ;
profile _characteristics [ sectionTitle ] = [ ] ;
let containerTemplate = `
<div class="row profile-row" id=" ${ section . id } ">
<div class="rowInner">
<div class="main-header">
<h1> ${ sectionTitle } </h1>
</div>
<div class="main-body">
2025-07-24 22:56:01 +01:00
${ await makePercentageDivs (
uniqueWeights ,
section . output _variable _list ,
sectionTitle
) }
2022-04-12 08:57:07 -04:00
</div>
</div>
` ;
container . append ( containerTemplate ) ;
}
}
2025-07-24 22:56:01 +01:00
async function makePercentageDivs (
uniqueWeights ,
output _variable _list ,
sectionTitle
) {
2022-04-12 08:57:07 -04:00
let accumlatedString = "" ;
for ( const item of output _variable _list ) {
let varName = item ;
let percentage = uniqueWeights [ item ] ? ? 0 ;
if ( percentage > 100 ) {
percentage = 100 ;
}
let tmp = `
<div class="bodyCols">
<div class="bodyTitle">
<h4> ${ varName } </h4>
</div>
<div class="bodyDesc">
<p> ${ await getOutputVariableRangesResponses ( varName , percentage ) } </p>
</div>
<div class="bodyProgress">
<div id="# ${ varName } " class="movingBar" style="width: ${ percentage } %"></div>
</div>
</div>
` ;
accumlatedString += tmp ;
2025-07-24 22:56:01 +01:00
profile _characteristics [ sectionTitle ] . push ( {
name : varName ,
percentage : percentage ,
} ) ;
2022-04-12 08:57:07 -04:00
}
return accumlatedString ;
}
async function getOutputVariableRangesResponses ( varName , percentage ) {
const outputVariable = await getOutputVariable ( varName ) ;
if ( outputVariable && outputVariable . ranges _response ) {
const rangesResponses = outputVariable . ranges _response ;
const requiredRange = rangesResponses . find ( function ( rr ) {
let minRange = parseFloat ( Object . keys ( rr ) [ 0 ] . split ( "-" ) [ 0 ] ) ;
let maxRange = parseFloat ( Object . keys ( rr ) [ 0 ] . split ( "-" ) [ 1 ] ) ;
2025-07-24 22:56:01 +01:00
if (
Math . round ( percentage ) >= minRange &&
Math . round ( percentage ) <= maxRange
)
return rr ;
2022-04-12 08:57:07 -04:00
} ) ;
if ( requiredRange ) {
let currResponse = requiredRange [ Object . keys ( requiredRange ) [ 0 ] ] ;
return currResponse ;
}
}
return "" ;
}
function getFullActivesList ( ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
url : url _preset + "/api/v1/actives" ,
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
function getFullOutputVariablesList ( ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
url : url _preset + "/api/v1/output-variables" ,
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
function getOutputVariable ( name ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
url : url _preset + ` /api/v1/output-variable/ ${ name } ` ,
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
function getProfileSections ( ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
url : url _preset + "/api/v1/profile-sections" ,
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
// @parameter Array of all output variables names
function getActivesList ( outputVariablesNames ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
2025-07-24 22:56:01 +01:00
url :
url _preset +
` /api/v1/output-variables/actives-list?names_list= ${ outputVariablesNames . join (
","
) } ` ,
2022-04-12 08:57:07 -04:00
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
function getRules ( ) {
return new Promise ( function ( res , rej ) {
$ . ajax ( {
url : url _preset + "/api/v1/rules" ,
type : "GET" ,
success : function ( response ) {
return res ( response . data ) ;
} ,
error : function ( jqXHR , exception ) {
console . error ( jqXHR ) ;
console . error ( exception ) ;
return rej ( exception ) ;
} ,
} ) ; //ajax ends here
} ) ;
}
// function to calculate Age
function calculateAge ( year ) {
if ( ! year ) {
return false ;
}
var d = 1 ;
var m = 0 ;
var y = year ;
var birthdate = new Date ( y , m , d ) ;
var today = new Date ( ) ;
var diff = today - birthdate ;
var age = Math . floor ( diff / ( 1000 * 60 * 60 * 24 * 365 ) ) ;
return age ;
} // function calculateAge ends here
// function to call all the questions
async function nextQuestion ( goBack , goBackFromResponse , fromDependedOn ) {
clearTimeout ( timeout ) ;
clearTimeout ( closeResponseTimeout ) ;
if ( goBack ) {
2025-07-24 22:56:01 +01:00
let stepBack =
uniqueQuestionsShowed . length - 2 < 0
? 0
: uniqueQuestionsShowed . length - 2 ;
2022-04-12 08:57:07 -04:00
let backQuizId = uniqueQuestionsShowed [ stepBack ] . quiz ;
if ( stepBack !== 0 ) {
uniqueQuestionsShowed . pop ( ) ;
}
currentQuizIndex = backQuizId - 1 ;
totalQuizQuestions = allItems [ currentQuizIndex ] . questions ;
currentQuestionCounter = uniqueQuestionsShowed [ stepBack ] . counter ;
progress = uniqueQuestionsShowed [ stepBack ] . progress ;
if ( progress < 0 ) progress = 0 ;
$ ( "#myBar" ) . css ( "width" , progress + "%" ) ;
var divsToHide = document . getElementsByClassName ( "answerRow" ) ;
for ( let i = 0 ; i < divsToHide . length ; i ++ ) {
divsToHide [ i ] . style . display = "none" ;
}
$ ( "#questionRow" ) . css ( "display" , "none" ) ;
let dependedOnQuestions = totalQuizQuestions . filter ( function ( qs ) {
2025-07-24 22:56:01 +01:00
return (
qs . depends _on &&
parseInt ( qs . depends _on . split ( "|" ) [ 0 ] ) ==
totalQuizQuestions [ currentQuestionCounter ] . id
) ;
2022-04-12 08:57:07 -04:00
} ) ;
if ( dependedOnQuestions . length > 0 ) {
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn = dataToReturn . filter ( ( answerObj ) => {
return answerObj . question . id != dq . id ;
} ) ;
} ) ;
localStorage . setItem ( "answers" , JSON . stringify ( dataToReturn ) ) ;
}
if ( goBackFromResponse ) {
$ ( "#page5" ) . css ( "display" , "none" ) ;
$ ( "#page4" ) . css ( "display" , "none" ) ;
$ ( "#page3" ) . css ( "display" , "block" ) ;
}
return await askQuestion ( totalQuizQuestions , currentQuestionCounter , true ) ;
}
increase = ( 1 / totalQuizQuestions . length ) * 100 ;
if ( isNaN ( increase ) || increase == Infinity ) increase = 0 ;
else increase = increase * ( 1 / 3 ) ;
progress = progress + increase ;
$ ( "#myBar" ) . css ( "width" , progress + "%" ) ;
timerStart = true ; // allowing the timer to work for questions
nextBtnClicked = false ; // resetting next button is clicked to not clicked
//first get the answer of previous question and store it.
if ( currentActiveAnswerType && ! isSkipStoreAnswer ) {
2025-07-24 22:56:01 +01:00
await storeAnswer (
totalQuizQuestions [ currentQuestionCounter - 1 ] ,
currentActiveAnswerType
) ;
2022-04-12 08:57:07 -04:00
}
weights = { } ;
sliderAns = "" ;
sliderBLActives = [ ] ;
tempMcqAns = "" ;
tempMcqAnsValue = 0 ;
tempMcqiBLActives = [ ] ;
tempMcqiAns = "" ;
tempMcqiAnsValue = 0 ;
tempMcqBLActives = [ ] ;
minRangeVal = null ;
maxRangeVal = null ;
responseOnGoing = false ;
hasNoResponse = true ;
// displaying user's name on top *this will be executed only once*
if ( dataToReturn [ 0 ] != null && ! isExecuted ) {
isExecuted = true ;
var tempName = dataToReturn [ 0 ] . answer ;
tempName = tempName . split ( " " ) [ 0 ] ; //get first name only
tempName = tempName . toUpperCase ( ) ;
$ ( "#page3 .container .row .createdByDiv" ) . html ( "" ) ;
$ ( "#page3 .container .row .createdByDiv" ) . append ( `
Created By ${ tempName }
` ) ;
$ ( "#page4 .container .row .createdByDiv" ) . html ( "" ) ;
$ ( "#page4 .container .row .createdByDiv" ) . append ( `
Created By ${ tempName }
` ) ;
$ ( "#page5 .container .row .createdByDiv" ) . html ( "" ) ;
$ ( "#page5 .container .row .createdByDiv" ) . append ( `
Created By ${ tempName }
` ) ;
} //displaying user name on top ends here
// first getting the first quiz
totalQuizQuestions = allItems [ currentQuizIndex ] . questions ;
// checking if there is any resp onse in question or answer
if ( currentQuestionCounter != 0 ) {
2025-07-24 22:56:01 +01:00
apiQues = totalQuizQuestions . find (
( ques ) => ques . id == lastShowedQuestionId
) ;
2022-04-12 08:57:07 -04:00
let lastAnswerObject = dataToReturn . find ( function ( ansObj ) {
return ansObj . question . id == apiQues ? . id ;
} ) ;
if ( lastAnswerObject && ! fromDependedOn ) {
var fullAnswerObject = apiQues . answers . find ( function ( cAns ) {
return cAns . answer == lastAnswerObject . answer ;
} ) ;
// quesResponse = apiQues.response;
//when there is response with the question
if ( apiQues . id == 14 ) {
//save progress if there is answer
if ( lastAnswerObject . answer ) {
//ajax save contact
// const email = lastAnswerObject.answer;
// let fullName = localStorage.getItem("name");
// let firstName, lastName;
// if (fullName && fullName !== "You") firstName = fullName.split(" ")[0];
// if (fullName && fullName !== "You" && fullName.split(" ").length > 1) lastName = fullName.split(" ")[fullName.split(" ").length - 1];
// try {
// const newProfile = await fetch(url_preset + "/klaviyo/identity", {
// method: "POST",
// headers: {
// "content-type": "application/json",
// },
// body: JSON.stringify({ email, firstName, lastName }),
// }).then((res) => res.json());
// const addedToList = await fetch(url_preset + "/klaviyo/list", {
// method: "POST",
// headers: {
// "content-type": "application/json",
// },
// body: JSON.stringify({ email }),
// }).then((res) => res.json());
// console.log(newProfile);
// console.log(addedToList);
// } catch (error) {
// console.error(error);
// }
}
}
if ( apiQues . id == 20 && apiQues . type == 7 ) {
if ( Array . isArray ( lastAnswerObject . answer ) ) {
if ( lastAnswerObject . answer . length == 1 ) {
2025-07-24 22:56:01 +01:00
showResponse ( null , "We'll make sure to leave this one out" ) ;
2022-04-12 08:57:07 -04:00
} else if ( lastAnswerObject . answer . length > 1 ) {
2025-07-24 22:56:01 +01:00
showResponse ( null , "We'll make sure to leave those out" ) ;
2022-04-12 08:57:07 -04:00
}
}
} else if ( apiQues . type == 1 && apiQues . id == 1 ) {
if ( apiQues . answers . length > 0 && apiQues . answers [ 0 ] . response _header ) {
responseHeader = apiQues . answers [ 0 ] . response _header ;
var responseArguments = apiQues . answers [ 0 ] . response _arguments ;
responseArguments = JSON . parse ( responseArguments ) ;
var replaceWith = localStorage . getItem ( responseArguments [ 0 ] ) ;
if ( replaceWith ) {
replaceWith = replaceWith . toUpperCase ( ) ;
2025-07-24 22:56:01 +01:00
responseHeader = inject _substitute (
responseHeader ,
"name" ,
replaceWith
) ;
2022-04-12 08:57:07 -04:00
responseHeader = responseHeader . split ( " " ) [ 0 ] ;
$ ( "#page3" ) . css ( "display" , "none" ) ;
$ ( "#page4" ) . css ( "display" , "block" ) ;
$ ( "#page4 .customImgRow .imgRowInner p" ) . html ( "" ) ;
$ ( "#page4 .customImgRow .imgRowInner p" ) . css ( "display" , "block" ) ;
2025-07-24 22:56:01 +01:00
$ ( "#page4 .customImgRow .imgRowInner p" ) . append (
` ${ responseHeader } `
) ;
2022-04-12 08:57:07 -04:00
responseOnGoing = true ;
hasNoResponse = false ;
// closeResponseTimeout = setTimeout(async () => {
// closeResponse();
// }, closeResponseTimeoutCounter);
}
} else if ( apiQues . answers && apiQues . answers [ 0 ] . responseBody ) {
$ ( "#page3" ) . css ( "display" , "none" ) ;
$ ( "#page4" ) . css ( "display" , "block" ) ;
$ ( "#page4 .customImgRow .imgRowInner p" ) . html ( "" ) ;
$ ( "#page4 .customImgRow .imgRowInner p" ) . css ( "display" , "block" ) ;
$ ( "#page4 .customImgRow .imgRowInner p" ) . append ( ` ${ responseHeader } ` ) ;
responseOnGoing = true ;
hasNoResponse = false ;
closeResponseTimeout = setTimeout ( async ( ) => {
closeResponse ( ) ;
} , closeResponseTimeoutCounter ) ;
}
} else if ( apiQues . type == 3 && apiQues . id == 2 && age ) {
if ( age < 25 ) age = "<25" ;
else if ( age >= 25 && age <= 40 ) age = "25-40" ;
else if ( age > 40 ) age = ">40" ;
let correctAgeAnswer = apiQues . answers . find ( function ( cAns ) {
return cAns . answer == age ;
} ) ;
if ( correctAgeAnswer ) {
responseHeader = correctAgeAnswer . response _header ;
responseBody = correctAgeAnswer . response _body ;
showResponse ( responseHeader , responseBody ) ;
}
} else if ( [ 4 , 5 , 6 ] . includes ( apiQues . type ) ) {
2025-07-24 22:56:01 +01:00
if (
fullAnswerObject &&
( fullAnswerObject . response _header || fullAnswerObject . response _body )
) {
2022-04-12 08:57:07 -04:00
if ( fullAnswerObject . response _arguments ) {
responseHeader = fullAnswerObject . response _header ;
var responseArguments = fullAnswerObject . response _arguments ;
responseArguments = JSON . parse ( responseArguments ) ;
var replaceWith = localStorage . getItem ( responseArguments [ 0 ] ) ;
replaceWith = replaceWith . toUpperCase ( ) ;
2025-07-24 22:56:01 +01:00
responseHeader = inject _substitute (
responseHeader ,
"name" ,
replaceWith
) ;
2022-04-12 08:57:07 -04:00
responseBody = fullAnswerObject . response _body ;
} else {
responseHeader = fullAnswerObject . response _header ;
responseBody = fullAnswerObject . response _body ;
}
showResponse ( responseHeader , responseBody ) ;
}
} else if ( apiQues . type == 8 ) {
showResponse ( false , false , true ) ;
}
}
}
// hide all answers row
var divsToHide = document . getElementsByClassName ( "answerRow" ) ; //divsToHide is an array
for ( var i = 0 ; i < divsToHide . length ; i ++ ) {
divsToHide [ i ] . style . display = "none" ; // depending on what you're doing
}
//hide question row
$ ( "#questionRow" ) . css ( "display" , "none" ) ;
if ( hasNoResponse ) {
if ( currentQuestionCounter < totalQuizQuestions . length ) {
return askQuestion ( totalQuizQuestions , currentQuestionCounter ) ;
} else {
if ( currentQuizIndex + 1 < allItems . length ) {
currentQuizIndex ++ ;
currentQuestionCounter = 0 ;
totalQuizQuestions = allItems [ currentQuizIndex ] . questions ;
showQuizTitle ( ) ;
return askQuestion ( totalQuizQuestions , currentQuestionCounter ) ;
} else {
return showPreparingPage ( ) ;
}
}
}
} // nextQuestion function ends here
function showResponse ( responseHead , responseBody , weatherQuestion ) {
responseOnGoing = true ;
hasNoResponse = false ;
$ ( "#page3" ) . css ( "display" , "none" ) ;
$ ( "#page5 #weatherApi" ) . css ( "display" , "none" ) ;
$ ( "#progressBarSection" ) . css ( "display" , "block" ) ;
$ ( "#page5" ) . css ( "display" , "block" ) ;
if ( responseHead ) {
$ ( "#page5 .responseRow .responseInner .responseHead" ) . html ( "" ) ;
2025-07-24 22:56:01 +01:00
$ ( "#page5 .responseRow .responseInner .responseHead" ) . css (
"display" ,
"block"
) ;
2022-04-12 08:57:07 -04:00
$ ( "#page5 .responseRow .responseInner .responseHead" ) . append ( `
<h1> ${ responseHead } </h1>
` ) ;
} else {
$ ( "#page5 .responseRow .responseInner .responseHead" ) . html ( "" ) ;
}
if ( responseBody ) {
$ ( "#page5 .responseRow .responseInner .responseBody" ) . html ( "" ) ;
2025-07-24 22:56:01 +01:00
$ ( "#page5 .responseRow .responseInner .responseBody" ) . css (
"display" ,
"block"
) ;
2022-04-12 08:57:07 -04:00
$ ( "#page5 .responseRow .responseInner .responseBody" ) . append ( `
<p> ${ responseBody } </p>
` ) ;
} else {
$ ( "#page5 .responseRow .responseInner .responseBody" ) . html ( "" ) ;
}
if ( weatherQuestion ) {
$ ( "#page5 #weatherApi" ) . css ( "display" , "block" ) ;
}
2025-07-24 22:56:01 +01:00
// 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... ` ) ;
} else {
clearInterval ( responseCountdownInterval ) ;
$ ( "#responseCountdown" ) . hide ( ) ;
}
} , 1000 ) ;
2022-04-12 08:57:07 -04:00
closeResponseTimeout = setTimeout ( ( ) => {
2025-07-24 22:56:01 +01:00
clearInterval ( responseCountdownInterval ) ;
$ ( "#responseCountdown" ) . hide ( ) ;
2022-04-12 08:57:07 -04:00
closeResponse ( ) ;
} , closeResponseTimeoutCounter ) ;
}
// function to close response page
function closeResponse ( ) {
responseOnGoing = false ;
hasNoResponse = true ;
2025-07-24 22:56:01 +01:00
clearInterval ( responseCountdownInterval ) ;
$ ( "#responseCountdown" ) . hide ( ) ;
2022-04-12 08:57:07 -04:00
$ ( "#page5" ) . css ( "display" , "none" ) ;
$ ( "#page4" ) . css ( "display" , "none" ) ;
$ ( "#page3" ) . css ( "display" , "block" ) ;
if ( currentQuestionCounter < totalQuizQuestions . length ) {
return askQuestion ( totalQuizQuestions , currentQuestionCounter ) ;
} else {
if ( currentQuizIndex + 1 < allItems . length ) {
currentQuizIndex ++ ;
currentQuestionCounter = 0 ;
totalQuizQuestions = allItems [ currentQuizIndex ] . questions ;
showQuizTitle ( ) ;
return askQuestion ( totalQuizQuestions , currentQuestionCounter ) ;
} else {
return showPreparingPage ( ) ;
}
}
} // function closeResponse ends here
async function askQuestion ( totalQuizQuestions , counter , fromBack ) {
2025-07-24 22:56:01 +01:00
// Always hide all answer rows before showing the current one
$ ( ".answerRow" ) . hide ( ) ;
2022-04-12 08:57:07 -04:00
clearTimeout ( timeout ) ;
clearTimeout ( closeResponseTimeout ) ;
var ques = totalQuizQuestions [ counter ] ;
var dependsOn = ques . depends _on ;
argument = ques . question _arguments ;
argument = JSON . parse ( argument ) ;
var type = 1 ;
var note = ques . note ;
var noteType = ques . note _type ;
weights = { } ;
sliderAns = "" ;
sliderVal = 0 ;
sliderBLActives = [ ] ;
tempMcqAns = "" ;
tempMcqAnsValue = 0 ;
tempMcqiBLActives = [ ] ;
tempMcqiAns = "" ;
tempMcqiAnsValue = 0 ;
tempMcqBLActives = [ ] ;
tempSelectionAns = [ ] ;
minRangeVal = null ;
maxRangeVal = null ;
isSkipStoreAnswer = false ;
saveResponseInto = "" ;
responseOnGoing = false ;
hasNoResponse = true ;
lastCurrentQuizQuesInProgress = false ;
// checking if the question depends on another question or not
if ( dependsOn ) {
let dependedQuesId = dependsOn . split ( "|" ) [ 0 ] ;
let wantedAnswer = dependsOn . split ( "|" ) [ 1 ] ;
const userAnswerToDependedQuestion = dataToReturn . find ( function ( item ) {
return item . question . id == parseInt ( dependedQuesId ) ;
} ) ;
2025-07-24 22:56:01 +01:00
if (
! userAnswerToDependedQuestion ||
! userAnswerToDependedQuestion . answer ||
userAnswerToDependedQuestion . answer ? . toLowerCase ( ) !=
wantedAnswer ? . toLowerCase ( )
) {
2022-04-12 08:57:07 -04:00
currentActiveAnswerType = null ;
isSkipStoreAnswer = true ;
currentQuestionCounter ++ ;
if ( currentQuestionCounter >= totalQuizQuestions . length ) {
currentQuizIndex ++ ;
currentQuestionCounter = 0 ;
totalQuizQuestions = allItems [ currentQuizIndex ] . questions ;
showQuizTitle ( ) ;
}
return await nextQuestion ( false , false , true ) ;
}
}
lastShowedQuestionId = ques . id ;
if ( ! fromBack ) {
uniqueQuestionsShowed . push ( {
quiz : ques . quiz _id ,
question : ques . id ,
counter : currentQuestionCounter ,
progress : progress ,
} ) ;
}
// displaying note if it exists
if ( note ) {
$ ( "#noteRow" ) . css ( "display" , "flex" ) ;
$ ( "#noteRow .noteDesc p" ) . html ( note ) ;
$ ( "#page3 .questionRow" ) . removeClass ( "no-note" ) ;
$ ( "#page3 .row.noteRow" ) . removeClass ( "image-below" ) ;
if ( noteType == 1 ) {
$ ( "#noteRow .noteTitle h4" ) . html ( "- Note -" ) ;
} else {
$ ( "#noteRow .noteTitle h4" ) . html ( "- Scientific Note -" ) ;
}
} else {
2025-07-24 22:56:01 +01:00
if ( ! $ ( "#page3 .questionRow.mtb" ) . hasClass ( "no-note" ) )
$ ( "#page3 .questionRow.mtb" ) . addClass ( "no-note" ) ;
2022-04-12 08:57:07 -04:00
$ ( "#noteRow" ) . css ( "display" , "none" ) ;
}
// end of displaying note
if ( dataToReturn && dataToReturn . length > 0 ) {
var alreadyAnswered = dataToReturn . find ( function ( answer ) {
return answer . question . id == ques . id ;
} ) ;
}
if ( oldAnswers && oldAnswers . length > 0 ) {
//get the answer
var currenQuesAnswerObj = oldAnswers . find ( ( answerObj ) => {
return answerObj . question . id == ques . id ;
} ) ;
}
// displaying question
$ ( "#questionRow" ) . css ( "display" , "block" ) ;
2025-07-24 22:56:01 +01:00
if ( ! $ ( "#page3 .questionRow" ) . hasClass ( "no-image" ) )
$ ( "#page3 .questionRow" ) . addClass ( "no-image" ) ;
2022-04-12 08:57:07 -04:00
type = ques . type ;
if ( ques . id == 1 ) {
2025-07-24 22:56:01 +01:00
if ( $ ( "#page3 .container" ) . hasClass ( "mto" ) )
$ ( ".container" ) . removeClass ( "mto" ) ;
2022-04-12 08:57:07 -04:00
$ ( "#page3 .questionRow.mtb" ) . removeClass ( "mtb" ) ;
$ ( "#page3 .container" ) . addClass ( "center-everything" ) ;
$ ( "#identity" ) . addClass ( "hide" ) ;
saveResponseInto = ques . save _response _into ;
} else {
2025-07-24 22:56:01 +01:00
if ( $ ( "#page3 .container" ) . hasClass ( "center-everything" ) )
$ ( "#page3 .container" ) . removeClass ( "center-everything" ) ;
if ( ! $ ( "#page3 .questionRow" ) . hasClass ( "mtb" ) )
$ ( "#page3 .questionRow" ) . addClass ( "mtb" ) ;
2022-04-12 08:57:07 -04:00
$ ( "#page3 .container" ) . addClass ( "mto" ) ;
$ ( "#identity" ) . removeClass ( "hide" ) ;
}
// checking question type
if ( type == 1 ) {
$ ( "#typeText" ) . css ( "display" , "block" ) ;
$ ( "#typeText input" ) . removeAttr ( "disabled" ) ;
$ ( "#typeText input" ) . removeClass ( "disabled" ) ;
currentActiveAnswerType = "typeText" ;
$ ( "#typeText input" ) . val ( "" ) ;
$ ( "#typeText input" ) . attr ( "placeholder" , ques . placeholder ) ;
$ ( "#typeText input" ) . attr ( "name" , ques . placeholder ) ;
$ ( "#typeText input" ) . attr ( "id" , ques . placeholder ) ;
if ( alreadyAnswered && alreadyAnswered . answer ) {
$ ( "#typeText input" ) . val ( alreadyAnswered . answer ) ;
2025-07-24 22:56:01 +01:00
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
2022-04-12 08:57:07 -04:00
$ ( "#typeText input" ) . val ( currenQuesAnswerObj . answer ) ;
} else {
if ( ques . id == 14 ) {
if ( customerEmail ) {
$ ( "#typeText input" ) . val ( $ ( customerEmail ) . text ( ) ) ;
}
}
}
$ ( "#typeText input" ) . trigger ( "focus" ) ;
} // type 1 ends here
else if ( type == 2 || type == 3 ) {
$ ( "#typeNum" ) . css ( "display" , "block" ) ;
currentActiveAnswerType = "typeNum" ;
$ ( "#typeNum input" ) . attr ( "placeholder" , ques . placeholder ) ;
$ ( "#typeNum input" ) . attr ( "name" , ques . placeholder ) ;
$ ( "#typeNum input" ) . attr ( "id" , ques . placeholder ) ;
if ( alreadyAnswered && alreadyAnswered . answer ) {
$ ( "#typeNum input" ) . val ( alreadyAnswered . answer ) ;
2025-07-24 22:56:01 +01:00
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
2022-04-12 08:57:07 -04:00
$ ( "#typeNum input" ) . val ( currenQuesAnswerObj . answer ) ;
}
if ( ques . save _response _into ) saveResponseInto = ques . save _response _into ;
$ ( "#typeNum input" ) . trigger ( "focus" ) ;
} // type 2 and 3 ends here
else if ( type == 4 ) {
$ ( "#typeMcq .answerInner" ) . html ( "" ) ;
$ ( "#typeMcq" ) . css ( "display" , "block" ) ;
currentActiveAnswerType = "typeMcq" ;
ques . answers . forEach ( ( val ) => {
if ( val . answer ) {
$ ( "#typeMcq .answerInner" ) . append ( `
<div class="mcqOptions">
<button data-val=" ${ val . answer } " data-id=" ${ val . id } " data-answer-value=" ${ val . answer _value } " data-bl-active=' ${ val . black _list _actives } ' class="multiBtns mcqBtn"> ${ val . answer } </button>
</div>
` ) ;
}
} ) ;
if ( alreadyAnswered && alreadyAnswered . answer ) {
2025-07-24 22:56:01 +01:00
$ ( ` #typeMcq button[data-val=" ${ alreadyAnswered . answer } "] ` ) . addClass (
"highlight"
) ;
selectAlreadyMcqAnswered (
` #typeMcq button[data-val=" ${ alreadyAnswered . answer } "] `
) ;
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
$ ( ` #typeMcq button[data-val=" ${ currenQuesAnswerObj . answer } "] ` ) . addClass (
"highlight"
) ;
selectAlreadyMcqAnswered (
` #typeMcq button[data-val=" ${ currenQuesAnswerObj . answer } "] `
) ;
2022-04-12 08:57:07 -04:00
}
} // type 4 ends here
else if ( type == 5 ) {
$ ( "#typeMcqi .answerInner" ) . html ( "" ) ;
$ ( "#typeMcqi" ) . css ( "display" , "block" ) ;
console . log ( ques ) ;
currentActiveAnswerType = "typeMcqi" ;
ques . answers . forEach ( ( val ) => {
if ( val . answer && val . image && ques . image _width && ques . image _height ) {
$ ( "#typeMcqi .answerInner" ) . append ( `
2025-07-24 22:56:01 +01:00
<div class="mcqiOptions" style="width: ${
ques . image _width
} px; height: ${ ques . image _height } px;">
<button data-id=" ${ val . id } " data-val=" ${
val . answer
} " data-answer-value=" ${ val . answer _value } " data-bl-active=' ${
val . black _list _actives
} ' class="mcqiBtn">
<img class="mcqiImg" src=" ${
url _preset + val . image . url
} " alt="image missing">
2022-04-12 08:57:07 -04:00
</button>
</div>
` ) ;
2025-07-24 22:56:01 +01:00
if ( ! $ ( "#page3 .row.noteRow" ) . hasClass ( "image-below" ) )
$ ( "#page3 .row.noteRow" ) . addClass ( "image-below" ) ;
2022-04-12 08:57:07 -04:00
$ ( "#page3 .questionRow" ) . removeClass ( "no-image" ) ;
}
} ) ;
if ( alreadyAnswered && alreadyAnswered . answer ) {
2025-07-24 22:56:01 +01:00
$ ( ` #typeMcqi button[data-val=" ${ alreadyAnswered . answer } "] ` ) . addClass (
"highlight"
) ;
selectAlreadyMcqiAnswered (
` #typeMcqi button[data-val=" ${ alreadyAnswered . answer } "] `
) ;
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
$ ( ` #typeMcqi button[data-val=" ${ currenQuesAnswerObj . answer } "] ` ) . addClass (
"highlight"
) ;
selectAlreadyMcqiAnswered (
` #typeMcqi button[data-val=" ${ currenQuesAnswerObj . answer } "] `
) ;
2022-04-12 08:57:07 -04:00
}
} // type 5 ends here
else if ( type == 6 ) {
$ ( ".slider" ) . removeClass ( "active" ) ;
let atleastOneImage = false ;
ranges = [ ] ;
$ ( "#typeSlide .answerInner .sliderRanges" ) . html ( "" ) ;
$ ( "#typeSlide .answerInner .imgDiv" ) . html ( "" ) ;
$ ( "#typeSlide" ) . css ( "display" , "block" ) ;
currentActiveAnswerType = "typeSlide" ;
if ( ques . save _response _into ) saveResponseInto = ques . save _response _into ;
minRangeVal = parseFloat ( ques . slider _range . split ( "-" ) [ 0 ] ) ;
maxRangeVal = parseFloat ( ques . slider _range . split ( "-" ) [ 1 ] ) ;
$ ( "#myRange" ) . attr ( "min" , minRangeVal ) ;
$ ( "#myRange" ) . attr ( "max" , maxRangeVal ) ;
$ ( "#typeSlide #myRange" ) . val ( minRangeVal ) ;
var numOfAnswers = ques . answers . length ;
let minStep = 0 ;
let incremental = parseFloat ( maxRangeVal ) / parseFloat ( numOfAnswers ) ;
ques . answers . forEach ( ( val , index ) => {
let hasImage = false ;
if ( val . image && val . image . id && val . image . url ) {
atleastOneImage = true ;
hasImage = {
id : val . image . id ,
url : url _preset + val . image . url ,
width : val . image . width ,
height : val . image . height ,
} ;
2025-07-24 22:56:01 +01:00
if ( ! $ ( "#page3 .row.noteRow" ) . hasClass ( "image-below" ) )
$ ( "#page3 .row.noteRow" ) . addClass ( "image-below" ) ;
2022-04-12 08:57:07 -04:00
$ ( "#page3 .questionRow" ) . removeClass ( "no-image" ) ;
if ( index == 0 ) {
$ ( "#typeSlide .answerInner .imgDiv" ) . css ( "display" , "block" ) ;
2025-07-24 22:56:01 +01:00
$ ( "#typeSlide .answerInner .imgDiv" ) . append (
` <img id=" ${ hasImage . id } " src=" ${ hasImage . url } " alt="Image missing"> `
) ;
2022-04-12 08:57:07 -04:00
}
} else {
$ ( "#page3 .row.noteRow" ) . removeClass ( "image-below" ) ;
}
ranges . push ( {
min : minStep ,
max : minStep + incremental ,
image : hasImage ,
answer : val . answer ,
2025-07-24 22:56:01 +01:00
black _list _actives : val . black _list _actives
? JSON . parse ( val . black _list _actives )
: [ ] ,
2022-04-12 08:57:07 -04:00
output _var : ques . output _variable _name ,
weight : ques . weight ,
2025-07-24 22:56:01 +01:00
extra _var : ques . extra _output _variable
? JSON . parse ( ques . extra _output _variable )
: [ ] ,
2022-04-12 08:57:07 -04:00
} ) ;
//add ranges
$ ( "#typeSlide .answerInner .sliderRanges" ) . append ( `
2025-07-24 22:56:01 +01:00
<div data-val=" ${ val . answer } " data-id=" ${
val . id
} " data-min-range=" ${ minStep } " data-max-range=" ${
minStep + incremental
} " class="ranges">
2022-04-12 08:57:07 -04:00
${ val . hide _answer == 1 ? "" : val . answer }
</div>
` ) ;
minStep = minStep + incremental ;
} ) ;
if ( ! atleastOneImage ) {
2025-07-24 22:56:01 +01:00
if ( ! $ ( "#page3 .questionRow" ) . hasClass ( "no-image" ) )
$ ( "#page3 .questionRow" ) . addClass ( "no-image" ) ;
2022-04-12 08:57:07 -04:00
}
2025-07-24 22:56:01 +01:00
$ ( ".sliderRanges div" ) . css (
"width" ,
` ${ parseFloat ( 1 / ques . answers . length ) * 100 } % `
) ;
2022-04-12 08:57:07 -04:00
if ( alreadyAnswered && alreadyAnswered . answer ) {
$ ( ` #typeSlide #myRange ` ) . val ( parseFloat ( alreadyAnswered . slider _value ) ) ;
$ ( "#myRange" ) . trigger ( "input" , [ true ] ) ;
2025-07-24 22:56:01 +01:00
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
$ ( ` #typeSlide #myRange ` ) . val (
parseFloat ( currenQuesAnswerObj . slider _value )
) ;
2022-04-12 08:57:07 -04:00
$ ( "#myRange" ) . trigger ( "input" , [ true ] ) ;
}
} // type 6 ends here
else if ( type == 7 ) {
$ ( "#typeSelection .answerInner" ) . html ( "" ) ;
$ ( "#typeSelection" ) . css ( "display" , "block" ) ;
currentActiveAnswerType = "typeSelection" ;
ques . answers . forEach ( ( val , index ) => {
if ( val . answer ) {
$ ( "#typeSelection .answerInner" ) . append ( `
<div class="selectionOptions">
2025-07-24 22:56:01 +01:00
<button data-val=" ${ val . answer } " data-id=" ${ val . id } " class="selectionBtns selectionBtn" onclick="checkAllergie(this)"> ${ val . answer } </button>
2022-04-12 08:57:07 -04:00
</div>
` ) ;
}
} ) ;
2025-07-24 22:56:01 +01:00
// Add 'None of the above' button
$ ( "#typeSelection .answerInner" ) . append ( `
<div class="selectionOptions">
<button class="selectionBtns selectionBtn noneOfTheAboveBtn" onclick="handleNoneOfTheAbove()">None of the above</button>
</div>
` ) ;
2022-04-12 08:57:07 -04:00
if ( alreadyAnswered && alreadyAnswered . answer ) {
if ( Array . isArray ( alreadyAnswered . answer ) ) {
alreadyAnswered . answer . forEach ( ( answer ) => {
if ( ! [ "Banana" , "Olive" , "Sunflowers" ] . includes ( answer ) ) {
2025-07-24 22:56:01 +01:00
$ ( ` #typeSelection button[data-val=" ${ answer } "] ` ) . trigger ( "click" , [
true ,
] ) ;
2022-04-12 08:57:07 -04:00
}
} ) ;
}
2025-07-24 22:56:01 +01:00
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
2022-04-12 08:57:07 -04:00
if ( Array . isArray ( currenQuesAnswerObj . answer ) ) {
currenQuesAnswerObj . answer . forEach ( ( answer ) => {
if ( ! [ "Banana" , "Olive" , "Sunflowers" ] . includes ( answer ) ) {
2025-07-24 22:56:01 +01:00
$ ( ` #typeSelection button[data-val=" ${ answer } "] ` ) . trigger ( "click" , [
true ,
] ) ;
2022-04-12 08:57:07 -04:00
}
} ) ;
}
}
} //type 7 ends here
else if ( type == 8 ) {
$ ( "#typeGeo" ) . css ( "display" , "block" ) ;
currentActiveAnswerType = "typeGeo" ;
$ ( "#typeGeo input#city" ) . val ( "" ) ;
$ ( "#typeGeo input#city" ) . attr ( "placeholder" , ques . placeholder ) ;
if ( alreadyAnswered && alreadyAnswered . answer ) {
$ ( "#typeGeo input#city" ) . val ( alreadyAnswered . answer ) ;
$ ( "#typeGeo #city_id" ) . val ( alreadyAnswered . city _id ) ;
2025-07-24 22:56:01 +01:00
} else if (
currenQuesAnswerObj &&
currenQuesAnswerObj . answer &&
! alreadyAnswered
) {
2022-04-12 08:57:07 -04:00
$ ( "#typeGeo input#city" ) . val ( currenQuesAnswerObj . answer ) ;
$ ( "#typeGeo #city_id" ) . val ( currenQuesAnswerObj . city _id ) ;
}
$ ( "#typeGeo input#city" ) . trigger ( "focus" ) ;
}
if ( argument != null ) {
var newQues = ques . question ;
var replaceWith = localStorage . getItem ( argument [ 0 ] ) ;
newQues = inject _substitute ( newQues , "name" , replaceWith ) ;
$ ( "#questionRow h1" ) . html ( newQues ) ;
} else {
$ ( "#questionRow h1" ) . html ( ques . question ) ;
}
currentQuestionCounter ++ ;
2025-07-24 22:56:01 +01:00
// At the end of askQuestion, always update the nav bar
renderQuestionNavBar ( ) ;
2022-04-12 08:57:07 -04:00
}
async function storeAnswer ( currentQuestion , currentActiveAnswerType ) {
var temp = [ ] ;
temp [ "question" ] = currentQuestion ;
let answerExists = dataToReturn . findIndex ( function ( answerObject ) {
return answerObject . question ? . id == temp . question ? . id ;
} ) ;
console . log ( answerExists ) ;
if ( currentActiveAnswerType == "typeText" ) {
ans = $ ( "#" + currentActiveAnswerType + " input" ) . val ( ) ;
if ( saveResponseInto == "name" ) {
if ( ! ans ) {
ans = "You" ;
}
localStorage . setItem ( "name" , ans ) ;
}
temp [ "answer" ] = ans ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeNum" ) {
ans = $ ( "#" + currentActiveAnswerType + " input" ) . val ( ) ;
if ( saveResponseInto == "age" ) {
UserBirth = ans ;
if ( UserBirth ) {
age = calculateAge ( UserBirth ) ;
weights [ currentQuestion . output _variable _name ] = {
value : parseFloat ( age ) * currentQuestion . weight ,
base : currentQuestion . weight ,
} ;
if ( currentQuestion . extra _output _variable ) {
let extra _var = JSON . parse ( currentQuestion . extra _output _variable ) ;
extra _var . forEach ( function ( extra ) {
weights [ extra . name ] = {
value : parseFloat ( age ) * extra . weight ,
base : extra . weight ,
} ;
} ) ;
}
temp [ "weights" ] = weights ;
}
}
temp [ "answer" ] = ans ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeMcq" ) {
ans = tempMcqAns ;
if ( currentQuestion . output _variable _name ) {
weights [ currentQuestion . output _variable _name ] = {
value : parseFloat ( tempMcqAnsValue ) * currentQuestion . weight ,
base : currentQuestion . weight ,
} ;
if ( currentQuestion . extra _output _variable ) {
let extra _var = JSON . parse ( currentQuestion . extra _output _variable ) ;
extra _var . forEach ( function ( extra ) {
weights [ extra . name ] = {
value : parseFloat ( tempMcqAnsValue ) * parseFloat ( extra . weight ) ,
base : parseFloat ( extra . weight ) ,
} ;
} ) ;
}
temp [ "weights" ] = weights ;
}
temp [ "answer" ] = ans ;
temp [ "black_list_actives" ] = tempMcqBLActives ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeMcqi" ) {
ans = tempMcqiAns ;
if ( currentQuestion . output _variable _name ) {
weights [ currentQuestion . output _variable _name ] = {
value : parseFloat ( tempMcqiAnsValue ) * currentQuestion . weight ,
base : currentQuestion . weight ,
} ;
if ( currentQuestion . extra _output _variable ) {
let extra _var = JSON . parse ( currentQuestion . extra _output _variable ) ;
extra _var . forEach ( function ( extra ) {
weights [ extra . name ] = {
value : parseFloat ( tempMcqiAnsValue ) * parseFloat ( extra . weight ) ,
base : parseFloat ( extra . weight ) ,
} ;
} ) ;
}
temp [ "weights" ] = weights ;
}
temp [ "answer" ] = ans ;
temp [ "black_list_actives" ] = tempMcqiBLActives ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeSlide" ) {
ans = sliderAns ;
temp [ "answer" ] = ans ;
temp [ "slider_value" ] = sliderVal ;
temp [ "weights" ] = weights ;
temp [ "black_list_actives" ] = sliderBLActives ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeSelection" ) {
ans = tempSelectionAns ;
temp [ "answer" ] = ans ;
temp [ "black_list_actives" ] = tempSelectionAns ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
} else if ( currentActiveAnswerType == "typeGeo" ) {
ans = $ ( "#typeGeo input#city" ) . val ( ) ;
city _id = $ ( "#typeGeo #city_id" ) . val ( ) ;
//check if answer but not city_id
if ( ! ans ) {
return false ;
}
if ( ans && ! city _id ) {
2025-07-24 22:56:01 +01:00
await fetch (
url _preset +
"/api/v1/places/autocomplete?input=" +
ans . replace ( / /g , "" )
)
2022-04-12 08:57:07 -04:00
. then ( ( res ) => res . json ( ) )
. then ( function ( data ) {
city _id = data [ 0 ] . id ;
} ) ;
}
try {
if ( ! $ ( ".lds-ring" ) . hasClass ( "active" ) ) $ ( ".lds-ring" ) . addClass ( "active" ) ;
2025-07-24 22:56:01 +01:00
const payload = await fetch (
url _preset + ` /api/v1/weather-profile?city_id= ${ city _id } `
) . then ( ( response ) => response . json ( ) ) ;
2022-04-12 08:57:07 -04:00
if ( payload . success && payload . data ) {
temp [ "weights" ] = payload . data . weights ;
$ ( "#humidity .info-value" ) . html ( payload . data . humidity ) ;
2025-07-24 22:56:01 +01:00
$ ( "#temp .info-value" ) . html (
` ${ payload . data . temperature } ${ payload . data . unit } `
) ;
2022-04-12 08:57:07 -04:00
$ ( "#sun .info-value" ) . html ( payload . data . sun ) ;
$ ( "#pollution .info-value" ) . html ( payload . data . pollution ) ;
} else {
throw new Error ( ) ;
}
} catch ( err ) {
$ ( "#weatherApi" ) . html ( "Couldn't get your location." ) ;
$ ( "#weatherApi" ) . css ( {
font : "italic 42px 'Bradford LL'" ,
"text-align" : "center" ,
} ) ;
}
$ ( ".lds-ring" ) . removeClass ( "active" ) ;
temp [ "answer" ] = ans ;
temp [ "city_id" ] = city _id ;
temp = Object . assign ( { } , temp ) ;
if ( temp [ "answer" ] ) {
if ( answerExists == - 1 ) {
dataToReturn . push ( temp ) ;
} else {
const dependedOnQuestions = dataToReturn . filter ( ( ansObj , index ) => {
2025-07-24 22:56:01 +01:00
if (
ansObj . question . depends _on &&
ansObj . question . depends _on . split ( "|" ) [ 0 ] == temp [ "question" ] . id
) {
2022-04-12 08:57:07 -04:00
ansObj . obj _index = index ;
return ansObj ;
}
} ) ;
2025-07-24 22:56:01 +01:00
if (
dependedOnQuestions &&
temp [ "answer" ] !== dataToReturn [ answerExists ] . answer
) {
2022-04-12 08:57:07 -04:00
dependedOnQuestions . forEach ( ( dq ) => {
dataToReturn . splice ( dq . obj _index , 1 ) ;
} ) ;
}
dataToReturn [ answerExists ] = temp ;
}
}
}
localStorage . setItem ( "answers" , JSON . stringify ( dataToReturn ) ) ;
2025-07-24 22:56:01 +01:00
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 ( ) ;
2022-04-12 08:57:07 -04:00
}
let currentSuggestIndex ;
let oldVal ;
let itemSelected = false ;
let enterOnce = false ;
$ ( document ) . on ( "click focus" , async function ( event ) {
2025-07-24 22:56:01 +01:00
if (
! event . target . closest ( "#result" ) &&
! event . target . closest ( "#typeGeo input" )
) {
2022-04-12 08:57:07 -04:00
$ ( "#result" ) . css ( {
display : "none" ,
} ) ;
} else if ( event . target . closest ( "#typeGeo input" ) ) {
$ ( "#result" ) . css ( {
display : "block" ,
} ) ;
}
} ) ;
$ ( document ) . on ( "click" , "li.autocomplete-item" , async function ( event ) {
enterOnce = true ;
$ ( "#typeGeo input[type=search]" ) . val ( $ ( this ) . text ( ) ) ;
$ ( "#typeGeo #city_id" ) . val ( $ ( this ) . attr ( "data-place-id" ) ) ;
$ ( "#result" ) . css ( {
display : "none" ,
} ) ;
$ ( "#typeGeo input[type=search]" ) . trigger ( "focus" ) ;
} ) ;
$ ( "#typeText input" ) . on ( "keyup" , function ( evt ) {
if ( [ "Enter" ] . includes ( evt . key ) ) {
return nextQuestion ( ) ;
}
} ) ;
$ ( "#typeNum input" ) . on ( "keyup" , function ( evt ) {
if ( [ "Enter" ] . includes ( evt . key ) ) {
return nextQuestion ( ) ;
}
} ) ;
$ ( "#typeGeo input" ) . on ( "keyup" , function ( evt ) {
const val = $ ( this ) . val ( ) ;
if ( [ "ArrowDown" , "ArrowUp" , "Enter" ] . includes ( evt . key ) ) {
if ( evt . key == "Enter" ) {
if ( ! enterOnce ) {
enterOnce = true ;
} else {
return nextQuestion ( ) ;
}
$ ( "#typeGeo input" ) . val ( $ ( "#suggestion-list li.active.selected" ) . text ( ) ) ;
2025-07-24 22:56:01 +01:00
$ ( "#typeGeo #city_id" ) . val (
$ ( "#suggestion-list li.active.selected" ) . attr ( "data-place-id" )
) ;
2022-04-12 08:57:07 -04:00
$ ( "#result" ) . css ( {
display : "none" ,
} ) ;
return false ;
}
enterOnce = false ;
$ ( "#result" ) . css ( {
display : "block" ,
} ) ;
$ ( ` #suggestion-list li ` ) . removeClass ( "active" ) ;
$ ( ` #suggestion-list li ` ) . removeClass ( "selected" ) ;
let listLength = $ ( "#suggestion-list li" ) . length ;
if ( evt . key == "ArrowDown" ) {
currentSuggestIndex = currentSuggestIndex ? currentSuggestIndex + 1 : 1 ;
if ( currentSuggestIndex > listLength ) {
currentSuggestIndex = 1 ;
}
} else if ( evt . key == "ArrowUp" ) {
2025-07-24 22:56:01 +01:00
currentSuggestIndex = currentSuggestIndex
? currentSuggestIndex - 1
: listLength ;
2022-04-12 08:57:07 -04:00
if ( currentSuggestIndex < 1 ) {
currentSuggestIndex = listLength ;
}
}
2025-07-24 22:56:01 +01:00
$ ( ` #suggestion-list li:nth-child( ${ currentSuggestIndex } ) ` ) . addClass (
"active"
) ;
$ ( ` #suggestion-list li:nth-child( ${ currentSuggestIndex } ) ` ) . addClass (
"selected"
) ;
2022-04-12 08:57:07 -04:00
return false ;
}
if ( val == oldVal ) {
return false ;
} else {
oldVal = val ;
}
res = $ ( "#result" ) . css ( {
display : "block" ,
} ) ;
res . html ( "" ) ;
if ( val == "" ) {
return ;
}
let list = "" ;
2025-07-24 22:56:01 +01:00
fetch (
url _preset + "/api/v1/places/autocomplete?input=" + val . replace ( / /g , "" )
)
2022-04-12 08:57:07 -04:00
. then ( ( res ) => res . json ( ) )
. then ( function ( data ) {
for ( i = 0 ; i < data . length ; i ++ ) {
2025-07-24 22:56:01 +01:00
list +=
` <li class='autocomplete-item' data-place-id=' ${
data [ i ] . id
} ' tabindex=' ${ i + 1 } '> ` +
data [ i ] . name +
"</li>" ;
2022-04-12 08:57:07 -04:00
}
res . html ( ` <ul id='suggestion-list'> ` + list + ` </ul> ` ) ;
return true ;
} )
. catch ( function ( err ) {
console . warn ( "Something went wrong." , err ) ;
return false ;
} ) ;
} ) ;
//handlers
$ ( document ) . on ( "input" , "#myRange" , async function ( event , isCustom ) {
clearTimeout ( timeout ) ;
sliderVal = parseFloat ( $ ( this ) . val ( ) ) ;
let currRange = ranges . find ( function ( range ) {
return sliderVal >= range . min && sliderVal <= range . max ;
} ) ;
sliderAns = currRange . answer ;
let percentageMultiplier = ( 1 / ( maxRangeVal - minRangeVal ) ) * 100 ;
weights [ currRange . output _var ] = {
value : ( sliderVal - minRangeVal ) * percentageMultiplier * currRange . weight ,
base : currRange . weight ,
} ;
if ( currRange . extra _var && currRange . extra _var . length ) {
currRange . extra _var . forEach ( function ( extra ) {
weights [ extra . name ] = {
value : sliderVal * parseFloat ( extra . weight ) ,
base : parseFloat ( extra . weight ) ,
} ;
} ) ;
}
sliderBLActives = currRange . black _list _actives ;
if ( currRange . image ) {
if ( $ ( "#typeSlide .answerInner .imgDiv img" ) . length == 0 ) {
2025-07-24 22:56:01 +01:00
$ ( "#typeSlide .answerInner .imgDiv" ) . append (
` <img id=" ${ currRange . image . id } " src=" ${ currRange . image . url } " alt="Image missing"> `
) ;
2022-04-12 08:57:07 -04:00
} else {
$ ( "#typeSlide .answerInner .imgDiv img" ) . attr ( "id" , currRange . image . id ) ;
$ ( "#typeSlide .answerInner .imgDiv img" ) . attr ( "src" , currRange . image . url ) ;
}
} else {
$ ( "#typeSlide .answerInner .imgDiv" ) . html ( "" ) ;
}
if ( ! isCustom ) {
timeout = setTimeout ( function ( ) {
nextQuestion ( ) ;
} , nextQuestionTimeoutCounter ) ;
}
} ) ;
$ ( document ) . on ( "click" , ".selectionBtn" , function ( evt , isCustom ) {
clearTimeout ( timeout ) ;
var val = $ ( this ) . attr ( "data-val" ) ;
if ( $ ( this ) . hasClass ( "active" ) ) {
tempSelectionAns . splice ( tempSelectionAns . indexOf ( val ) , 1 ) ;
$ ( this ) . removeClass ( "active" ) ;
$ ( this ) . removeClass ( "highlight" ) ;
} else {
tempSelectionAns . push ( val ) ;
if ( ! $ ( this ) . hasClass ( "active" ) ) $ ( this ) . addClass ( "active" ) ;
if ( ! $ ( this ) . hasClass ( "highlight" ) ) $ ( this ) . addClass ( "highlight" ) ;
}
if ( ! isCustom ) {
timeout = setTimeout ( function ( ) {
nextQuestion ( ) ;
} , selectionQuestionTimeoutCounter ) ;
}
} ) ;
$ ( document ) . on ( "click" , ".mcqiBtn" , async function ( ) {
tempMcqiAns = $ ( this ) . attr ( "data-val" ) ;
tempMcqiAnsValue = $ ( this ) . attr ( "data-answer-value" ) ;
if ( $ ( this ) . attr ( "data-bl-active" ) ) {
tempMcqiBLActives = JSON . parse ( $ ( this ) . attr ( "data-bl-active" ) ) ;
}
return await nextQuestion ( ) ;
} ) ;
$ ( document ) . on ( "click" , ".mcqBtn" , async function ( ) {
tempMcqAns = $ ( this ) . attr ( "data-val" ) ;
tempMcqAnsValue = $ ( this ) . attr ( "data-answer-value" ) ;
if ( $ ( this ) . attr ( "data-bl-active" ) ) {
tempMcqBLActives = JSON . parse ( $ ( this ) . attr ( "data-bl-active" ) ) ;
}
return await nextQuestion ( ) ;
} ) ;
function inject _substitute ( text , normalKey , value ) {
text = text . replace ( new RegExp ( "<<<" + normalKey + ">>>" , "g" ) , value ) ;
return text ;
}
function selectAlreadyMcqAnswered ( self ) {
tempMcqAns = $ ( self ) . attr ( "data-val" ) ;
tempMcqAnsValue = $ ( self ) . attr ( "data-answer-value" ) ;
if ( $ ( self ) . attr ( "data-bl-active" ) ) {
tempMcqBLActives = JSON . parse ( $ ( self ) . attr ( "data-bl-active" ) ) ;
}
}
function selectAlreadyMcqiAnswered ( self ) {
tempMcqiAns = $ ( self ) . attr ( "data-val" ) ;
tempMcqiAnsValue = $ ( self ) . attr ( "data-answer-value" ) ;
if ( $ ( self ) . attr ( "data-bl-active" ) ) {
tempMcqiBLActives = JSON . parse ( $ ( self ) . attr ( "data-bl-active" ) ) ;
}
}
$ ( ".slider" ) . on ( "input change" , function ( ) {
if ( ! $ ( this ) . hasClass ( "active" ) ) $ ( this ) . addClass ( "active" ) ;
} ) ;
async function addToCart ( ) {
if ( ! $ ( ".lds-ring" ) . hasClass ( "active" ) ) $ ( ".lds-ring" ) . addClass ( "active" ) ;
let existingProducts = [ ] ,
lineItems = [ ] ,
cart ;
const response = await fetch ( url _preset + "/v1/api/get-shopify-products" ) ;
const data = await response . json ( ) ;
if ( response . ok && data ) {
const products = data . products ;
existingProducts = products . filter ( ( product ) => {
2025-07-24 22:56:01 +01:00
let inFinalList = finalActives . find (
( active ) => active [ 0 ] == product . title
) ;
2022-04-12 08:57:07 -04:00
if ( inFinalList ) {
product . score = inFinalList [ 1 ] ;
return product ;
}
} ) ;
}
existingProducts . forEach ( ( prod ) => {
lineItems . push ( {
id : prod . variants [ 0 ] . id ,
quantity : 1 ,
2025-07-24 22:56:01 +01:00
properties : {
score : prod . score ? parseFloat ( prod . score ) . toFixed ( 2 ) : - 1 ,
} ,
2022-04-12 08:57:07 -04:00
} ) ;
// }
} ) ;
console . log ( lineItems ) ;
cart = {
items : lineItems ,
attributes : {
answers : JSON . stringify (
dataToReturn . map ( ( item ) => {
item . question = { id : item . question . id } ;
return item ;
} )
) ,
profile : JSON . stringify ( profile _characteristics ) ,
actives : JSON . stringify ( finalActives . map ( ( active ) => active [ 0 ] ) ) ,
} ,
} ;
await fetch ( "/cart/clear" ) . then ( ( res ) => {
res . ok ? console . log ( "cart cleared" ) : "Something went wrong" ;
} ) ;
const cartResponse = await fetch ( "/cart/add.js" , {
method : "POST" ,
headers : {
"Content-Type" : "application/json" ,
} ,
body : JSON . stringify ( cart ) ,
} ) ;
const cartData = await cartResponse . json ( ) ;
console . log ( cartResponse ) ;
console . log ( cartData ) ;
$ ( ".lds-ring" ) . removeClass ( "active" ) ;
if ( cartResponse . ok ) {
window . location . href = "/cart" ;
}
}
function handleNoneOfTheAbove ( ) {
isSkipStoreAnswer = true ;
nextQuestion ( ) ;
}
function handleImageMissing ( self ) {
$ ( self ) . addClass ( "image-missing" ) ;
}
2025-07-24 22:56:01 +01:00
// 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 ( ) ;
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 ) ;
}
// 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 ( ) {
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 ( ) ;
}
} ) ;
// 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 ( ) ;
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 ;
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" ;
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 ( ) ;
}
// 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 ;
}
}
if ( found ) {
askQuestion ( allItems [ currentQuizIndex ] . questions , currentQuestionCounter ) ;
}
} ) ;
// Update nav bar on question change
let origAskQuestion = askQuestion ;
askQuestion = async function ( ... args ) {
let 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 ( ) ;
}