@@ -95,9 +95,6 @@ export default {
valueToLogType: String,
},
computed: {
- formattedGroupName() {
- return this.groupName.replace(" ", "-");
- },
getFieldSetClasses() {
if (this.isOverflowScrollable) {
return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0";
@@ -147,21 +144,37 @@ export default {
},
selectedValues: {
get: function() {
+ console.log("_ _ BQ - - selectedValues GET this.modelValue: ", this.modelValue) //./
+ /*
+ "1|answer|DD11132|Yes"
+ */
return this.modelValue;
},
set: function(newValue) {
+ console.log("_ _ BQ - - selectedValues GET newValue: ", newValue) //./
+
this.$emit("update:modelValue", newValue);
}
},
},
methods: {
- getValues(answer){
- if (this.useTextForValue){
- return answer.Text
- }
-
+ formatString(str) {
+ return str.replace(" ", "-");
+ },
+ getValue(answer){
+ if (this.useTextForValue) { return answer.Text }
return answer.Name ? answer.Name : answer;
},
+ getAnswerString(answer, prop = "Name") {
+ switch (typeof answer) {
+ case "string":
+ case "number":
+ case "boolean":
+ return this.formatString(answer.toString());
+ default:
+ return answer[prop] ? this.formatString(answer[prop]) : this.formatString(answer.toString());
+ }
+ },
handleCheckedChanged(val) {
if(this.selectingInitiatesLoad) {
this.selectedValues = val.value;
diff --git a/src/common-components/question-chain/question-chain.vue b/src/common-components/question-chain/question-chain.vue
index 3ac603eb2..560621c9c 100644
--- a/src/common-components/question-chain/question-chain.vue
+++ b/src/common-components/question-chain/question-chain.vue
@@ -9,7 +9,7 @@
:answers="q.answers"
:groupName="`${keyString}-${q.questionSequence}`"
v-model="q.answerSelected"
- @isCheckedChanged="handleChainCompleted"
+ @isCheckedChanged="handleAnswer"
isRequired
:validationRules="validationRules"
/>
@@ -58,12 +58,15 @@ export default {
q.questionSequence + "|nextQuestion|" + a.nextQuestionSequence + "|" + a.answerText :
q.questionSequence + "|answer|" + a.answerResult + "|" + a.answerText,
nextQuestionSequence: a.nextQuestionSequence,
+ answerResult: a.answerResult,
+ questionSequence: q.questionSequence,
+ questionType: a.nextQuestionSequence ? "nextQuestion" : "answer",
}
}),
answerSelected: q.answerSelected || "",
};
question.answerPair = answerPair;
- if (!q.isDuplicateQuestion) {
+ if (!q.suppressQuestion) {
this.questions.push(question);
}
});
@@ -76,75 +79,86 @@ export default {
document.querySelector('.current-question').scrollIntoView({behavior: "smooth"});
})
}
-
},
methods: {
- handleChainCompleted(returnedAnswer) {
- const isQuestionChainComplete = this.handleReturnedAnswer(returnedAnswer.value);
+ handleAnswer(returnedAnswer) {
+ /*
+ returnedAnswer example format:
+ {
+ "checkValue": "1|answer|DD11132|Yes",
+ "value": "1|answer|DD11132|Yes",
+ "buttonId": "Driver-Front-1-1|answer|DD11132|Yes"
+ }
+ */
+ const isQuestionChainComplete = this.testReturnedAnswer(returnedAnswer.checkValue);
- if (isQuestionChainComplete) {
- this.$emit("update:modelValue", isQuestionChainComplete);
- }
- },
- handleReturnedAnswer(returnedAnswer) { // this method will return either a final answer or Boolean false
- if (!returnedAnswer) { return false }
+ if (isQuestionChainComplete) {
+ this.$emit("update:modelValue", isQuestionChainComplete);
+ }
+ },
+ testReturnedAnswer(returnedAnswer) { // this method will return either a final answer or Boolean false
+ if (!returnedAnswer) { return false }
- // Example returnedAnswers:
- // "1|nextQuestion|3|No"
- // "5|answer|DW02104|Yes"
+ // Example returnedAnswers:
+ // "1|nextQuestion|3|No"
+ // "5|answer|DW02104|Yes"
- const returnedAnswerArray = returnedAnswer.split("|");
- const questionNum = parseInt(returnedAnswerArray[0]);
- const questionType = returnedAnswerArray[1];
- const questionAnswer = returnedAnswerArray[2];
- const questionAnswerText = returnedAnswerArray[3];
+ const returnedAnswerArray = returnedAnswer.split("|");
+ const questionNum = parseInt(returnedAnswerArray[0]);
+ const questionType = returnedAnswerArray[1];
+ const questionAnswer = returnedAnswerArray[2];
+ const questionAnswerText = returnedAnswerArray[3];
+ const answeredQuestions = [];
- this.questions.forEach((q) => {
- // mark this question as "answered"
- if (q.questionSequence === questionNum) {
- q.answerSelected = returnedAnswer;
- q.answerNumber = questionNum;
- }
- // remove all previous answers after the index of this one in questions
- if ((q.questionSequence > questionNum)) {
- delete q.answerSelected;
- }
- });
-
- // return false if there's a nextQuestion... or return an object with "final" answers
- if (questionType === "nextQuestion") {
- // update to next question index
- this.currentQuestionNum = parseInt(questionAnswer); // update count to display next question
- // scroll the next question into view
- this.$nextTick(() => {
- document.querySelector('.current-question').scrollIntoView({behavior: "smooth"});
- })
- return false;
- } else {
- const answeredQuestions = [];
- this.questions.forEach(( q ) => {
- if (q.answerSelected) {
- answeredQuestions.push({
- questionText: q.questionText,
- selectedAnswerText: q.answerSelected.split("|")[3],
- questionNum: q.questionSequence,
+ this.questions.forEach((q) => {
+ // find this question and mark it as "answered" by populating answerSelected
+ if (q.questionSequence === questionNum) {
+ q.answerSelected = returnedAnswer;
+ q.answerNumber = questionNum;
+ q.selectedAnswerText = questionAnswerText;
+ }
+ // remove all answers AFTER this question...
+ // (needed in case user is changing previously answered questions)
+ if ((q.questionSequence > questionNum)) {
+ delete q.answerSelected;
+ }
+ if (q.answerSelected) {
+ answeredQuestions.push({
+ questionText: q.questionText,
+ selectedAnswerText: q.answerSelected.split("|")[3],
+ questionNum: q.questionSequence,
+ });
+ }
});
- }
- });
- // reset current question index
- this.currentQuestionNum = 0; // reset count
- return {
- answerResult: questionAnswer,
- answeredQuestions: answeredQuestions,
- partIndex: this.partIndex,
- };
+ // return false if there's a nextQuestion... or return an object with final answers (truthy)
+ if (questionType === "nextQuestion") {
- }
+ // update to next question index
+ this.currentQuestionNum = parseInt(questionAnswer); // update count to display next question
+ // scroll the next question into view
+ this.$nextTick(() => {
+ document.querySelector('.current-question').scrollIntoView({behavior: "smooth"});
+ })
+ return false;
+
+ } else {
+
+ // reset current question index (removes .current-question class)
+ this.currentQuestionNum = 0; // reset count
+
+ // return an object with the part answer, all the answered questions, and the part index
+ return {
+ answerResult: questionAnswer,
+ answeredQuestions: answeredQuestions,
+ partIndex: this.partIndex,
+ };
+
+ }
+ },
+ },
+ components: {
+ buttonQuestion,
},
- },
- components: {
- buttonQuestion,
- },
};
diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue
index 8082e42f7..881eaf90b 100644
--- a/src/layouts/part-questions/part-questions.vue
+++ b/src/layouts/part-questions/part-questions.vue
@@ -23,7 +23,6 @@
0;
},
- handleAnswerUpdates(key, 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 relevent questions for the current part have been answered)
- const glassPartWithAnswer = this.partsQuestionsData[answer.partIndex];
- const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : [];
+ handleAnswerUpdates(key, 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 relevent 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,
+ "extra": {
+ "Text": "Yes",
+ "nextQuestionSequence": null,
+ "answerResult": "DD11132",
+ "questionSequence": 1,
+ "questionType": "answer"
+ }
+ }
+ ],
+ "partIndex": 0
+ }
+ */
+
+ // collect a list of the answered questions' numbers, needed later below
const answeredQuestionIndexes = [];
- // since user has answered a question differently than anything that was preloaded,
- // then clear out the preloaded answers
+ // if user has answered a question differently than anything that was preloaded,
+ // we need to clear out any preloaded answers
this.selectedAnswers = {};
- // examine all the answers returned that were part of the user's journey through question-chain
-
- // loop through every answered question on currently answered glass part
+ // loop through every answered question on the currently answered glass part
answer.answeredQuestions?.forEach((aq) => {
- // gather all the question numbers of the answered questions
+ // 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 (but only examining parts after currently being answered part)
- this.partsQuestionsData.forEach((glassPart, i) => {
+
+ // loop through all glass parts data
+ this.partsQuestionsData.forEach((glassPart, gpIndex) => {
- // restrict duplicate logic to only parts that follow the currently being answered part
- if (i > answer.partIndex) {
+ // only look for duplicates forward... to parts that follow after the currently being answered part
+ if (gpIndex > answer.partIndex) {
+
+ let suppressUntil;
+ // reset this glass part, in case user is changing their previous answers
+ glassPart.answerData = null;
+ glassPart.isSuppressedPart = null;
// loop through this glass part's part questions, looking for a questionText match
glassPart.partQuestions.forEach((pq, pqIndex) => {
+
// clear out any previously set answers
- //delete pq.answerSelected;
pq.answerSelected = null;
- // does pq.questionText match answeredQuestionText? (aka do we have a duplicate question?)
+ // 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) {
-
- // which one of this partQuestions' answers matches our answer?
+
+ const thisAnsweredPartQuestion = glassPart.partQuestions[pqIndex];
let matchedAnswer;
- pq.answers.forEach((ans, ansIndex) => {
- // delete pq.answers[ansIndex].selected;
- pq.answers[ansIndex].selected = null;
+ let rejectedAnswers = []; // set as an array, in case we ever have questions with more than 2 answers...
+
+ // which one of this partQuestions' answers matches our answer?
+ pq.answers.forEach((ans) => {
if (ans.answerText.toUpperCase() === answeredQuestionAnswer) {
matchedAnswer = ans;
- pq.answers[ansIndex].selected = true;
+ ans.selected = true;
+ } else {
+ rejectedAnswers.push(ans);
+ ans.selected = null;
}
});
- if (matchedAnswer) {
- const thisAnsweredPartQuestion = glassPart.partQuestions[pqIndex];
+ // 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();
- // remove answerData from this glass part
- glassPart.answerData = null;
- glassPart.isSuppressedPart = null;
-
- // Update the key to re-render this part's question-chain component
- this.partsQuestionsData[i].key = this.partsQuestionsData[i].glassLocation + this.partsQuestionsData[i].glassName + Date.now().toString();
-
- // handle suppressing downstream in this question chain
- const rejectedAnswer = thisAnsweredPartQuestion.answers.filter((ans) => {
- return !ans.selected;
- });
-
- if (rejectedAnswer[0].nextQuestionSequence) {
- glassPart.partQuestions[rejectedAnswer[0].nextQuestionSequence - 1].suppressDuplicateQuestion = true;
- }
- if (matchedAnswer.nextQuestionSequence) {
- // ensure that accepted answer is NOT suppressed
- glassPart.partQuestions[matchedAnswer.nextQuestionSequence - 1].suppressDuplicateQuestion = null;
- }
-
- // handle suppressing upstream in this question chain
- glassPart.partQuestions.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 of the 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;
- }
- }
- });
- });
+ // handle suppressing downstream in this question chain
- // suppress current question
- thisAnsweredPartQuestion.suppressDuplicateQuestion = true;
-
- const thisGlassPart = "glassPart" + i;
- if (this.foundDuplicateQuestions[thisGlassPart]) {
- if (!this.foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredPartQuestion.questionSequence)) {
- this.foundDuplicateQuestions[thisGlassPart].push(thisAnsweredPartQuestion.questionSequence);
+ if (matchedAnswer.nextQuestionSequence) {
+ // ensure that the question that the accepted answer has set to be next is NOT suppressed
+ glassPart.partQuestions[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
+ glassPart.partQuestions.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;
+ }
}
- } else {
- this.foundDuplicateQuestions[thisGlassPart] = [thisAnsweredPartQuestion.questionSequence];
- }
-
- // are there any questions left that are not suppressed?
- const remainingQuestions = glassPart.partQuestions.filter((q) => {
- return !q.suppressDuplicateQuestion;
});
-
- 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,
- isDuplicateQuestion: pq.suppressDuplicateQuestion,
- };
- // set the answerData as 'already answered'
- glassPart.answerData = {
- answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult,
- answeredQuestions: [answeredQuestionObj],
- };
-
- // suppress this glassPart because it has an answer
- glassPart.isSuppressedPart = true;
+ });
+
+ // suppress current question
+ thisAnsweredPartQuestion.suppressQuestion = true;
+
+ const thisGlassPart = "glassPart" + gpIndex;
+ if (this.foundDuplicateQuestions[thisGlassPart]) {
+ if (!this.foundDuplicateQuestions[thisGlassPart].includes(thisAnsweredPartQuestion.questionSequence)) {
+ this.foundDuplicateQuestions[thisGlassPart].push(thisAnsweredPartQuestion.questionSequence);
}
+ } else {
+ this.foundDuplicateQuestions[thisGlassPart] = [thisAnsweredPartQuestion.questionSequence];
+ }
- } // END of if (matchedAnswer)
+ // are there any questions left that are not suppressed?
+ const remainingQuestions = glassPart.partQuestions.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'
+ glassPart.answerData = {
+ answerResult: matchedAnswer.nextQuestionSequence ? matchedAnswer.nextQuestionSequence : matchedAnswer.answerResult,
+ answeredQuestions: [answeredQuestionObj],
+ };
+
+ // suppress this glassPart because it has an answer
+ glassPart.isSuppressedPart = true;
+ }
}
});
// Update the key to re-render this part's question-chain component
- this.partsQuestionsData[i].key = this.partsQuestionsData[i].glassLocation + this.partsQuestionsData[i].glassName + Date.now().toString();
+ this.partsQuestionsData[gpIndex].key = this.partsQuestionsData[gpIndex].glassLocation + this.partsQuestionsData[gpIndex].glassName + Date.now().toString();
}
@@ -308,8 +339,10 @@ export default {
});
+ // 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
+ // add them to the list of answered questions if found
// EX answeredQuestionIndexes: [1,5,11,13]
@@ -319,13 +352,15 @@ export default {
// };
const thisPartsDupes = this.foundDuplicateQuestions["glassPart" + answer.partIndex];
-
+ const completeAnsweredQuestions = answer.answeredQuestions ? [...answer.answeredQuestions] : [];
+ const glassPartAnswered = this.partsQuestionsData[answer.partIndex];
+
thisPartsDupes?.forEach((dupe) => {
// dupe is a single integer
- const dupeQuestion = glassPartWithAnswer.partQuestions[dupe - 1];
+ const dupeQuestion = glassPartAnswered.partQuestions[dupe - 1];
const dupeQuestionAnswer = dupeQuestion.answers.find((q) => q.selected === true);
- glassPartWithAnswer.partQuestions.forEach((q) => {
+ glassPartAnswered.partQuestions.forEach((q) => {
let includeThisDupeInAnsweredQuestions = false;
// did one of the answers of this question point to the duplicated question?
@@ -347,7 +382,7 @@ export default {
questionNum: dupeQuestion.questionSequence,
questionText: dupeQuestion.questionText,
selectedAnswerText: dupeQuestionAnswer.answerText,
- isDuplicateQuestion: dupeQuestion.suppressDuplicateQuestion,
+ suppressQuestion: dupeQuestion.suppressQuestion,
});
}
});
@@ -363,7 +398,7 @@ export default {
filteredCompleteAnsweredQuestions = filteredCompleteAnsweredQuestions.sort((a,b) => a.questionNum - b.questionNum);
// set final answer data for the current answered glass part
- glassPartWithAnswer.answerData = {
+ glassPartAnswered.answerData = {
answerResult: answer.answerResult,
answeredQuestions: filteredCompleteAnsweredQuestions,
}
@@ -386,8 +421,12 @@ export default {
this.partsQuestionsData = this.partsQuestionsFromApi.map((part, i) => {
part.key = part.glassLocation + "-" + part.glassName;
this.selectedAnswers[part.key] = [];
+ if (!alreadyAnsweredQuestions) {
+ part.answerData = null;
+ }
alreadyAnsweredQuestions?.forEach((savedPart) => {
+
if (!savedPart.glassLocation || !savedPart.glassName || !savedPart.answeredQuestions || !savedPart.result) {
return;
}
@@ -412,8 +451,8 @@ export default {
// mark this partQuestion as answered (question-chain will read this)
part.partQuestions[aq.questionNum-1].answerSelected = answerString;
// mark this partQuestion as duplicate if it is (question-chain will read this)
- if (aq.isDuplicateQuestion) {
- part.partQuestions[aq.questionNum-1].isDuplicateQuestion = true;
+ if (aq.suppressQuestion) {
+ part.partQuestions[aq.questionNum-1].suppressQuestion = true;
}
});
@@ -426,6 +465,7 @@ export default {
answeredQuestions: savedPart.answeredQuestions
}
}
+
});
// Set up watch for each set of part questions, which gets updated when all questions for a part have been answered
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 83c9b0fd1..7011835b9 100644
--- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue
+++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue
@@ -15,6 +15,7 @@
:value="value"
:aria-required="isRequired"
v-model="checkValue"
+ :checked="checkValue"
@change="handleInputChange()"
/>