{"version":3,"file":"main.js","sources":["../../src/js/main.js"],"sourcesContent":["// Quiz Module\nlet QuizModule = (function ($) {\n let selectors = {\n steps: '.step',\n prevStepBtn: '.prev-step',\n nextStepBtn: '.next-step',\n closeStepBtn: '.step-buttons-close',\n stepCounter: '.step-counter',\n quizSubheader: '.quiz-header p',\n quizOverlay: '#quiz-overlay',\n openQuiz: '#open-quiz',\n closeQuiz: '#close-quiz',\n selectedIconsDisplay: '#selected-icons-display',\n filterButtons: '.category-filter-button',\n hiddenFieldSymptombild: `textarea[name=\"${getHiddenFieldName(\n 'symptombild'\n )}\"]`,\n hiddenFieldSelectedSymptoms: `textarea[name=\"${getHiddenFieldName(\n 'selectedSymptoms'\n )}\"]`,\n };\n\n let elements = {};\n\n let constants = {\n MODAL_SUBHEADER: {\n 1: 'Svara på frågorna nedan för att ge oss en grundförståelse på vem du är.',\n 6: 'Klicka i de symptom du har besvär med.',\n 8: 'Antagen symptombild.',\n },\n MAX_ICON_SELECTION: 20,\n CONTRACEPTIVE_USE_CLAUSES_TEXT:\n 'I de första stegen svarade du att du idag använder preventivmedel av något slag. Preventivmedel påverkar vår kropp på olika sätt, vilket kan leda till att man upplever mer eller mindre av vissa symptom.',\n HAS_FAMILY_HISTORY_CLAUSES_TEXT:\n 'I de första stegen svarade du att du eller någon i din närmsta familj (mamma, pappa, syskon) har någon sjukdomshistoria av blodpropp, diabetes, hjärt- och kärlsjukdom, koagulationsrubbning och/eller bröstcancer innan du/dom var 50 år. Detta kan påverka din symptombild vilket innebär att du bör råda med sjukvård innan du vidtar andra åtgärder eller rekommendationer.',\n IMAGE_IDS: {\n VULVACANCER: 1162,\n LIVMODERCANCER: 1158,\n NO_MATCHING_RESULT: 1235,\n },\n STEP_NAMES: {\n AGE: 'age',\n AGE_GROUP: 'ageGroup',\n CONTRACEPTIVE_USE: 'contraceptiveUse',\n FAMILY_HISTORY: 'familyHistory',\n OTHER_ILLNESSES: 'otherIllnesses',\n SYMPTOMS_SELECTION: 'symptomsSelection',\n CONTROL_QUESTIONS: 'controlQuestions',\n RESULT: 'result',\n },\n STEP_INDEX_TO_NAME: {\n 0: 'age',\n 1: 'ageGroup',\n 2: 'contraceptiveUse',\n 3: 'familyHistory',\n 4: 'otherIllnesses',\n 5: 'symptomsSelection',\n 6: 'controlQuestions',\n 7: 'result',\n },\n };\n\n let quizState = {\n currentStepIndex: 0,\n responseData: null,\n wentThroughControlQuestions: false,\n displayedTotalStep: 0,\n selectedCategory: 'all',\n };\n\n let formValues = {\n hasFamilyMedicalHistory: false,\n contraceptiveUse: false,\n contraceptiveUseInput: false,\n otherIllnesses: false,\n otherIllnessesInput: null,\n selectedAgeGroup: 'tonaring',\n userAge: null,\n selectedIcons: [],\n controlQuestionAnswers: {},\n };\n\n const QuizNavigation = {\n moveToNextStep: async function () {\n const currentStepName =\n constants.STEP_INDEX_TO_NAME[quizState.currentStepIndex];\n\n if (\n currentStepName === constants.STEP_NAMES.SYMPTOMS_SELECTION &&\n elements.selectedIconsDisplay.find('.selected-icon').length === 0\n ) {\n alert('Please select at least one icon.');\n return;\n }\n\n if (currentStepName === constants.STEP_NAMES.SYMPTOMS_SELECTION) {\n let selectedSymptoms = $('#selected-icons-display .selected-icon')\n .map(function () {\n return $(this).data('id');\n })\n .get();\n\n try {\n await fetchMatchingImages(selectedSymptoms);\n } catch (error) {\n console.error('Fetching images failed: ', error);\n return;\n }\n }\n\n if (currentStepName === constants.STEP_NAMES.CONTROL_QUESTIONS) {\n hideImagesBasedOnControlQuestionsAndAmountOfSelectedIcons();\n populateHiddenFields();\n }\n\n if (quizState.currentStepIndex < constants.TOTAL_STEPS - 1) {\n quizState.currentStepIndex++;\n // scrollToTopOfQuiz();\n updateQuizUI();\n }\n },\n moveToPreviousStep: function () {\n const currentStepName =\n constants.STEP_INDEX_TO_NAME[quizState.currentStepIndex];\n if (currentStepName === constants.STEP_NAMES.CONTROL_QUESTIONS) {\n quizState.displayedTotalStep = 7;\n }\n if (\n !quizState.wentThroughControlQuestions &&\n quizState.currentStepIndex === constants.TOTAL_STEPS - 1\n ) {\n quizState.currentStepIndex -= 2;\n } else {\n quizState.currentStepIndex--;\n }\n // scrollToTopOfQuiz();\n updateQuizUI();\n },\n };\n\n function initSelectors() {\n $.each(selectors, function (key, selector) {\n elements[key] = $(selector);\n });\n\n constants.TOTAL_STEPS = elements.steps.length;\n quizState.displayedTotalStep = constants.TOTAL_STEPS - 1;\n }\n\n function bindEventHandlers() {\n elements.openQuiz.on('click', function (e) {\n handleOpenQuizModal(e);\n });\n\n elements.closeQuiz.on('click', function (e) {\n handleCloseQuizModal(e);\n });\n\n elements.closeStepBtn.on('click', function (e) {\n handleCloseQuizModal(e);\n });\n\n elements.nextStepBtn.on('click', function (e) {\n handleNextStepClick(e);\n });\n\n elements.prevStepBtn.on('click', function (e) {\n handlePrevStepClick(e);\n });\n\n $('#multistep-form')\n .on('change', 'input[name=\"ageGroupSelection\"]', function () {\n updateFormValue('selectedAgeGroup', $(this).val());\n })\n .on('change', 'input[name=\"familyMedicalHistory\"]', function () {\n updateFormValue('hasFamilyMedicalHistory', $(this).val() === 'ja');\n })\n .on('change', 'input[name=\"contraceptiveUse\"]', function () {\n updateFormValue('contraceptiveUse', $(this).val() === 'ja');\n $('#contraceptiveUse-input').toggle($(this).val() === 'ja');\n })\n .on('change', 'input[name=\"otherIllnesses\"]', function () {\n updateFormValue('otherIllnesses', $(this).val() === 'ja');\n $('#otherIllnesses-input').toggle($(this).val() === 'ja');\n })\n .on('input', 'input[name=\"userAge\"]', function () {\n updateFormValue('userAge', $(this).val());\n });\n\n // Input events for detailed inputs\n $('#contraceptiveUse-input').on('input', 'input', function () {\n updateFormValue('contraceptiveUseInput', $(this).val());\n });\n\n $('#otherIllnesses-input').on('input', 'input', function () {\n updateFormValue('otherIllnessesInput', $(this).val());\n });\n\n // Click events for quiz icon selection and category filters\n $('#symptoms-grid').on('click', '.quiz-icon', function (e) {\n handleIconGridClick(e, $(this));\n });\n\n $('#category-filter-buttons').on(\n 'click',\n '.category-filter-button',\n function (event) {\n handleFilterButtonClick.call(this, event);\n }\n );\n\n // Click event for selected icons\n elements.selectedIconsDisplay.on('click', '.selected-icon', (e) =>\n handleSelectedIconClick(e)\n );\n }\n\n function configureFormEvents(elements) {\n jQuery(document).on('gform_confirmation_loaded', function (event, formId) {\n if (formId === 3) {\n elements.prevStepBtn.hide();\n elements.nextStepBtn.hide();\n elements.closeStepBtn.show();\n }\n });\n }\n\n function updateFormValue(key, value) {\n formValues[key] = value;\n }\n\n function getHiddenFieldName(fieldKey) {\n const isLocalEnvironment = window.location.hostname.includes('localhost');\n const fieldNames = {\n symptombild: isLocalEnvironment ? 'input_5' : 'input_4',\n selectedSymptoms: isLocalEnvironment ? 'input_7' : 'input_6',\n };\n\n const fieldName = fieldNames[fieldKey];\n if (!fieldName)\n throw new Error(`Field name for key \"${fieldKey}\" not found.`);\n return fieldName;\n }\n\n function handleOpenQuizModal(e) {\n e.preventDefault();\n elements.quizOverlay.addClass('open');\n $('body').css('overflow', 'hidden');\n resetQuiz();\n }\n\n function handleCloseQuizModal(e) {\n e.preventDefault();\n elements.quizOverlay.removeClass('open');\n $('body').css('overflow', 'auto');\n }\n\n function handleNextStepClick(e) {\n e.preventDefault();\n\n if (quizState.currentStepIndex < constants.TOTAL_STEPS - 1) {\n QuizNavigation.moveToNextStep();\n } else {\n checkAndScrollToFirstEmptyInput();\n $('#gform_submit_button_3').click();\n }\n }\n\n function handlePrevStepClick(e) {\n e.preventDefault();\n QuizNavigation.moveToPreviousStep();\n }\n\n function handleSelectedIconClick(event) {\n event.preventDefault();\n let iconId = $(event.currentTarget).data('id');\n removeIcon(iconId);\n $(event.currentTarget).removeClass('selected');\n updateSelectedIconsDisplay();\n }\n\n function handleIconGridClick(event, target) {\n let iconId = target.data('id');\n let iconName = target.data('name');\n let iconThumbnail = target.find('img').attr('src');\n\n if (formValues.selectedIcons.some((icon) => icon.id === iconId)) {\n removeIcon(iconId);\n target.removeClass('selected');\n } else if (formValues.selectedIcons.length < constants.MAX_ICON_SELECTION) {\n addIcon(iconId, iconName, iconThumbnail);\n target.addClass('selected');\n }\n }\n\n function handleFilterButtonClick(event) {\n event.preventDefault();\n\n const selectedCategory = $(this).data('category');\n\n elements.filterButtons.removeClass('active');\n $(this).addClass('active');\n\n quizState.selectedCategory = selectedCategory;\n applyCategoryFilters(selectedCategory);\n }\n\n function resetQuiz() {\n // Resetting quiz state to initial values\n quizState.currentStepIndex = 0;\n quizState.responseData = null;\n quizState.wentThroughControlQuestions = false;\n quizState.displayedTotalStep = elements.steps.length - 1;\n quizState.selectedCategory = 'all';\n\n // Resetting form values to their default\n formValues.hasFamilyMedicalHistory = false;\n formValues.contraceptiveUse = false;\n formValues.contraceptiveUseInput = false;\n formValues.otherIllnesses = false;\n formValues.otherIllnessesInput = null;\n formValues.selectedAgeGroup = 'tonaring';\n formValues.userAge = null;\n formValues.selectedIcons = [];\n formValues.controlQuestionAnswers = {};\n\n // Additional UI updates\n $(\n 'input[type=\"text\"], input[type=\"email\"], input[type=\"number\"], textarea'\n ).val('');\n $('input[type=\"checkbox\"]').prop('checked', false);\n\n // Reset all radio buttons to unchecked first\n $('input[type=\"radio\"]').prop('checked', false);\n\n // Then, set the first radio button in each group to be checked\n $('input[type=\"radio\"]').each(function () {\n let name = $(this).attr('name');\n $(`input[name=\"${name}\"]:first`).prop('checked', true);\n });\n\n // Hide the extra inputs\n $('#otherIllnesses-input').hide();\n $('#contraceptiveUse-input').hide();\n\n // Reset the flags associated with these inputs\n $('input[name=\"contraceptiveUse\"][value=\"nej\"]').prop('checked', true);\n $('input[name=\"otherIllnesses\"][value=\"nej\"]').prop('checked', true);\n\n // Reset specific UI elements that were dynamically updated during the quiz\n elements.selectedIconsDisplay.empty();\n\n // Reset selected icons visual state\n $('#symptoms-grid .quiz-icon').removeClass('selected');\n\n // Update category filter buttons UI\n elements.filterButtons.removeClass('active');\n elements.filterButtons.filter('[data-category=\"all\"]').addClass('active');\n\n // Apply 'all' category filter\n applyCategoryFilters('all');\n\n updateQuizUI();\n }\n\n function updateQuizUI() {\n $('.scrollable-content').scrollTop(0);\n\n // Show/hide steps based on the currentStepIndex\n elements.steps.hide();\n elements.steps.eq(quizState.currentStepIndex).show();\n\n // Update step counter UI\n const totalStepsIncludingControl = quizState.wentThroughControlQuestions\n ? constants.TOTAL_STEPS\n : constants.TOTAL_STEPS - 1;\n quizState.displayedTotalStep = totalStepsIncludingControl;\n\n // Adjust the displayed step index\n let displayedStepIndex = quizState.currentStepIndex + 1;\n displayedStepIndex = Math.min(\n displayedStepIndex,\n quizState.displayedTotalStep\n );\n\n if (elements.stepCounter) {\n elements.stepCounter.text(\n `${displayedStepIndex} / ${quizState.displayedTotalStep}`\n );\n }\n\n const currentStepName =\n constants.STEP_INDEX_TO_NAME[quizState.currentStepIndex];\n\n if (currentStepName === constants.STEP_NAMES.SYMPTOMS_SELECTION) {\n applyCategoryFilters(quizState.selectedCategory);\n }\n\n if (\n currentStepName === constants.STEP_NAMES.SYMPTOMS_SELECTION ||\n currentStepName === constants.STEP_NAMES.RESULT\n ) {\n elements.quizOverlay.find('.quiz-inner').addClass('quiz-modal-expanded');\n } else {\n elements.quizOverlay\n .find('.quiz-inner')\n .removeClass('quiz-modal-expanded');\n }\n\n // Update modal subheader based on the current step, if applicable\n if (\n elements.quizSubheader &&\n constants.MODAL_SUBHEADER[quizState.currentStepIndex + 1]\n ) {\n elements.quizSubheader.text(\n constants.MODAL_SUBHEADER[quizState.currentStepIndex + 1]\n );\n }\n\n // Update navigation buttons\n elements.prevStepBtn.toggle(quizState.currentStepIndex > 0);\n elements.nextStepBtn.text(\n quizState.currentStepIndex === constants.TOTAL_STEPS - 1\n ? 'Skicka'\n : 'Nästa'\n );\n }\n\n function prepareControlQuestions() {\n let uniqueControlQuestions = getUniqueControlQuestions(\n quizState.responseData\n );\n\n let controlQuestionHtml = uniqueControlQuestions\n .map((question, index) => createControlQuestionHtml(question, index))\n .join('');\n\n $('#control-question-step .control-question-content').html(\n controlQuestionHtml\n );\n\n attachControlQuestionListeners(uniqueControlQuestions);\n\n $('#control-question-step').show();\n\n createHtmlForMatchingImages();\n }\n\n function createControlQuestionHtml(question, index) {\n if (!question.question) return '';\n\n const yesNoInputs = createYesNoInputs(index);\n const extraFeedback = question.extraFeedback\n ? createControlQuestionFeedback(question)\n : '';\n\n return `\n