From b0447586c51e8960b142bf7664dde8f1f3aff3ca Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Thu, 6 Oct 2022 15:12:03 -0400 Subject: [PATCH 01/53] CSR-803: remove obsolete code --- src/layouts/capability-questions/capability-questions.vue | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue index 39b96c361..2c132af9b 100644 --- a/src/layouts/capability-questions/capability-questions.vue +++ b/src/layouts/capability-questions/capability-questions.vue @@ -85,12 +85,6 @@ export default { AlertFewMoreQuestionsCopy() { return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText"); }, - windshieldPart() { - return this.pageData.partsOrQuestions.find(x => x.glassLocation === damageLocationsSelected.WINDSHIELD); - }, - windshieldPartInfo() { - return this.windshieldPart.parts[0]; - }, pageData() { return this.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS); } From e604bdb8e10b669e08357ff44c629a5a36c70643 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 7 Oct 2022 16:04:43 -0400 Subject: [PATCH 02/53] CSR-803: move handleAnswerUpdates to shared mixin --- .../capability-questions.vue | 277 +----------------- .../molding-questions/molding-questions.vue | 268 +---------------- src/layouts/part-questions/part-questions.vue | 270 +---------------- src/mixins/vehicle-questions-mixin.js | 257 ++++++++++++++++ 4 files changed, 279 insertions(+), 793 deletions(-) diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue index 2c132af9b..f9a15a6e8 100644 --- a/src/layouts/capability-questions/capability-questions.vue +++ b/src/layouts/capability-questions/capability-questions.vue @@ -9,7 +9,7 @@ -
+
x.capabilityQuestions).map((glass, i) => { + this.questionsData = this.pageData.partsOrQuestions.filter(x => x.capabilityQuestions).map((glass, i) => { // NOTE: questions for property "questions" can differ between layouts glass.questions = glass.capabilityQuestions; // reset selectedAnswers for this glass @@ -103,16 +101,16 @@ export default { }); }, methods: { - showThisQuestionChain(glass, i) { - if (!glass.capabilityQuestions || glass.capabilityQuestions?.length < 1 || glass.isSuppressedPart) { return false; } // return false if no capabilityQuestions or if suppressed - return this.currentQuestionChainIndex === i || glass.answerData?.answerResult?.length > 0; - }, arePagePrerequisitesValid() { const capabilityQuestionsPageData = store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS); return capabilityQuestionsPageData && Object.keys(capabilityQuestionsPageData).length > 0; }, + showThisQuestionChain(glass, i) { + if (!glass.capabilityQuestions || glass.capabilityQuestions?.length < 1 || glass.isSuppressedPart) { return false; } // return false if no capabilityQuestions or if suppressed + return this.currentQuestionChainIndex === i || glass.answerData?.answerResult?.length > 0; + }, async forwardButtonAction() { - const capabilityQuestionsAnswersArray = this.capabilityQuestionsData.map((glass) => { + const capabilityQuestionsAnswersArray = this.questionsData.map((glass) => { const selectedAnswerResult2 = this.getCorrespondingAnswerResult2(glass.answerData.answerResult); return { @@ -127,7 +125,7 @@ export default { }); // clear out answerData for future page loads; must occur prior to store save - this.capabilityQuestionsData.forEach((glass) => { + this.questionsData.forEach((glass) => { glass.answerData = {}; }); @@ -138,270 +136,17 @@ export default { let partsOrQuestions = this.pageData.partsOrQuestions; for (let answer of capabilityQuestionsAnswersArray) { const correspondingPart = partsOrQuestions.find(partOrQuestion => partOrQuestion.glassLocation === answer.glassLocation); - const partFromCapabilityQuestionAnswer = (await this.dispatchStoreAction(storeActions.GET_PART_FROM_CAPABILITY_QUESTION_ANSWER, answer.glassLocation, false)).data; + const partFromCapabilityQuestionAnswer = (await this.dispatchStoreAction(this.storeActions.GET_PART_FROM_CAPABILITY_QUESTION_ANSWER, answer.glassLocation, false)).data; partsOrQuestions.find(partOrQuestion => partOrQuestion.glassLocation === answer.glassLocation).parts = partFromCapabilityQuestionAnswer; } this.navigateForward(partsOrQuestions); }, - handleAnswerUpdates(answer) { - // only runs when all questions in a question-chain have been answered - // when selectedAnswers updates, user has completed this part's question chain and has a final answer - // (does not get run for each invididual question's answer, only when - // all relevant questions for the current part have been answered) - - /* - answer example format: - { - "answerResult": "DD11132", - "answeredQuestions": [ - { - "questionText": "Is your Grand Cherokee the Laredo model?", - "selectedAnswerText": "Yes", - "questionNum": 1, - } - ], - "glassIndex": 0 - } - */ - - // collect a list of the answered questions' numbers, needed later below - const answeredQuestionIndexes = []; - const foundDuplicateQuestions = []; - - // if user has answered a question differently than anything that was preloaded, - // we need to clear out any preloaded answers - this.selectedAnswers = {}; - - // loop through every answered question on the currently answered glass part - answer.answeredQuestions?.forEach((aq) => { - - // keep track of this question number - answeredQuestionIndexes.push(aq.questionNum); - - const answeredQuestionText = aq.questionText.toUpperCase(); - const answeredQuestionAnswer = aq.selectedAnswerText.toUpperCase(); - - // HANDLE DUPLICATE QUESTIONS - - // loop through all glass parts data - this.capabilityQuestionsData.forEach((glass, gpIndex) => { - - // only look for duplicates forward... to parts that follow after the currently being answered part - if (gpIndex > answer.glass) { - - let suppressUntil; - // reset this glass part, in case user is changing their previous answers - glass.answerData = null; - glass.isSuppressedPart = null; - - // loop through this glass part's part questions, looking for a questionText match - glass.capabilityQuestions.forEach((pq, pqIndex) => { - - // clear out any previously set answers - pq.answerSelected = null; - - // clear or set suppressQuestion property for each question - if (suppressUntil) { - // if suppressUntil has been set, then suppress this question if before it - if (pqIndex + 1 < suppressUntil) { - pq.suppressQuestion = true; - } else { - pq.suppressQuestion = null; - } - } else { - pq.suppressQuestion = null; - } - - // if these match then we have a duplicate question - if (pq.questionText.toUpperCase() === answeredQuestionText) { - - const thisAnsweredCapabilityQuestion = glass.capabilityQuestions[pqIndex]; - let matchedAnswer; - let rejectedAnswers = []; // set as an array, in case we ever have questions with more than 2 answers... - - // which one of this capabilityQuestions' answers matches our answer? - pq.answers.forEach((ans) => { - if (ans.answerText.toUpperCase() === answeredQuestionAnswer) { - matchedAnswer = ans; - ans.selected = true; - } else { - rejectedAnswers.push(ans); - ans.selected = null; - } - }); - - // Update the key to re-render this part's question-chain component - this.capabilityQuestionsData[gpIndex].key = this.capabilityQuestionsData[gpIndex].glassLocation + this.capabilityQuestionsData[gpIndex].glassName + Date.now().toString(); - - // handle suppressing downstream in this question chain - - if (matchedAnswer.nextQuestionSequence) { - // ensure that the question that the accepted answer has set to be next is NOT suppressed - glass.capabilityQuestions[matchedAnswer.nextQuestionSequence - 1].suppressQuestion = null; - // if the duplicate is the 1ST question, then set suppressUntil var to lowest nextQuestion number - if (pqIndex === 0) { - if (!suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence } - if (matchedAnswer.nextQuestionSequence < suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence } - } - } - - // handle suppressing upstream in this question chain - glass.capabilityQuestions.forEach((q) => { - q.answers.forEach((thisAns) => { - // restore any of the answers that formerly led to the duplicated question - if (thisAns.originalNextQuestionSequence === pq.questionSequence) { - // restore original nextQuestionSequence - thisAns.nextQuestionSequence = thisAns.originalNextQuestionSequence; - this.originalNextQuestionSequence = null; - // restore original answerResult - if (thisAns.originalAnswerResult) { - thisAns.answerResult = thisAns.originalAnswerResult; - thisAns.originalAnswerResult = null; - } - } - // search for any answers that lead to the duplicated question - if (thisAns.nextQuestionSequence === pq.questionSequence) { - // update either the nextQuestionSequence or the answerResult - if (matchedAnswer.nextQuestionSequence) { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = matchedAnswer.nextQuestionSequence; - } else { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = null; - thisAns.originalAnswerResult = thisAns.originalAnswerResult || thisAns.answerResult; - thisAns.answerResult = matchedAnswer.answerResult; - } - } - }); - }); - - // suppress current question - thisAnsweredCapabilityQuestion.suppressQuestion = true; - - const thisGlassPart = "glass" + gpIndex; - if (foundDuplicateQuestions[thisGlassPart]) { - if (!foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredCapabilityQuestion.questionSequence)) { - foundDuplicateQuestions[thisGlassPart].push(thisAnsweredCapabilityQuestion.questionSequence); - } - } else { - foundDuplicateQuestions[thisGlassPart] = [thisAnsweredCapabilityQuestion.questionSequence]; - } - - // are there any questions left that are not suppressed? - const remainingQuestions = glass.capabilityQuestions.filter((q) => { - return !q.suppressQuestion; - }); - - if (remainingQuestions.length < 1) { - // this is the final answer for this glass part - - // mark this part as completely answered by adding answerData - const answeredQuestionObj = { - questionText: pq.questionText, - selectedAnswerText: matchedAnswer.answerText, - questionNum: pq.questionSequence, - suppressQuestion: pq.suppressQuestion, - }; - // set the answerData as 'already answered' - glass.answerData = { - answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult, - answeredQuestions: [answeredQuestionObj], - }; - - // suppress this glass because it has an answer - glass.isSuppressedPart = true; - } - - } - - }); - - // Update the key to re-render this part's question-chain component - this.capabilityQuestionsData[gpIndex].key = this.capabilityQuestionsData[gpIndex].glassLocation + this.capabilityQuestionsData[gpIndex].glassName + Date.now().toString(); - - } - }); - }); - - // DETERMINE ANSWERED QUESTIONS LIST FOR THIS GLASS PART - - // look through all (this part's) part questions for any duplicates that were suppressed; - // add them to the list of answered questions if found - - // EX answeredQuestionIndexes: [1,5,11,13] - - // EX foundDuplicateQuestions = { - // "glassPart1": [1], - // "glassPart2": [7, 10] - // }; - - const thisPartsDupes = foundDuplicateQuestions["glass" + answer.glassIndex]; - const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : []; - const glassPartAnswered = this.capabilityQuestionsData[answer.glassIndex]; - - thisPartsDupes?.forEach((dupe) => { - // dupe is a single integer - const dupeQuestion = glassPartAnswered.capabilityQuestions[dupe - 1]; - const dupeQuestionAnswer = dupeQuestion.answers.find((q) => q.selected === true); - - glassPartAnswered.capabilityQuestions.forEach((q) => { - let includeThisDupeInAnsweredQuestions = false; - - // did one of the answers of this question point to the duplicated question? - q.answers.forEach((a) => { - if ((dupe === a.originalNextQuestionSequence) && - (answeredQuestionIndexes.includes(q.questionSequence)) && - (a.answerText.toUpperCase() === dupeQuestionAnswer.answerText.toUpperCase())) { - includeThisDupeInAnsweredQuestions = true; - } - }); - - // is this q.questionSequence listed as the duplicated question's nextQuestionSequence? - if ((q.questionSequence === dupeQuestionAnswer.nextQuestionSequence) && (answeredQuestionIndexes.includes(q.questionSequence))) { - includeThisDupeInAnsweredQuestions = true; - } - - if (includeThisDupeInAnsweredQuestions) { - completeAnsweredQuestions.push({ - questionNum: dupeQuestion.questionSequence, - questionText: dupeQuestion.questionText, - selectedAnswerText: dupeQuestionAnswer.answerText, - suppressQuestion: dupeQuestion.suppressQuestion, - }); - } - }); - }); - - // make sure there are no duplicated dupes in the list... - const foundInCompleteAnsweredQuestions = new Set(); - let filteredCompleteAnsweredQuestions = completeAnsweredQuestions.filter(el => { - const duplicate = foundInCompleteAnsweredQuestions.has(el.questionText); - foundInCompleteAnsweredQuestions.add(el.questionText); - return !duplicate; - }); - filteredCompleteAnsweredQuestions = filteredCompleteAnsweredQuestions.sort((a, b) => a.questionNum - b.questionNum); - - // set final answer data for the current answered glass part - glassPartAnswered.answerData = { - answerResult: answer.answerResult, - answeredQuestions: filteredCompleteAnsweredQuestions, - } - - // this part has been fully answered, so advance to next part's question chain - for (let i = answer.glassIndex + 1; i < this.capabilityQuestionsData.length; i++) { - // if this part has not yet been fully answered, then make it the current part - if (!this.capabilityQuestionsData[i].answerData?.answerResult) { - this.currentQuestionChainIndex = i; - break; - } - } - }, // TODO I'm sure there's a better/simplier way to do this that I'm missing but my brain's fried // Find the part that has some answer that has an answerResult matching the selected answerResult, then get the corresponding answerResult2 getCorrespondingAnswerResult2(answerResult1) { - return this.capabilityQuestionsData + return this.questionsData .find(part => part.capabilityQuestions.some(question => question.answers.some(answer => answer.answerResult == answerResult1))) // found part .capabilityQuestions.find(question => question.answers.some(answer => answer.answerResult == answerResult1)) // found question .answers.find(answer => answer.answerResult == answerResult1) diff --git a/src/layouts/molding-questions/molding-questions.vue b/src/layouts/molding-questions/molding-questions.vue index 50cfe42c2..b60e4dd5f 100644 --- a/src/layouts/molding-questions/molding-questions.vue +++ b/src/layouts/molding-questions/molding-questions.vue @@ -20,7 +20,7 @@ :manualCopy="AlertFewMoreQuestionsCopy" v-bind:isDismissible="false" /> -
+
x.parts[0].childPartQuestions.length).map((glass, i) => { + this.questionsData = this.pageData.partsOrQuestions.filter(x => x.parts[0].childPartQuestions.length).map((glass, i) => { // NOTE: questions for property "questions" can differ between layouts glass.questions = glass.parts[0].childPartQuestions; // reset selectedAnswers for this glass @@ -130,7 +128,7 @@ export default { return this.currentGlassIndex === i || glass.answerData?.answerResult?.length > 0; }, async forwardButtonAction() { - const questionAnswersArray = this.moldingQuestionsData.map((glass) => { + const questionAnswersArray = this.questionsData.map((glass) => { return { glassLocation: glass.glassLocation, glassName: glass.glassName, @@ -141,7 +139,7 @@ export default { }); // clear out answerData for future page loads; must occur prior to store save - this.moldingQuestionsData.forEach((glass) => { + this.questionsData.forEach((glass) => { glass.answerData = {}; }); @@ -162,262 +160,6 @@ export default { this.navigateForward(partsOrQuestions); }, - handleAnswerUpdates(answer) { - // only runs when all questions in a question-chain have been answered - // when selectedAnswers updates, user has completed this part's question chain and has a final answer - // (does not get run for each invididual question's answer, only when - // all relevant questions for the current part have been answered) - - /* - answer example format: - { - "answerResult": "DD11132", - "answeredQuestions": [ - { - "questionText": "Is your Grand Cherokee the Laredo model?", - "selectedAnswerText": "Yes", - "questionNum": 1, - } - ], - "glassIndex": 0 - } - */ - - // collect a list of the answered questions' numbers, needed later below - const answeredQuestionIndexes = []; - const foundDuplicateQuestions = []; - - // if user has answered a question differently than anything that was preloaded, - // we need to clear out any preloaded answers - this.selectedAnswers = {}; - - // loop through every answered question on the currently answered glass part - answer.answeredQuestions?.forEach((aq) => { - - // keep track of this question number - answeredQuestionIndexes.push(aq.questionNum); - - const answeredQuestionText = aq.questionText.toUpperCase(); - const answeredQuestionAnswer = aq.selectedAnswerText.toUpperCase(); - - // HANDLE DUPLICATE QUESTIONS - - // loop through all glass parts data - this.moldingQuestionsData.forEach((glass, gpIndex) => { - - // only look for duplicates forward... to parts that follow after the currently being answered part - if (gpIndex > answer.glassIndex) { - - let suppressUntil; - // reset this glass part, in case user is changing their previous answers - glass.answerData = null; - glass.isSuppressedPart = null; - - // loop through this glass part's part questions, looking for a questionText match - glass.questions.forEach((pq, pqIndex) => { - - // clear out any previously set answers - pq.answerSelected = null; - - // clear or set suppressQuestion property for each question - if (suppressUntil) { - // if suppressUntil has been set, then suppress this question if before it - if (pqIndex + 1 < suppressUntil) { - pq.suppressQuestion = true; - } else { - pq.suppressQuestion = null; - } - } else { - pq.suppressQuestion = null; - } - - // if these match then we have a duplicate question - if (pq.questionText.toUpperCase() === answeredQuestionText) { - - const thisAnsweredPartQuestion = glass.questions[pqIndex]; - let matchedAnswer; - let rejectedAnswers = []; // set as an array, in case we ever have questions with more than 2 answers... - - // which one of this questions' answers matches our answer? - pq.answers.forEach((ans) => { - if (ans.answerText.toUpperCase() === answeredQuestionAnswer) { - matchedAnswer = ans; - ans.selected = true; - } else { - rejectedAnswers.push(ans); - ans.selected = null; - } - }); - - // Update the key to re-render this part's question-chain component - this.moldingQuestionsData[gpIndex].key = this.moldingQuestionsData[gpIndex].glassLocation + this.moldingQuestionsData[gpIndex].glassName + Date.now().toString(); - - // handle suppressing downstream in this question chain - - if (matchedAnswer.nextQuestionSequence) { - // ensure that the question that the accepted answer has set to be next is NOT suppressed - glass.questions[matchedAnswer.nextQuestionSequence - 1].suppressQuestion = null; - // if the duplicate is the 1ST question, then set suppressUntil var to lowest nextQuestion number - if (pqIndex === 0) { - if (!suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence } - if (matchedAnswer.nextQuestionSequence < suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence} - } - } - - // handle suppressing upstream in this question chain - glass.questions.forEach((q) => { - q.answers.forEach((thisAns) => { - // restore any of the answers that formerly led to the duplicated question - if (thisAns.originalNextQuestionSequence === pq.questionSequence) { - // restore original nextQuestionSequence - thisAns.nextQuestionSequence = thisAns.originalNextQuestionSequence; - this.originalNextQuestionSequence = null; - // restore original answerResult - if (thisAns.originalAnswerResult) { - thisAns.answerResult = thisAns.originalAnswerResult; - thisAns.originalAnswerResult = null; - } - } - // search for any answers that lead to the duplicated question - if (thisAns.nextQuestionSequence === pq.questionSequence) { - // update either the nextQuestionSequence or the answerResult - if (matchedAnswer.nextQuestionSequence) { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = matchedAnswer.nextQuestionSequence; - } else { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = null; - thisAns.originalAnswerResult = thisAns.originalAnswerResult || thisAns.answerResult; - thisAns.answerResult = matchedAnswer.answerResult; - } - } - }); - }); - - // suppress current question - thisAnsweredPartQuestion.suppressQuestion = true; - - const thisGlassPart = "glass" + gpIndex; - if (foundDuplicateQuestions[thisGlassPart]) { - if (!foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredPartQuestion.questionSequence)) { - foundDuplicateQuestions[thisGlassPart].push(thisAnsweredPartQuestion.questionSequence); - } - } else { - foundDuplicateQuestions[thisGlassPart] = [thisAnsweredPartQuestion.questionSequence]; - } - - // are there any questions left that are not suppressed? - const remainingQuestions = glass.questions.filter((q) => { - return !q.suppressQuestion; - }); - - if (remainingQuestions.length < 1) { - // this is the final answer for this glass part - - // mark this part as completely answered by adding answerData - const answeredQuestionObj = { - questionText: pq.questionText, - selectedAnswerText: matchedAnswer.answerText, - questionNum: pq.questionSequence, - suppressQuestion: pq.suppressQuestion, - }; - // set the answerData as 'already answered' - glass.answerData = { - answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult, - answeredQuestions: [answeredQuestionObj], - }; - - // suppress this glass because it has an answer - glass.isSuppressedPart = true; - } - - } - - }); - - // Update the key to re-render this part's question-chain component - this.moldingQuestionsData[gpIndex].key = this.moldingQuestionsData[gpIndex].glassLocation + this.moldingQuestionsData[gpIndex].glassName + Date.now().toString(); - - } - - }); - - }); - - // DETERMINE ANSWERED QUESTIONS LIST FOR THIS GLASS PART - - // look through all (this part's) part questions for any duplicates that were suppressed; - // add them to the list of answered questions if found - - // EX answeredQuestionIndexes: [1,5,11,13] - - // EX foundDuplicateQuestions = { - // "glassPart1": [1], - // "glassPart2": [7, 10] - // }; - - const thisPartsDupes = foundDuplicateQuestions["glass" + answer.glassIndex]; - const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : []; - const glassPartAnswered = this.moldingQuestionsData[answer.glassIndex]; - - thisPartsDupes?.forEach((dupe) => { - // dupe is a single integer - const dupeQuestion = glassPartAnswered.questions[dupe - 1]; - const dupeQuestionAnswer = dupeQuestion.answers.find((q) => q.selected === true); - - glassPartAnswered.questions.forEach((q) => { - let includeThisDupeInAnsweredQuestions = false; - - // did one of the answers of this question point to the duplicated question? - q.answers.forEach((a) => { - if ((dupe === a.originalNextQuestionSequence) && - (answeredQuestionIndexes.includes(q.questionSequence)) && - (a.answerText.toUpperCase() === dupeQuestionAnswer.answerText.toUpperCase())) { - includeThisDupeInAnsweredQuestions = true; - } - }); - - // is this q.questionSequence listed as the duplicated question's nextQuestionSequence? - if ((q.questionSequence === dupeQuestionAnswer.nextQuestionSequence) && (answeredQuestionIndexes.includes(q.questionSequence))) { - includeThisDupeInAnsweredQuestions = true; - } - - if (includeThisDupeInAnsweredQuestions) { - completeAnsweredQuestions.push({ - questionNum: dupeQuestion.questionSequence, - questionText: dupeQuestion.questionText, - selectedAnswerText: dupeQuestionAnswer.answerText, - suppressQuestion: dupeQuestion.suppressQuestion, - }); - } - }); - }); - - // make sure there are no duplicated dupes in the list... - const foundInCompleteAnsweredQuestions = new Set(); - let filteredCompleteAnsweredQuestions = completeAnsweredQuestions.filter(el => { - const duplicate = foundInCompleteAnsweredQuestions.has(el.questionText); - foundInCompleteAnsweredQuestions.add(el.questionText); - return !duplicate; - }); - filteredCompleteAnsweredQuestions = filteredCompleteAnsweredQuestions.sort((a,b) => a.questionNum - b.questionNum); - - // set final answer data for the current answered glass part - glassPartAnswered.answerData = { - answerResult: answer.answerResult, - answeredQuestions: filteredCompleteAnsweredQuestions, - } - - // this part has been fully answered, so advance to next molding question chain - for (let i = answer.glassIndex + 1; i < this.moldingQuestionsData.length; i++) { - // if this part has not yet been fully answered, then make it the current part - if (!this.moldingQuestionsData[i].answerData?.answerResult) { - this.currentGlassIndex = i; - break; - } - } - - }, }, components: { funnelHeader, diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue index 131a70f44..d5e79540b 100644 --- a/src/layouts/part-questions/part-questions.vue +++ b/src/layouts/part-questions/part-questions.vue @@ -20,7 +20,7 @@ :manualCopy="AlertFewMoreQuestionsCopy" v-bind:isDismissible="false" /> -
+
x.partQuestions).map((glass, i) => { + this.questionsData = this.pageData.partsOrQuestions.filter(x => x.partQuestions).map((glass, i) => { // NOTE: questions for property "questions" can differ between layouts glass.questions = glass.partQuestions; // reset selectedAnswers for this glass @@ -130,7 +128,7 @@ export default { return this.currentGlassIndex === i || glass.answerData?.answerResult?.length > 0; }, async forwardButtonAction() { - const questionAnswersArray = this.partsQuestionsData.map((glass) => { + const questionAnswersArray = this.questionsData.map((glass) => { return { glassLocation: glass.glassLocation, glassName: glass.glassName, @@ -141,7 +139,7 @@ export default { }); // clear out answerData for future page loads; must occur prior to store save - this.partsQuestionsData.forEach((glass) => { + this.questionsData.forEach((glass) => { glass.answerData = {}; }); @@ -149,7 +147,7 @@ export default { await this.dispatchStoreAction(this.storeActions.SAVE_PART_QUESTION_ANSWERS, questionAnswersArray, false); // call API parts method - const partsLookup = await this.dispatchStoreAction(storeActions.GET_PARTS) + const partsLookup = await this.dispatchStoreAction(this.storeActions.GET_PARTS) .catch(() => { return this.$refs.funnelFooter.removeLoader(); }); @@ -158,262 +156,6 @@ export default { this.navigateForward(glassNameAndPartsForStore); }, - handleAnswerUpdates(answer) { - // only runs when all questions in a question-chain have been answered - // when selectedAnswers updates, user has completed this part's question chain and has a final answer - // (does not get run for each invididual question's answer, only when - // all relevant questions for the current part have been answered) - - /* - answer example format: - { - "answerResult": "DD11132", - "answeredQuestions": [ - { - "questionText": "Is your Grand Cherokee the Laredo model?", - "selectedAnswerText": "Yes", - "questionNum": 1, - } - ], - "glassIndex": 0 - } - */ - - // collect a list of the answered questions' numbers, needed later below - const answeredQuestionIndexes = []; - const foundDuplicateQuestions = []; - - // if user has answered a question differently than anything that was preloaded, - // we need to clear out any preloaded answers - this.selectedAnswers = {}; - - // loop through every answered question on the currently answered glass part - answer.answeredQuestions?.forEach((aq) => { - - // keep track of this question number - answeredQuestionIndexes.push(aq.questionNum); - - const answeredQuestionText = aq.questionText.toUpperCase(); - const answeredQuestionAnswer = aq.selectedAnswerText.toUpperCase(); - - // HANDLE DUPLICATE QUESTIONS - - // loop through all glass parts data - this.partsQuestionsData.forEach((glass, gpIndex) => { - - // only look for duplicates forward... to parts that follow after the currently being answered part - if (gpIndex > answer.glassIndex) { - - let suppressUntil; - // reset this glass part, in case user is changing their previous answers - glass.answerData = null; - glass.isSuppressedPart = null; - - // loop through this glass part's questions, looking for a questionText match - glass.questions.forEach((pq, pqIndex) => { - - // clear out any previously set answers - pq.answerSelected = null; - - // clear or set suppressQuestion property for each question - if (suppressUntil) { - // if suppressUntil has been set, then suppress this question if before it - if (pqIndex + 1 < suppressUntil) { - pq.suppressQuestion = true; - } else { - pq.suppressQuestion = null; - } - } else { - pq.suppressQuestion = null; - } - - // if these match then we have a duplicate question - if (pq.questionText.toUpperCase() === answeredQuestionText) { - - const thisAnsweredQuestion = glass.questions[pqIndex]; - let matchedAnswer; - let rejectedAnswers = []; // set as an array, in case we ever have questions with more than 2 answers... - - // which one of this questions' answers matches our answer? - pq.answers.forEach((ans) => { - if (ans.answerText.toUpperCase() === answeredQuestionAnswer) { - matchedAnswer = ans; - ans.selected = true; - } else { - rejectedAnswers.push(ans); - ans.selected = null; - } - }); - - // Update the key to re-render this part's question-chain component - this.partsQuestionsData[gpIndex].key = this.partsQuestionsData[gpIndex].glassLocation + this.partsQuestionsData[gpIndex].glassName + Date.now().toString(); - - // handle suppressing downstream in this question chain - - if (matchedAnswer.nextQuestionSequence) { - // ensure that the question that the accepted answer has set to be next is NOT suppressed - glass.questions[matchedAnswer.nextQuestionSequence - 1].suppressQuestion = null; - // if the duplicate is the 1ST question, then set suppressUntil var to lowest nextQuestion number - if (pqIndex === 0) { - if (!suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence } - if (matchedAnswer.nextQuestionSequence < suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence} - } - } - - // handle suppressing upstream in this question chain - glass.questions.forEach((q) => { - q.answers.forEach((thisAns) => { - // restore any of the answers that formerly led to the duplicated question - if (thisAns.originalNextQuestionSequence === pq.questionSequence) { - // restore original nextQuestionSequence - thisAns.nextQuestionSequence = thisAns.originalNextQuestionSequence; - this.originalNextQuestionSequence = null; - // restore original answerResult - if (thisAns.originalAnswerResult) { - thisAns.answerResult = thisAns.originalAnswerResult; - thisAns.originalAnswerResult = null; - } - } - // search for any answers that lead to the duplicated question - if (thisAns.nextQuestionSequence === pq.questionSequence) { - // update either the nextQuestionSequence or the answerResult - if (matchedAnswer.nextQuestionSequence) { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = matchedAnswer.nextQuestionSequence; - } else { - thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; - thisAns.nextQuestionSequence = null; - thisAns.originalAnswerResult = thisAns.originalAnswerResult || thisAns.answerResult; - thisAns.answerResult = matchedAnswer.answerResult; - } - } - }); - }); - - // suppress current question - thisAnsweredQuestion.suppressQuestion = true; - - const thisGlassPart = "glass" + gpIndex; - if (foundDuplicateQuestions[thisGlassPart]) { - if (!foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredQuestion.questionSequence)) { - foundDuplicateQuestions[thisGlassPart].push(thisAnsweredQuestion.questionSequence); - } - } else { - foundDuplicateQuestions[thisGlassPart] = [thisAnsweredQuestion.questionSequence]; - } - - // are there any questions left that are not suppressed? - const remainingQuestions = glass.questions.filter((q) => { - return !q.suppressQuestion; - }); - - if (remainingQuestions.length < 1) { - // this is the final answer for this glass part - - // mark this part as completely answered by adding answerData - const answeredQuestionObj = { - questionText: pq.questionText, - selectedAnswerText: matchedAnswer.answerText, - questionNum: pq.questionSequence, - suppressQuestion: pq.suppressQuestion, - }; - // set the answerData as 'already answered' - glass.answerData = { - answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult, - answeredQuestions: [answeredQuestionObj], - }; - - // suppress this glass because it has an answer - glass.isSuppressedPart = true; - } - - } - - }); - - // Update the key to re-render this part's question-chain component - this.partsQuestionsData[gpIndex].key = this.partsQuestionsData[gpIndex].glassLocation + this.partsQuestionsData[gpIndex].glassName + Date.now().toString(); - - } - - }); - - }); - - // DETERMINE ANSWERED QUESTIONS LIST FOR THIS GLASS PART - - // look through all (this part's) part questions for any duplicates that were suppressed; - // add them to the list of answered questions if found - - // EX answeredQuestionIndexes: [1,5,11,13] - - // EX foundDuplicateQuestions = { - // "glassPart1": [1], - // "glassPart2": [7, 10] - // }; - - const thisPartsDupes = foundDuplicateQuestions["glass" + answer.glassIndex]; - const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : []; - const glassPartAnswered = this.partsQuestionsData[answer.glassIndex]; - - thisPartsDupes?.forEach((dupe) => { - // dupe is a single integer - const dupeQuestion = glassPartAnswered.questions[dupe - 1]; - const dupeQuestionAnswer = dupeQuestion.answers.find((q) => q.selected === true); - - glassPartAnswered.questions.forEach((q) => { - let includeThisDupeInAnsweredQuestions = false; - - // did one of the answers of this question point to the duplicated question? - q.answers.forEach((a) => { - if ((dupe === a.originalNextQuestionSequence) && - (answeredQuestionIndexes.includes(q.questionSequence)) && - (a.answerText.toUpperCase() === dupeQuestionAnswer.answerText.toUpperCase())) { - includeThisDupeInAnsweredQuestions = true; - } - }); - - // is this q.questionSequence listed as the duplicated question's nextQuestionSequence? - if ((q.questionSequence === dupeQuestionAnswer.nextQuestionSequence) && (answeredQuestionIndexes.includes(q.questionSequence))) { - includeThisDupeInAnsweredQuestions = true; - } - - if (includeThisDupeInAnsweredQuestions) { - completeAnsweredQuestions.push({ - questionNum: dupeQuestion.questionSequence, - questionText: dupeQuestion.questionText, - selectedAnswerText: dupeQuestionAnswer.answerText, - suppressQuestion: dupeQuestion.suppressQuestion, - }); - } - }); - }); - - // make sure there are no duplicated dupes in the list... - const foundInCompleteAnsweredQuestions = new Set(); - let filteredCompleteAnsweredQuestions = completeAnsweredQuestions.filter(el => { - const duplicate = foundInCompleteAnsweredQuestions.has(el.questionText); - foundInCompleteAnsweredQuestions.add(el.questionText); - return !duplicate; - }); - filteredCompleteAnsweredQuestions = filteredCompleteAnsweredQuestions.sort((a,b) => a.questionNum - b.questionNum); - - // set final answer data for the current answered glass part - glassPartAnswered.answerData = { - answerResult: answer.answerResult, - answeredQuestions: filteredCompleteAnsweredQuestions, - } - - // this part has been fully answered, so advance to next part's question chain - for (let i = answer.glassIndex + 1; i < this.partsQuestionsData.length; i++) { - // if this part has not yet been fully answered, then make it the current part - if (!this.partsQuestionsData[i].answerData?.answerResult) { - this.currentGlassIndex = i; - break; - } - } - - }, }, components: { funnelHeader, diff --git a/src/mixins/vehicle-questions-mixin.js b/src/mixins/vehicle-questions-mixin.js index 415fa1e6d..a34107970 100644 --- a/src/mixins/vehicle-questions-mixin.js +++ b/src/mixins/vehicle-questions-mixin.js @@ -126,6 +126,263 @@ export default { return glass; }, + handleAnswerUpdates(answer, vm) { + // only runs when all questions in a question-chain have been answered + // when selectedAnswers updates, user has completed this part's question chain and has a final answer + // (does not get run for each invididual question's answer, only when + // all relevant questions for the current part have been answered) + + /* answer example format: + { + "answerResult": "DD11132", + "answeredQuestions": [ + { + "questionText": "Is your Grand Cherokee the Laredo model?", + "selectedAnswerText": "Yes", + "questionNum": 1, + } + ], + "glassIndex": 0 + } + */ + + const self = vm ?? this; + + // collect a list of the answered questions' numbers, needed later below + const answeredQuestionIndexes = []; + const foundDuplicateQuestions = []; + + // if user has answered a question differently than anything that was preloaded, + // we need to clear out any preloaded answers + self.selectedAnswers = {}; + + // loop through every answered question on the currently answered glass part + answer.answeredQuestions?.forEach((aq) => { + + // keep track of this question number + answeredQuestionIndexes.push(aq.questionNum); + + const answeredQuestionText = aq.questionText.toUpperCase(); + const answeredQuestionAnswer = aq.selectedAnswerText.toUpperCase(); + + // HANDLE DUPLICATE QUESTIONS + + // loop through all glass parts data + self.questionsData.forEach((glass, gpIndex) => { + + // only look for duplicates forward... to parts that follow after the currently being answered part + if (gpIndex > answer.glassIndex) { + + let suppressUntil; + // reset this glass part, in case user is changing their previous answers + glass.answerData = null; + glass.isSuppressedPart = null; + + // loop through this glass part's questions, looking for a questionText match + glass.questions.forEach((pq, pqIndex) => { + + // clear out any previously set answers + pq.answerSelected = null; + + // clear or set suppressQuestion property for each question + if (suppressUntil) { + // if suppressUntil has been set, then suppress this question if before it + if (pqIndex + 1 < suppressUntil) { + pq.suppressQuestion = true; + } else { + pq.suppressQuestion = null; + } + } else { + pq.suppressQuestion = null; + } + + // if these match then we have a duplicate question + if (pq.questionText.toUpperCase() === answeredQuestionText) { + + const thisAnsweredQuestion = glass.questions[pqIndex]; + let matchedAnswer; + let rejectedAnswers = []; // set as an array, in case we ever have questions with more than 2 answers... + + // which one of this questions' answers matches our answer? + pq.answers.forEach((ans) => { + if (ans.answerText.toUpperCase() === answeredQuestionAnswer) { + matchedAnswer = ans; + ans.selected = true; + } else { + rejectedAnswers.push(ans); + ans.selected = null; + } + }); + + // Update the key to re-render this part's question-chain component + self.questionsData[gpIndex].key = self.questionsData[gpIndex].glassLocation + self.questionsData[gpIndex].glassName + Date.now().toString(); + + // handle suppressing downstream in this question chain + + if (matchedAnswer.nextQuestionSequence) { + // ensure that the question that the accepted answer has set to be next is NOT suppressed + glass.questions[matchedAnswer.nextQuestionSequence - 1].suppressQuestion = null; + // if the duplicate is the 1ST question, then set suppressUntil var to lowest nextQuestion number + if (pqIndex === 0) { + if (!suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence } + if (matchedAnswer.nextQuestionSequence < suppressUntil) { suppressUntil = matchedAnswer.nextQuestionSequence} + } + } + + // handle suppressing upstream in this question chain + glass.questions.forEach((q) => { + q.answers.forEach((thisAns) => { + // restore any of the answers that formerly led to the duplicated question + if (thisAns.originalNextQuestionSequence === pq.questionSequence) { + // restore original nextQuestionSequence + thisAns.nextQuestionSequence = thisAns.originalNextQuestionSequence; + self.originalNextQuestionSequence = null; + // restore original answerResult + if (thisAns.originalAnswerResult) { + thisAns.answerResult = thisAns.originalAnswerResult; + thisAns.originalAnswerResult = null; + } + } + // search for any answers that lead to the duplicated question + if (thisAns.nextQuestionSequence === pq.questionSequence) { + // update either the nextQuestionSequence or the answerResult + if (matchedAnswer.nextQuestionSequence) { + thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; + thisAns.nextQuestionSequence = matchedAnswer.nextQuestionSequence; + } else { + thisAns.originalNextQuestionSequence = thisAns.nextQuestionSequence; + thisAns.nextQuestionSequence = null; + thisAns.originalAnswerResult = thisAns.originalAnswerResult || thisAns.answerResult; + thisAns.answerResult = matchedAnswer.answerResult; + } + } + }); + }); + + // suppress current question + thisAnsweredQuestion.suppressQuestion = true; + + const thisGlassPart = "glass" + gpIndex; + if (foundDuplicateQuestions[thisGlassPart]) { + if (!foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredQuestion.questionSequence)) { + foundDuplicateQuestions[thisGlassPart].push(thisAnsweredQuestion.questionSequence); + } + } else { + foundDuplicateQuestions[thisGlassPart] = [thisAnsweredQuestion.questionSequence]; + } + + // are there any questions left that are not suppressed? + const remainingQuestions = glass.questions.filter((q) => { + return !q.suppressQuestion; + }); + + if (remainingQuestions.length < 1) { + // this is the final answer for this glass part + + // mark this part as completely answered by adding answerData + const answeredQuestionObj = { + questionText: pq.questionText, + selectedAnswerText: matchedAnswer.answerText, + questionNum: pq.questionSequence, + suppressQuestion: pq.suppressQuestion, + }; + // set the answerData as 'already answered' + glass.answerData = { + answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult, + answeredQuestions: [answeredQuestionObj], + }; + + // suppress this glass because it has an answer + glass.isSuppressedPart = true; + } + + } + + }); + + // Update the key to re-render this part's question-chain component + self.questionsData[gpIndex].key = self.questionsData[gpIndex].glassLocation + self.questionsData[gpIndex].glassName + Date.now().toString(); + + } + + }); + + }); + + // DETERMINE ANSWERED QUESTIONS LIST FOR THIS GLASS PART + + // look through all (this part's) part questions for any duplicates that were suppressed; + // add them to the list of answered questions if found + + // EX answeredQuestionIndexes: [1,5,11,13] + + // EX foundDuplicateQuestions = { + // "glassPart1": [1], + // "glassPart2": [7, 10] + // }; + + const thisPartsDupes = foundDuplicateQuestions["glass" + answer.glassIndex]; + const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : []; + const glassPartAnswered = self.questionsData[answer.glassIndex]; + + thisPartsDupes?.forEach((dupe) => { + // dupe is a single integer + const dupeQuestion = glassPartAnswered.questions[dupe - 1]; + const dupeQuestionAnswer = dupeQuestion.answers.find((q) => q.selected === true); + + glassPartAnswered.questions.forEach((q) => { + let includeThisDupeInAnsweredQuestions = false; + + // did one of the answers of this question point to the duplicated question? + q.answers.forEach((a) => { + if ((dupe === a.originalNextQuestionSequence) && + (answeredQuestionIndexes.includes(q.questionSequence)) && + (a.answerText.toUpperCase() === dupeQuestionAnswer.answerText.toUpperCase())) { + includeThisDupeInAnsweredQuestions = true; + } + }); + + // is this q.questionSequence listed as the duplicated question's nextQuestionSequence? + if ((q.questionSequence === dupeQuestionAnswer.nextQuestionSequence) && (answeredQuestionIndexes.includes(q.questionSequence))) { + includeThisDupeInAnsweredQuestions = true; + } + + if (includeThisDupeInAnsweredQuestions) { + completeAnsweredQuestions.push({ + questionNum: dupeQuestion.questionSequence, + questionText: dupeQuestion.questionText, + selectedAnswerText: dupeQuestionAnswer.answerText, + suppressQuestion: dupeQuestion.suppressQuestion, + }); + } + }); + }); + + // make sure there are no duplicated dupes in the list... + const foundInCompleteAnsweredQuestions = new Set(); + let filteredCompleteAnsweredQuestions = completeAnsweredQuestions.filter(el => { + const duplicate = foundInCompleteAnsweredQuestions.has(el.questionText); + foundInCompleteAnsweredQuestions.add(el.questionText); + return !duplicate; + }); + filteredCompleteAnsweredQuestions = filteredCompleteAnsweredQuestions.sort((a,b) => a.questionNum - b.questionNum); + + // set final answer data for the current answered glass part + glassPartAnswered.answerData = { + answerResult: answer.answerResult, + answeredQuestions: filteredCompleteAnsweredQuestions, + } + + // this part has been fully answered, so advance to next part's question chain + for (let i = answer.glassIndex + 1; i < self.questionsData.length; i++) { + // if this part has not yet been fully answered, then make it the current part + if (!self.questionsData[i].answerData?.answerResult) { + self.currentGlassIndex = i; + break; + } + } + + }, // Can't use `this` because navigateForward is also called from vin-pages-mixin async navigateForward(partsOrQuestions, vm) { const self = vm ?? this; From fbbbf377beefb03ed69ae08c22bf2560c415f779 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 10 Oct 2022 13:24:56 -0400 Subject: [PATCH 03/53] CSR-803 standardize naming across questions pages --- .../capability-questions/capability-questions.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue index f9a15a6e8..cb0d0d656 100644 --- a/src/layouts/capability-questions/capability-questions.vue +++ b/src/layouts/capability-questions/capability-questions.vue @@ -12,7 +12,7 @@
@@ -106,11 +106,11 @@ export default { return capabilityQuestionsPageData && Object.keys(capabilityQuestionsPageData).length > 0; }, showThisQuestionChain(glass, i) { - if (!glass.capabilityQuestions || glass.capabilityQuestions?.length < 1 || glass.isSuppressedPart) { return false; } // return false if no capabilityQuestions or if suppressed + if (!glass.questions || glass.questions?.length < 1 || glass.isSuppressedPart) { return false; } // return false if no capabilityQuestions or if suppressed return this.currentQuestionChainIndex === i || glass.answerData?.answerResult?.length > 0; }, async forwardButtonAction() { - const capabilityQuestionsAnswersArray = this.questionsData.map((glass) => { + const questionAnswersArray = this.questionsData.map((glass) => { const selectedAnswerResult2 = this.getCorrespondingAnswerResult2(glass.answerData.answerResult); return { @@ -130,11 +130,11 @@ export default { }); // save to vuex store as order.damage.capabilityQuestionAnswers (array) - await this.dispatchStoreAction(this.storeActions.SAVE_CAPABILITY_QUESTION_ANSWERS, capabilityQuestionsAnswersArray, false); + await this.dispatchStoreAction(this.storeActions.SAVE_CAPABILITY_QUESTION_ANSWERS, questionAnswersArray, false); // get parts from the capabilityQuestionAnswers let partsOrQuestions = this.pageData.partsOrQuestions; - for (let answer of capabilityQuestionsAnswersArray) { + for (let answer of questionAnswersArray) { const correspondingPart = partsOrQuestions.find(partOrQuestion => partOrQuestion.glassLocation === answer.glassLocation); const partFromCapabilityQuestionAnswer = (await this.dispatchStoreAction(this.storeActions.GET_PART_FROM_CAPABILITY_QUESTION_ANSWER, answer.glassLocation, false)).data; From 4324f0ee5fba57eb084172290125ba1ed9b5420e Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 31 Oct 2022 14:25:13 -0400 Subject: [PATCH 04/53] CSR-803: merge --- src/global-methods.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/global-methods.js b/src/global-methods.js index 14e5cca0e..30eeffb65 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -7,6 +7,7 @@ import { GaCategories, GaActions, GaLabels } from "@/constants/analytics"; import { headerKeys } from "@/constants/header-keys"; export default { +<<<<<<< Updated upstream callHttpClient({ method, endpoint, payload, logApiCall = true }) { return new Promise((resolve, reject) => { const cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO; @@ -14,6 +15,21 @@ export default { const headers = { [headerKeys.EXPERIMENT]: JSON.stringify(store.getters.experimentSettings), }; +======= + callHttpClient({ method, endpoint, payload, logApiCall = true }) { + return new Promise((resolve, reject) => { + let cfDistroUrl = applicationConfig.CONSUMER_CF_DISTRO; + if (endpoint.includes("/order/")) { + cfDistroUrl = "https://localhost:5001"; + } + if (endpoint.includes("/parts/")) { + cfDistroUrl = "https://localhost:5003"; + } + const payloadAndAnalyticsData = Object.assign({}, payload, { AppName: "FixMyGlass" }); + const headers = { + [headerKeys.EXPERIMENT]: JSON.stringify(store.getters.experimentSettings) + } +>>>>>>> Stashed changes axios({ method: method, From 3f6e778c89b6f3ae3a8ac85626309ea41689bef7 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Wed, 2 Nov 2022 17:08:46 -0400 Subject: [PATCH 05/53] WIP --- .../textbox-question/textbox-question.vue | 80 ++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/src/common-components/textbox-question/textbox-question.vue b/src/common-components/textbox-question/textbox-question.vue index 62b605b7b..53d68aa3d 100644 --- a/src/common-components/textbox-question/textbox-question.vue +++ b/src/common-components/textbox-question/textbox-question.vue @@ -4,26 +4,35 @@ :for="inputId" :aria-label="questionText" class="form-label" + :class="[questionAlignment ? 'mx-auto' : '']" v-html="labelText"> - +
+ +
{{ errorMessage }}
@@ -57,7 +66,8 @@ export default { }, validationRules: String, cmsWidgetName: String, - maxLength: String, + maxLength: String, // Left or center. Default is left + questionAlignment: String, // Left or center. Default is left }, setup(props) { const propsClone = Object.assign({}, props); @@ -94,6 +104,12 @@ export default { errors, }; }, + data() { + return { + includeSearchIcon: false, + cornerStyle: false, + }; + }, computed: { questionText() { return this.getCmsContent(this.cmsWidgetName, "QuestionText"); @@ -148,6 +164,30 @@ export default { color: $black; font-weight: 500; } + .input-wrapper { + position: relative; + &.has-search-icon { + input[type="text"] { + border-radius: 50rem; + } + button[type="submit"] { + position: absolute; + top: 50%; + transform: translateY(-50%); + right: 0; + background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.7817 14.7328L11.8252 10.7762C12.8833 9.45005 13.3936 7.76911 13.2513 6.07849C13.1091 4.38788 12.325 2.81587 11.0601 1.6852C9.79515 0.554524 8.14538 -0.0490261 6.44946 -0.00154744C4.75353 0.0459312 3.14012 0.740836 1.94045 1.94051C0.740775 3.14018 0.0458701 4.75359 -0.00160848 6.44952C-0.0490871 8.14545 0.554463 9.79521 1.68514 11.0601C2.81581 12.325 4.38782 13.1091 6.07843 13.2514C7.76905 13.3937 9.44999 12.8834 10.7762 11.8252L14.7349 15.7839C14.8044 15.8527 14.8869 15.907 14.9774 15.9439C15.068 15.9808 15.165 15.9995 15.2628 15.9989C15.3606 15.9983 15.4573 15.9784 15.5475 15.9405C15.6376 15.9025 15.7194 15.8471 15.7881 15.7776C15.8568 15.708 15.9112 15.6256 15.9481 15.535C15.985 15.4444 16.0036 15.3474 16.0031 15.2496C16.0025 15.1518 15.9826 15.0551 15.9446 14.965C15.9067 14.8748 15.8513 14.7931 15.7817 14.7243V14.7328ZM6.63737 11.7913C5.61803 11.7913 4.62157 11.4891 3.77402 10.9228C2.92646 10.3564 2.26587 9.5515 1.87578 8.60975C1.4857 7.668 1.38363 6.63172 1.5825 5.63196C1.78136 4.6322 2.27222 3.71386 2.99301 2.99307C3.7138 2.27229 4.63214 1.78142 5.6319 1.58256C6.63166 1.38369 7.66793 1.48576 8.60969 1.87585C9.55144 2.26593 10.3564 2.92652 10.9227 3.77408C11.489 4.62163 11.7913 5.61809 11.7913 6.63743C11.7896 8.00382 11.2461 9.31376 10.2799 10.2799C9.3137 11.2461 8.00376 11.7897 6.63737 11.7913Z' fill='%231574A1'/%3E%3C/svg%3E%0A"); + background-repeat: no-repeat; + background-position: center; + border-radius: 0 50rem 50rem 0; + background-color: $blue-100; + width: 2.75rem; + height: 100%; + border: 1px solid $gray-500; + border-left: none; + display: flex; + } + } + } input { &.has-icon { background-image: url(~@/assets/img/icons/location-pin.svg); From e7f59904e9e6ebdbac78d52d2fcc49c891238f53 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Thu, 3 Nov 2022 08:34:26 -0400 Subject: [PATCH 06/53] WIP change button aria text. --- src/common-components/textbox-question/textbox-question.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common-components/textbox-question/textbox-question.vue b/src/common-components/textbox-question/textbox-question.vue index 53d68aa3d..e10caae1d 100644 --- a/src/common-components/textbox-question/textbox-question.vue +++ b/src/common-components/textbox-question/textbox-question.vue @@ -31,7 +31,7 @@ @blur="handleChange" :maxlength="maxLength ? maxLength : '999'" @focus="$emit('focus', $event.target.value)" /> -
{{ errorMessage }} From 341bb7a7e44330788d38cf1265493c325b4cb05c Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 3 Nov 2022 08:35:25 -0400 Subject: [PATCH 07/53] CSR-917 Don't allow enter key for multiselects --- .../base-input-button/base-input-button.spec.js | 13 ++++++------- .../base-input-button/base-input-button.vue | 1 - 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/common-components/base-input-button/base-input-button.spec.js b/src/common-components/base-input-button/base-input-button.spec.js index 87e8af6d2..8a3ff6356 100644 --- a/src/common-components/base-input-button/base-input-button.spec.js +++ b/src/common-components/base-input-button/base-input-button.spec.js @@ -228,7 +228,7 @@ describe("baseInputButton.vue", () => { expect(wrapper.emitted()).not.toHaveProperty("update:modelValue"); }); - test("focus and click enter on a checkbox => update:modelValue is emitted with correct value", async () => { + test("focus and click enter on a checkbox => nothing should happen", async () => { // Arrange const { wrapper } = setupMocks({ mockData: { @@ -243,9 +243,10 @@ describe("baseInputButton.vue", () => { // Act await input.trigger("keypress", { key: "enter" }); + console.log(wrapper.emitted()["update:modelValue"]); // Assert - expect(wrapper.emitted()["update:modelValue"][0][0]).toEqual(["Hi"]); + expect(wrapper.emitted()["update:modelValue"]).toBe(undefined); }); }); @@ -319,7 +320,7 @@ describe("baseInputButton.vue", () => { expect(wrapper.vm.handlePushClickEventToGACheck).not.toHaveBeenCalled(); }); - test("eventType === eventTypes.ENTER => call handleClick and handlePushClickEventToGACheck", () => { + test("eventType === eventTypes.ENTER => do nothing", () => { // Arrange const { wrapper } = setupMocks({ mockData: { @@ -336,11 +337,9 @@ describe("baseInputButton.vue", () => { wrapper.vm.handleEventAction("enter", { myEvent: "test" }); // Assert - expect(wrapper.vm.handleClick).toHaveBeenCalledWith({ - myEvent: "test", - }); - expect(wrapper.vm.handlePushClickEventToGACheck).toHaveBeenCalledWith("click"); + expect(wrapper.vm.handleClick).not.toHaveBeenCalled(); expect(wrapper.vm.handleSelectionChange).not.toHaveBeenCalled(); + expect(wrapper.vm.handlePushClickEventToGACheck).not.toHaveBeenCalled(); }); test("eventType === eventTypes.CHANGE => call handleClick and handlePushClickEventToGACheck", () => { diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue index b71f4a63c..006323a18 100644 --- a/src/common-components/base-input-button/base-input-button.vue +++ b/src/common-components/base-input-button/base-input-button.vue @@ -53,7 +53,6 @@ export default { handleEventAction(eventType, e) { if (this.isMultiSelect) { switch (eventType) { - case this.eventTypes.ENTER: case this.eventTypes.CHANGE: this.handleClick(e); this.handlePushClickEventToGACheck(this.eventTypes.CLICK); From af80ae6f22a35cd6de29402f8a1b0c0189e1df84 Mon Sep 17 00:00:00 2001 From: Katie Date: Thu, 3 Nov 2022 09:33:37 -0400 Subject: [PATCH 08/53] CSR-918 Edit hover styling --- src/App.vue | 1 + src/router/index.js | 5 +++++ src/styles/common-error-styles.scss | 13 ++++++++----- src/styles/mixins/customMixins.scss | 4 ++++ src/styles/shared-input-button-styles.scss | 7 +++++++ .../list-button-horizontal.vue | 14 +------------- src/ux-components/list-button/list-button.vue | 12 +----------- src/ux-components/list-card/list-card.vue | 13 +------------ src/ux-components/radio/radio.vue | 2 +- 9 files changed, 29 insertions(+), 42 deletions(-) create mode 100644 src/styles/shared-input-button-styles.scss diff --git a/src/App.vue b/src/App.vue index 75e80355f..aef77fcb0 100644 --- a/src/App.vue +++ b/src/App.vue @@ -23,4 +23,5 @@ export default { @import "@/styles/common-typography-styles.scss"; @import "@/styles/common-error-styles.scss"; @import "@/styles/common-animations.scss"; +@import "@/styles/shared-input-button-styles.scss"; diff --git a/src/router/index.js b/src/router/index.js index 6350edf5d..02e0def4c 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -289,6 +289,11 @@ function navigateToUrl(url, optionalQuery = {}) { externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]); } + externalUrl.searchParams.append( + "experiments", + "ConceptFunnel=ConceptFunnel_V1=ConceptFunnel_TEST=true" + ); + window.location.assign(externalUrl); } diff --git a/src/styles/common-error-styles.scss b/src/styles/common-error-styles.scss index d497ae6ce..9befb1eb0 100644 --- a/src/styles/common-error-styles.scss +++ b/src/styles/common-error-styles.scss @@ -37,11 +37,14 @@ html { } &.list-button-horizontal { color: $red; - label { - border: 1px solid $red; - &:hover { - box-shadow: 0px 0px 0px 4px $red-200; - } + // label { + // border: 1px solid $red; + // &:hover { + // @include box-shadow-lg-hover($red-200); + // } + // } + &:hover { + @include box-shadow-lg-hover($red-200); } input[type="checkbox"]:focus + label, input[type="radio"]:focus + label { diff --git a/src/styles/mixins/customMixins.scss b/src/styles/mixins/customMixins.scss index 8620968f0..e9954b2a2 100644 --- a/src/styles/mixins/customMixins.scss +++ b/src/styles/mixins/customMixins.scss @@ -4,3 +4,7 @@ @mixin blue-gradient { background: linear-gradient(270deg, $blue 0%, $blue-800 100%); } + +@mixin box-shadow-lg-hover($color) { + box-shadow: 0 0 0 4px $color; +} diff --git a/src/styles/shared-input-button-styles.scss b/src/styles/shared-input-button-styles.scss new file mode 100644 index 000000000..e64faee71 --- /dev/null +++ b/src/styles/shared-input-button-styles.scss @@ -0,0 +1,7 @@ +.base-input-button { + &:hover { + cursor: pointer; + @include box-shadow-lg-hover($blue-300); + border: 1px solid transparent; + } +} diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index 1b4232c4c..4537ce5bb 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -2,7 +2,7 @@ @@ -86,18 +86,6 @@ export default { width: 100%; color: $gray-600; - &:hover { - @include media-breakpoint-up(sm) { - box-shadow: 0 0 0 4px $blue-300; - cursor: pointer; - z-index: 4 !important; - } - } - - + p { - display: none; - } - span { font-size: 0.875rem; } diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 4f7d34ae9..031805509 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -1,7 +1,7 @@