Merge pull request #586 from Safelite/feature/CSR-108

Feature/CSR-108
This commit is contained in:
AdamCaouetteSafelite 2022-06-30 14:34:29 -04:00 committed by GitHub
commit b6f453e736
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 75 deletions

View file

@ -13,6 +13,7 @@ module.exports = {
"!src/helpers/unit-test-helper.js",
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
"!src/layouts/part-questions/**/*.vue",
"!src/common-components/question-chain/**/*.vue",
"!src/layouts/reveal/**/*.vue"
// END
], // ! means exclude from coverage.

View file

@ -2,13 +2,13 @@
<div v-for="(q, i) in questions" :key="i">
<transition appear name="fade" mode="out-in">
<buttonQuestion
v-if="q.questionSequence === currentQuestion"
v-if="q.answerSelected || (q.questionSequence === currentQuestionNum)"
class="radioQuestion"
:class="(q.questionSequence === currentQuestionNum) && 'current-question'"
:questionText="q.questionText"
:answers="q.answers"
:groupName="`${questionData.glassName}-${questionData.glassLocation}-${i}`"
textPosition="text-start"
v-model="selectedValue"
v-model="selectedValuesArray"
:isRequired=true
:validationRules="validationRules"
:clearOnUnmount=false
@ -24,8 +24,8 @@ export default {
name: "questionChain",
data() {
return {
currentQuestion: 1,
answeredQuestions: [],
currentQuestionNum: 1,
questions: [{ "BlankObject": "NOT USED... placeholder for question #0"}],
};
},
props: {
@ -33,87 +33,113 @@ export default {
validationRules: String,
modelValue: Array,
},
created() {
this.questionData.partQuestions.map((q, i) => {
let answerPair = [];
const eachQuestion = {
questionText: q.questionText,
questionSequence: q.questionSequence,
answers: q.answers.map((a) => {
answerPair.push(a.nextQuestionSequence ? a.nextQuestionSequence : a.answerResult);
return {
Text: a.answerText,
// Name will either be nextQuestionSequence or answerResult
// Name will be used by list-button as the input value.
// It must be a single string or number, so concatenating together a string with
// 4 pieces of data separated by pipe characters:
// question number|type of answer|answer value|answer text
Name: a.nextQuestionSequence ?
q.questionSequence + "|nextQuestion|" + a.nextQuestionSequence + "|" + a.answerText :
q.questionSequence + "|answer|" + a.answerResult + "|" + a.answerText,
nextQuestionSequence: a.nextQuestionSequence,
}
}),
answerSelected: "",
};
eachQuestion.answerPair = answerPair;
this.questions.push(eachQuestion);
});
},
computed: {
questions() {
const questions = this.questionData.partQuestions.map((q, i) => {
return {
questionText: q.questionText,
questionSequence: q.questionSequence,
answers: q.answers.map((a) => {
return {
Text: a.answerText,
// Name will either be nextQuestionSequence or answerResult
Name: a.nextQuestionSequence ? a.nextQuestionSequence : "answer-" + a.answerResult,
nextQuestionSequence: a.nextQuestionSequence,
answerResult: a.answerResult,
}
})
}
});
// add an empty item to be array[0] since we start with 1
questions.unshift({ "DeliberatelyBlankObject": "This object has been added as a placeholder only for question #0"});
return questions;
},
selectedValue: {
selectedValuesArray: {
get: function() {
return this.modelValue;
return [];
},
set: function(returnedAnswer) {
const isNewModelValueComplete = this.getNewModelValue(returnedAnswer);
set: function(returnedAnswerArray) {
const returnedAnswer = returnedAnswerArray[returnedAnswerArray.length-1];
const isQuestionChainComplete = this.handleReturnedAnswer(returnedAnswer);
if (isNewModelValueComplete) {
this.$emit("update:modelValue", isNewModelValueComplete);
if (isQuestionChainComplete) {
this.$emit("update:modelValue", isQuestionChainComplete);
}
}
},
currentQuestion() {
return this.questions[this.currentQuestionNum];
},
},
methods: {
handleReturnedAnswer(returnedAnswer) { // returns either a final answer or Boolean false
if (!returnedAnswer) { return false }
// Example returnedAnswers:
// "1|nextQuestion|3|No"
// "5|answer|DW02104|Yes"
const returnedAnswerArray = returnedAnswer.split("|");
const questionNum = returnedAnswerArray[0];
const questionType = returnedAnswerArray[1];
const questionAnswer = returnedAnswerArray[2];
const questionAnswerText = returnedAnswerArray[3];
// remove all previous answers after the index of this one in questions
this.questions.map((q) => {
if ((q.questionSequence > questionNum) || (q.answerPair?.includes(questionAnswer))) {
q.answerSelected = "";
}
return q;
});
// set this question as "answered"
this.questions[questionNum].answerSelected = questionAnswerText;
// update to next question index
this.currentQuestionNum = questionType === "nextQuestion" ? parseInt(questionAnswer) : parseInt(questionNum); // update count to display next question
// return false if there's a nextQuestion... or return an object with "final" answers
if (questionType === "nextQuestion") {
return false;
} else {
const answeredQuestions = [];
this.questions.forEach(( q ) => {
if (q.answerSelected) {
answeredQuestions.push({
questionText: q.questionText,
selectedAnswerText: q.answerSelected,
questionNum: questionNum,
});
}
});
return {
answerResult: questionAnswer,
answeredQuestions: answeredQuestions,
};
}
}
},
methods: {
getNewModelValue(returnedAnswer) {
if (!returnedAnswer || !Array.isArray(returnedAnswer)) { return false }
const lastAnswer = returnedAnswer[returnedAnswer.length - 1];
const currentQuestion = this.questions[this.currentQuestion];
if (lastAnswer.indexOf("answer-") === 0) {
// if it is an answerResult
const finalAnswer = lastAnswer.slice(7);
const currentQuestionSelectedAnswer = currentQuestion.answers.find(
({ answerResult }) => answerResult === finalAnswer
);
// add current item to list of answered questions
this.answeredQuestions.push(
{
questionText: currentQuestion.questionText,
selectedAnswerText: currentQuestionSelectedAnswer.Text,
}
);
return {
answerResult: finalAnswer,
answeredQuestions: this.answeredQuestions,
};
} else {
const currentQuestionSelectedAnswer = currentQuestion.answers.find(
({ nextQuestionSequence }) => nextQuestionSequence === parseInt(lastAnswer)
);
// add current item to list of answered questions
this.answeredQuestions.push(
{
questionText: currentQuestion.questionText,
selectedAnswerText: currentQuestionSelectedAnswer.Text,
}
);
this.currentQuestion = parseInt(lastAnswer); // update count to display next question
return false;
}
watch: {
currentQuestion: {
handler() {
// scrolls page to next active question
this.$nextTick(() => {
document.querySelector('.current-question').scrollIntoView({behavior: "smooth"});
})
},
deep: true
}
},
components: {
buttonQuestion,
},
};
</script>
</script>