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/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..572be9ef5 100644
--- a/src/common-components/base-input-button/base-input-button.vue
+++ b/src/common-components/base-input-button/base-input-button.vue
@@ -1,6 +1,6 @@
@@ -104,7 +112,6 @@ export default {
box-shadow: 0px -1px 0px rgba(179, 180, 181, 0.3);
button {
margin: 0;
- height: 3rem;
}
}
}
diff --git a/src/common-components/question-chain/question-chain.vue b/src/common-components/question-chain/question-chain.vue
index 6121cbd25..432fd2eca 100644
--- a/src/common-components/question-chain/question-chain.vue
+++ b/src/common-components/question-chain/question-chain.vue
@@ -7,7 +7,7 @@
:class="q.questionSequence === currentQuestionNum && 'current-question'"
:questionText="q.questionText"
:answers="q.answers"
- :groupName="`question-${glassIndex}-${q.questionSequence}`"
+ :groupName="`question-${index}-${q.questionSequence}`"
:modelValue="q.answerSelected"
@update:modelValue="handleAnswer(q, $event)"
isRequired
@@ -31,8 +31,9 @@ export default {
props: {
questionData: Object,
validationRules: String,
- modelValue: Array,
- glassIndex: Number,
+ modelValue: Object,
+ index: Number,
+ answerKey: String,
},
async created() {
// do a test validation check upon create to prevent out of sync / incorrect valid states
@@ -65,7 +66,7 @@ export default {
}),
answerSelected: q.answerSelected || "",
};
- if (!q.suppressQuestion) {
+ if (!q.suppressThisQuestion) {
this.questions.push(question);
}
});
@@ -81,7 +82,6 @@ export default {
},
methods: {
handleAnswer(question, returnedAnswer) {
- question.answerSelected = returnedAnswer;
/*
returnedAnswer example format:
{
@@ -90,6 +90,8 @@ export default {
"buttonId": "Driver-Front-1-1|answer|DD11132|Yes"
}
*/
+
+ question.answerSelected = returnedAnswer;
const isQuestionChainComplete = this.getQuestionChainAnswerIfComplete(returnedAnswer);
if (isQuestionChainComplete) {
@@ -153,7 +155,7 @@ export default {
return {
answerResult: questionAnswer,
answeredQuestions: answeredQuestions,
- glassIndex: this.glassIndex,
+ index: this.index,
};
}
},
diff --git a/src/common-components/questions-page-layout/questions-page-layout.vue b/src/common-components/questions-page-layout/questions-page-layout.vue
new file mode 100644
index 000000000..85ccd33ad
--- /dev/null
+++ b/src/common-components/questions-page-layout/questions-page-layout.vue
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
diff --git a/src/common-components/textbox-question/textbox-question.spec.js b/src/common-components/textbox-question/textbox-question.spec.js
index 54e23e869..bfc65da16 100644
--- a/src/common-components/textbox-question/textbox-question.spec.js
+++ b/src/common-components/textbox-question/textbox-question.spec.js
@@ -33,6 +33,46 @@ describe("textboxQuestion.vue", () => {
expect(input.exists()).toBe(true);
});
+ it("Should return rounded-pill class", async () => {
+ // Act
+ const wrapper = shallowMount(textboxQuestion, {
+ global: {
+ directives: {
+ maska: maska,
+ },
+ },
+ mixins: [mockMixin],
+ propsData: {
+ cornerStyle: "rounded",
+ },
+ });
+
+ // Assert
+ const paragraph = wrapper.find("input");
+
+ expect(paragraph.attributes("class")).toContain("rounded-pill");
+ });
+
+ it.only("Should return form-control class", async () => {
+ // Act
+ const wrapper = shallowMount(textboxQuestion, {
+ global: {
+ directives: {
+ maska: maska,
+ },
+ },
+ mixins: [mockMixin],
+ propsData: {
+ questionAlignment: "text",
+ },
+ });
+
+ // Assert
+ const paragraph = wrapper.find("input");
+
+ expect(paragraph.attributes("class")).toContain("form-control");
+ });
+
it("Should render the 'questionText' data value as the label text when disableAutoFill is false.", async () => {
// Arrange
const wrapper = shallowMount(textboxQuestion, {
diff --git a/src/common-components/textbox-question/textbox-question.vue b/src/common-components/textbox-question/textbox-question.vue
index 62b605b7b..05d17dcd4 100644
--- a/src/common-components/textbox-question/textbox-question.vue
+++ b/src/common-components/textbox-question/textbox-question.vue
@@ -5,25 +5,33 @@
:aria-label="questionText"
class="form-label"
v-html="labelText">
-
+
+
+
+
{{ errorMessage }}
@@ -58,6 +66,9 @@ export default {
validationRules: String,
cmsWidgetName: String,
maxLength: String,
+ questionAlignment: String, // Left or center. Left is default.
+ cornerStyle: String, // Rounded or square. Square is default.
+ includeSearchIcon: Boolean,
},
setup(props) {
const propsClone = Object.assign({}, props);
@@ -148,6 +159,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);
diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js
index 0fade12fd..aeb38d792 100644
--- a/src/constants/endpoints.js
+++ b/src/constants/endpoints.js
@@ -76,7 +76,7 @@ const endpoints = {
},
LoadSession: {
url: "/order/api/v1/order/load-session",
- method: "POST",
+ method: "GET",
},
ValidateZip: {
url: "/location/api/v1/location/zip",
diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js
index 5b6800c86..1ef43bff0 100644
--- a/src/helpers/heritage-integration/cookie-helper.js
+++ b/src/helpers/heritage-integration/cookie-helper.js
@@ -21,6 +21,7 @@ export function updateOrCreateFunnelCookie() {
ReferralParentAccountNumber: store.getters.order.accountNumber,
HasDelayedClaimRegistration: wasClaimRegistrationDelayed,
SuppressConceptFunnel: shouldSuppressConceptFunnel,
+ SavedSessionId: store.getters.applicationUser.savedSessionId,
});
}
diff --git a/src/helpers/heritage-integration/order-helper.js b/src/helpers/heritage-integration/order-helper.js
index db95e0703..9a24e9c24 100644
--- a/src/helpers/heritage-integration/order-helper.js
+++ b/src/helpers/heritage-integration/order-helper.js
@@ -17,12 +17,8 @@ import { storeMutations } from "@/constants/store-mutations";
export async function loadSessionIfPresent() {
const funnelCookie = getFunnelCookie();
- // Do nothing if there is no cookie, correlation id, or referral number.
- if (
- funnelCookie == null ||
- funnelCookie.ReferralCorrelationId == null ||
- !funnelCookie.ReferralNumber
- ) {
+ // Do nothing if there is no cookie or session to use for loading.
+ if (funnelCookie == null || funnelCookie.SavedSessionId == null) {
return null;
}
@@ -33,15 +29,8 @@ export async function loadSessionIfPresent() {
return null;
}
- // Load referral if there is a cookie, and it doesn't indicate it needs a state reset.
- return (
- await loadSession(
- funnelCookie.ReferralNumber,
- funnelCookie.ReferralDate,
- funnelCookie.ReferralCorrelationId,
- funnelCookie.ReferralParentAccountNumber
- )
- ).data;
+ // Loads session including referral if there is a cookie, and it doesn't indicate it needs a state reset.
+ return (await loadSession(funnelCookie.SavedSessionId)).data;
}
/*
@@ -72,16 +61,13 @@ export async function saveSession() {
Calls API to load session given the referral number, referralDate, and referralCorrelationId
and returns the response.
*/
-async function loadSession(referralNumber, referralDate, referralCorrelationId, accountNumber) {
+async function loadSession(savedSessionId) {
// await the saveSessionPromise in the store to make sure we're loading up to date information
await store.getters.applicationUser.saveSessionPromise;
const response = await baseMixin.methods.dispatchStoreAction(
storeActions.LOAD_SESSION,
{
- referralNumber: referralNumber.toString(),
- referralDate: referralDate,
- referralCorrelationId: referralCorrelationId,
- accountNumber: accountNumber?.toString(),
+ savedSessionId: savedSessionId?.toString(),
},
false
);
diff --git a/src/helpers/heritage-integration/order-helper.spec.js b/src/helpers/heritage-integration/order-helper.spec.js
index 5ec0f4f69..74c911e05 100644
--- a/src/helpers/heritage-integration/order-helper.spec.js
+++ b/src/helpers/heritage-integration/order-helper.spec.js
@@ -24,6 +24,7 @@ describe("loadSessionIfPresent", () => {
ShouldResetState: testShouldResetState,
ReferralCorrelationId: "xxx",
ReferralNumber: "12345",
+ SavedSessionId: "aa115a05-e268-4eb4-a095-1d54b44f4a99",
};
document.cookie = `${cookieNames.FUNNEL_SESSION_INFO}=${JSON.stringify(
@@ -46,6 +47,7 @@ describe("loadSessionIfPresent", () => {
ShouldResetState: true,
ReferralCorrelationId: "xxx-xxx-xxx",
ReferralNumber: "12345",
+ SavedSessionId: "aa115a05-e268-4eb4-a095-1d54b44f4a99",
});
const mockData = {
@@ -103,6 +105,7 @@ describe("loadSessionIfPresent", () => {
ReferralNumber: 123456,
ReferralCorrelationId: "yyy-yyy-yyyy",
ReferralDate: new Date(),
+ SavedSessionId: "aa115a05-e268-4eb4-a095-1d54b44f4a99",
});
const mockData = {
diff --git a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue
index 003556727..9611965d8 100644
--- a/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue
+++ b/src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue
@@ -63,9 +63,7 @@ export default {
},
selectedVehicle() {
// this computed is only needed for the computed differentVehicleAlertBody text above
- return this.vehicles.find(
- ({ vin }) => vin === this.selectedVehicleVin[this.selectedVehicleVin.length - 1]
- );
+ return this.vehicles.find(({ vin }) => vin === this.selectedVehicleVin);
},
},
components: {
diff --git a/src/layouts/capability-questions/capability-questions.vue b/src/layouts/capability-questions/capability-questions.vue
index 9384a060b..67b95a707 100644
--- a/src/layouts/capability-questions/capability-questions.vue
+++ b/src/layouts/capability-questions/capability-questions.vue
@@ -1,61 +1,32 @@
-
-
diff --git a/src/layouts/molding-questions/molding-questions.vue b/src/layouts/molding-questions/molding-questions.vue
index 1b8b6da43..cfae7af71 100644
--- a/src/layouts/molding-questions/molding-questions.vue
+++ b/src/layouts/molding-questions/molding-questions.vue
@@ -1,57 +1,27 @@
-
-
diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue
index f9eae9311..9d1b54c66 100644
--- a/src/layouts/part-questions/part-questions.vue
+++ b/src/layouts/part-questions/part-questions.vue
@@ -1,57 +1,27 @@
-
-
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue
index 429075a40..e4e34f131 100644
--- a/src/layouts/vin-lookup/vin-lookup.vue
+++ b/src/layouts/vin-lookup/vin-lookup.vue
@@ -10,7 +10,11 @@
+
0;
},
- setupInitialData(glass, i, alreadyAnsweredQuestions, vm) {
- glass.key = glass.glassLocation + "-" + glass.glassName;
+ setupInitialData(glass, index, alreadyAnsweredQuestions, vm) {
const self = vm ?? this;
+
// clear answerData if no questions are already answered
if (!alreadyAnsweredQuestions) {
glass.answerData = null;
@@ -94,33 +93,39 @@ export default {
let answerString = "";
// loop through answeredQuestions for matches
- answeredGlass.answeredQuestions.forEach((aq) => {
- if (!aq.questionNum || !aq.selectedAnswerText) {
+ answeredGlass.answeredQuestions.forEach((answeredQuestion) => {
+ if (!answeredQuestion.questionNum || !answeredQuestion.selectedAnswerText) {
return;
}
// determine which answer was previously chosen
- const chosenAns = glass.questions[aq.questionNum - 1].answers.find((a) => {
+ const chosenAns = glass.questions[
+ answeredQuestion.questionNum - 1
+ ].answers.find((a) => {
return (
- a.answerText.toUpperCase() === aq.selectedAnswerText.toUpperCase()
+ a.answerText.toUpperCase() ===
+ answeredQuestion.selectedAnswerText.toUpperCase()
);
});
// set the answerString to use for answerSelected
if (chosenAns.nextQuestionSequence) {
- answerString = `${aq.questionNum}|nextQuestion|${chosenAns.nextQuestionSequence}|${chosenAns.answerText}`;
+ answerString = `${answeredQuestion.questionNum}|nextQuestion|${chosenAns.nextQuestionSequence}|${chosenAns.answerText}`;
} else {
- answerString = `${aq.questionNum}|answer|${chosenAns.answerResult}|${chosenAns.answerText}`;
+ answerString = `${answeredQuestion.questionNum}|answer|${chosenAns.answerResult}|${chosenAns.answerText}`;
}
// mark this question as answered (question-chain will read this)
- glass.questions[aq.questionNum - 1].answerSelected = answerString;
+ glass.questions[answeredQuestion.questionNum - 1].answerSelected =
+ answerString;
// mark this question as suppressed if needed (question-chain uses this)
- if (aq.suppressQuestion) {
- glass.questions[aq.questionNum - 1].suppressQuestion = true;
+ if (answeredQuestion.suppressThisQuestion) {
+ glass.questions[
+ answeredQuestion.questionNum - 1
+ ].suppressThisQuestion = true;
}
});
// advance the currentGlassIndex
- self.currentGlassIndex = i;
+ self.currentGlassIndex = index;
const answerResult = answeredGlass.partNum
? answeredGlass.partNum
@@ -135,20 +140,221 @@ export default {
}
});
- // Set up watch for each set of glass questions
- // (updated when all questions for a glass have been answered in question-chain)
- self.$watch(
- "selectedAnswers." + glass.glassLocation + "-" + glass.glassName,
- (newValue) => {
- if (newValue) {
- self.handleAnswerUpdates(newValue);
- }
- },
- { deep: true }
- );
-
return glass;
},
+ handleAnswerUpdates(answer, glassKey, 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,
+ }
+ ],
+ "index": 0
+ }
+ */
+
+ const self = vm ?? this;
+
+ // clear out any preloaded answers
+ self.selectedAnswers = {};
+
+ // loop through every answered question on the currently answered glass part
+ answer.answeredQuestions?.forEach((answeredQuestion) => {
+ /* answeredQuestion example format:
+ {
+ "questionText": "Is your Grand Cherokee the Laredo model?",
+ "selectedAnswerText": "Yes",
+ "questionNum": 1,
+ }
+ */
+
+ const answeredQuestionText = answeredQuestion.questionText.toUpperCase();
+ const answeredQuestionAnswer = answeredQuestion.selectedAnswerText.toUpperCase();
+
+ // HANDLE DUPLICATE QUESTIONS
+
+ // loop through all glass data
+ self.questionsData.forEach((glass, glassIndex) => {
+ /* glass example format:
+ {
+ "glassName": "Single",
+ "glassLocation": "Windshield",
+ "parts": null,
+ "questions": [
+ {
+ "questionSequence": 1,
+ "questionText": "Is your vehicle equipped with a black dotted pattern behind the rear view mirror, known as a third visor frit?",
+ "answers": [
+ {
+ "answerResult": "DW01537",
+ "answerText": "Yes",
+ "nextQuestionSequence": null
+ },
+ {
+ "answerResult": "DW01537b",
+ "answerText": "No",
+ "nextQuestionSequence": null
+ }
+ ]
+ }
+ ],
+ "answerKey": "Windshield-Single",
+ "answerData": null
+ }
+ */
+
+ // limit duplicate search to glass pieces that follow after the currently being answered glass piece
+ if (glassIndex > answer.index) {
+ let indexToSuppressTo;
+ // reset this glass piece, in case user is changing their previous answers
+ glass.answerData = null;
+ glass.isSuppressedPart = null;
+
+ // loop through this glass piece's questions, looking for a questionText match
+ glass.questions.forEach((question, questionIndex) => {
+ // clear out any previously set answers
+ question.answerSelected = null;
+
+ // clear or set suppressThisQuestion property for each question
+ if (indexToSuppressTo && questionIndex + 1 < indexToSuppressTo) {
+ question.suppressThisQuestion = true;
+ } else {
+ question.suppressThisQuestion = null;
+ }
+
+ // handle duplicate questions
+ if (question.questionText.toUpperCase() === answeredQuestionText) {
+ let matchedAnswer;
+
+ // handle matching answer in duplicated question
+ question.answers.forEach((ans) => {
+ if (ans.answerText.toUpperCase() === answeredQuestionAnswer) {
+ matchedAnswer = ans;
+ ans.selected = true;
+ } else {
+ ans.selected = null;
+ }
+ });
+
+ // handle duplicate's nextQuestion logic on other related questions
+ if (matchedAnswer.nextQuestionSequence) {
+ // clear any suppression on the nextQuestion
+ glass.questions[
+ matchedAnswer.nextQuestionSequence - 1
+ ].suppressThisQuestion = null;
+ // if the duplicate is 1ST question in array, set indexToSuppressTo
+ if (questionIndex === 0) {
+ if (
+ !indexToSuppressTo ||
+ matchedAnswer.nextQuestionSequence < indexToSuppressTo
+ ) {
+ indexToSuppressTo = matchedAnswer.nextQuestionSequence;
+ }
+ }
+ }
+
+ // update answers in this glass piece's questions with duplication logic modifications
+ glass.questions.forEach((q) => {
+ q.answers.forEach((a) => {
+ // revert any previously set nextQuestion logic modifications
+ if (
+ a.originalNextQuestionSequence ===
+ question.questionSequence
+ ) {
+ // restore original nextQuestionSequence
+ a.nextQuestionSequence = a.originalNextQuestionSequence;
+ self.originalNextQuestionSequence = null;
+ // restore original answerResult
+ if (a.originalAnswerResult) {
+ a.answerResult = a.originalAnswerResult;
+ a.originalAnswerResult = null;
+ }
+ }
+ // modify logic on any related questions
+ if (a.nextQuestionSequence === question.questionSequence) {
+ // update either nextQuestionSequence or answerResult
+
+ // update questions that lead to duplicated question
+ if (matchedAnswer.nextQuestionSequence) {
+ a.originalNextQuestionSequence =
+ a.nextQuestionSequence;
+ a.nextQuestionSequence =
+ matchedAnswer.nextQuestionSequence;
+ } else {
+ a.originalNextQuestionSequence =
+ a.nextQuestionSequence;
+ a.nextQuestionSequence = null;
+ a.originalAnswerResult =
+ a.originalAnswerResult || a.answerResult;
+ a.answerResult = matchedAnswer.answerResult;
+ }
+ }
+ });
+ });
+
+ // suppress current question
+ question.suppressThisQuestion = true;
+
+ // are there any questions left that are not suppressed?
+ const remainingQuestions = glass.questions.filter((q) => {
+ return !q.suppressThisQuestion;
+ });
+
+ if (remainingQuestions.length < 1) {
+ // this is the final answer for this glass piece
+
+ // mark this glass piece as completely answered by adding answerData
+ const answeredQuestionObj = {
+ questionText: question.questionText,
+ selectedAnswerText: matchedAnswer.answerText,
+ questionNum: question.questionSequence,
+ suppressThisQuestion: question.suppressThisQuestion,
+ };
+ // set the answerData (used as indicator that it has been already answered)
+ glass.answerData = {
+ answerResult: matchedAnswer.nextQuestionSequence
+ ? matchedAnswer.nextQuestionSequence
+ : matchedAnswer.answerResult,
+ answeredQuestions: [answeredQuestionObj],
+ };
+
+ // suppress this glass piece because it has an answer
+ glass.isSuppressedPart = true;
+ }
+ }
+ });
+
+ // Update key to force re-render of glass piece with duplicate question in case user changes previous related answer in the chain
+ self.questionsData[glassIndex].key =
+ self.questionsData[glassIndex].key + Date.now().toString();
+ }
+ });
+ });
+
+ // set final answer data for the current answered glass part
+ self.questionsData[answer.index].answerData = {
+ answerResult: answer.answerResult,
+ answeredQuestions: answer.answeredQuestions,
+ };
+
+ // this part has been fully answered, so advance to next part's question chain
+ for (let i = answer.index + 1; i < this.questionsData.length; i++) {
+ // if this part has not yet been fully answered, then make it the current part
+ if (!this.questionsData[i].answerData?.answerResult) {
+ this.currentGlassIndex = i;
+ break;
+ }
+ }
+ },
// Can't use `this` because navigateForward is also called from vin-pages-mixin
async navigateForward(partsOrQuestions, vm) {
const self = vm ?? this;
@@ -240,10 +446,16 @@ export default {
} else {
// if single parts only
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
+
// save to store lineItems.glassParts
self.$store.commit(storeMutations.UPDATE_GLASS_PARTS, collectedGlassParts);
- self.$refs.loadingModal.showModal();
+ if (self.$refs.questionsPage) {
+ self.$refs.questionsPage.showLoadingModal();
+ } else if (self.$refs.loadingModal) {
+ self.$refs.loadingModal.showModal();
+ }
+
navigateToHeritageFunnel();
}
},
diff --git a/src/mixins/vehicle-questions-mixin.spec.js b/src/mixins/vehicle-questions-mixin.spec.js
index 6f14cebdd..873614fc4 100644
--- a/src/mixins/vehicle-questions-mixin.spec.js
+++ b/src/mixins/vehicle-questions-mixin.spec.js
@@ -337,24 +337,6 @@ describe("vehicle-questions-mixin", () => {
});
describe("setupInitialData", () => {
- describe("should always", () => {
- test("return glass with new key attribute", async () => {
- // Arrange
- const { wrapper } = setupMocks({});
- const glass = {
- glassName: "Single",
- glassLocation: "Windshield",
- };
- const i = 0;
-
- // Act
- const returnedGlass = await wrapper.vm.setupInitialData(glass, i);
-
- // Assert
- expect(returnedGlass).toMatchObject({ key: "Windshield-Single" });
- });
- });
-
describe("if no alreadyAnsweredQuestions", () => {
test("should return glass with answerData of null", async () => {
// Arrange
@@ -430,6 +412,816 @@ describe("vehicle-questions-mixin", () => {
});
});
+ describe("handleAnswerUpdates", () => {
+ describe("selectedAnswers", () => {
+ test("should be cleared to be empty", () => {
+ // Arrange
+ const answer = {
+ answerResult: "DD11132",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "Yes",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.selectedAnswers = { test: "mockSelectedAnswers" };
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [],
+ answerData: "testAnswerData1",
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answer, "", wrapper.vm);
+
+ // Assert
+ expect(wrapper.vm.selectedAnswers).toMatchObject({});
+ });
+ });
+
+ describe("questions in glass parts that are after the answered glass", () => {
+ test("should have answerData cleared", () => {
+ // Arrange
+ const answer = {
+ answerResult: "DD11132",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "Yes",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [],
+ answerData: "testAnswerData1",
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [],
+ answerData: "testAnswerData2",
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answer, "", wrapper.vm);
+
+ // Assert
+ expect(wrapper.vm.questionsData[1].answerData).toEqual(null);
+ });
+ test("should have isSuppressedPart cleared", () => {
+ // Arrange
+ const answer = {
+ answerResult: "DD11132",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "Yes",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [],
+ answerData: "testAnswerData1",
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [],
+ answerData: "testAnswerData2",
+ isSuppressedPart: true,
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answer, "", wrapper.vm);
+
+ // Assert
+ expect(wrapper.vm.questionsData[1].isSuppressedPart).toEqual(null);
+ });
+ test("should set answerSelected for each glass part question to null ", () => {
+ // Arrange
+ const answer = {
+ answerResult: "DD11132",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "Yes",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [],
+ answerData: "testAnswerData1",
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText:
+ "Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 2,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 3,
+ },
+ ],
+ answerSelected: "456",
+ },
+ {
+ questionSequence: 2,
+ questionText:
+ "Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?",
+ answers: [
+ {
+ answerResult: "FW04848",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "FW04846",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ answerSelected: "789",
+ },
+ ],
+ answerData: "testAnswerData2",
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answer, "", wrapper.vm);
+
+ // Assert
+ expect(wrapper.vm.questionsData[1].questions[0].answerSelected).toEqual(null);
+ expect(wrapper.vm.questionsData[1].questions[1].answerSelected).toEqual(null);
+ });
+ });
+
+ describe("if there is a duplicate question", () => {
+ test("then the glass piece's key should be updated", () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ key: "testkey1",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ key: "testkey2",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+ const glassWithDuplicate = wrapper.vm.questionsData[1];
+
+ // Assert
+ expect(glassWithDuplicate.key).not.toBe("testkey2");
+ });
+
+ test("then that question should be supressed", () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+ const duplicateQuestion = wrapper.vm.questionsData[1].questions[0];
+
+ // Assert
+ expect(duplicateQuestion.suppressThisQuestion).toBeTruthy();
+ });
+
+ describe("and the duplicate has a nextQuestionSequence value", () => {
+ test("then the question set as nextQuestionSequence should not be suppressed", () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "ZZZTest duplicate question 1?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 2,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 3,
+ },
+ ],
+ },
+ {
+ questionSequence: 2,
+ questionText: "Test question 2?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ {
+ questionSequence: 3,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "345",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ suppressThisQuestion: true,
+ },
+ ],
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+ const nextQuestionAfterDuplicate = wrapper.vm.questionsData[1].questions[2];
+
+ // Assert
+ expect(nextQuestionAfterDuplicate.suppressThisQuestion).not.toBeTruthy();
+ });
+
+ test("then the nextQuestionSequence should be updated and the original value saved", () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test question 3?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test question 1?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 2,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 3,
+ },
+ ],
+ },
+ {
+ questionSequence: 2,
+ questionText: "Test question 2?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ {
+ questionSequence: 3,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 4,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 5,
+ },
+ ],
+ },
+ {
+ questionSequence: 4,
+ questionText: "Test question 4?",
+ answers: [
+ {
+ answerResult: "567",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "678",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ {
+ questionSequence: 5,
+ questionText: "Test question 5?",
+ answers: [
+ {
+ answerResult: "789",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "890",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+ const duplicatedQuestion = wrapper.vm.questionsData[1].questions[2];
+ const duplicatedQuestionAnswer = duplicatedQuestion.answers.filter((a) => {
+ return a.selected;
+ });
+ const answerToTest = wrapper.vm.questionsData[1].questions[0].answers.filter(
+ (a) => {
+ return a.originalNextQuestionSequence;
+ }
+ );
+
+ // Assert
+ expect(answerToTest[0].originalNextQuestionSequence).toEqual(
+ duplicatedQuestion.questionSequence
+ );
+ expect(answerToTest[0].nextQuestionSequence).toEqual(
+ duplicatedQuestionAnswer[0].nextQuestionSequence
+ );
+ });
+
+ describe("and the duplicate was the first question for that part", () => {
+ test("then any questions up to the nextQuestionSequence value should be marked as suppressed", () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test duplicate question 1?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test duplicate question 1?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 2,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 3,
+ },
+ ],
+ },
+ {
+ questionSequence: 2,
+ questionText: "Test question 2?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ {
+ questionSequence: 3,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "345",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ ];
+
+ // Act
+ wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+
+ // Assert
+ expect(
+ wrapper.vm.questionsData[1].questions[0].suppressThisQuestion
+ ).toBeTruthy();
+ expect(
+ wrapper.vm.questionsData[1].questions[1].suppressThisQuestion
+ ).toBeTruthy();
+ expect(
+ wrapper.vm.questionsData[1].questions[2].suppressThisQuestion
+ ).toBeFalsy();
+ });
+ });
+ });
+
+ describe("and the duplicate has an answerResult", () => {
+ test("then any questions in the same glass piece that lead to the duplicate should be modified to just provide the duplicate's answerResult", async () => {
+ // Arrange
+ const answerNo = {
+ answerResult: "456",
+ answeredQuestions: [
+ {
+ questionText: "Test question 3?",
+ selectedAnswerText: "No",
+ questionNum: 1,
+ },
+ ],
+ index: 0,
+ };
+ const { wrapper } = setupMocks({});
+
+ wrapper.vm.questionsData = [
+ {
+ glassLocation: "Windshield",
+ glassName: "Single",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ {
+ glassLocation: "Driver",
+ glassName: "Front",
+ questions: [
+ {
+ questionSequence: 1,
+ questionText: "Test question 1?",
+ answers: [
+ {
+ answerResult: "",
+ answerText: "Yes",
+ nextQuestionSequence: 2,
+ },
+ {
+ answerResult: "",
+ answerText: "No",
+ nextQuestionSequence: 3,
+ },
+ ],
+ },
+ {
+ questionSequence: 2,
+ questionText: "Test question 2?",
+ answers: [
+ {
+ answerResult: "123",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "234",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ {
+ questionSequence: 3,
+ questionText: "Test question 3?",
+ answers: [
+ {
+ answerResult: "345",
+ answerText: "Yes",
+ nextQuestionSequence: null,
+ },
+ {
+ answerResult: "456",
+ answerText: "No",
+ nextQuestionSequence: null,
+ },
+ ],
+ },
+ ],
+ },
+ ];
+
+ // Act
+ await wrapper.vm.handleAnswerUpdates(answerNo, "", wrapper.vm);
+
+ const questionsToTest = wrapper.vm.questionsData[1].questions;
+ const answerLeadingToDuplicate = questionsToTest[0].answers[1];
+ const duplicateQuestion = questionsToTest[2];
+ const answerInDuplicateQuestion = duplicateQuestion.answers.filter((a) => {
+ return a.selected;
+ });
+
+ // Assert
+ expect(answerLeadingToDuplicate.answerResult).toEqual(
+ answerInDuplicateQuestion[0].answerResult
+ );
+ expect(answerLeadingToDuplicate.originalAnswerResult).toBeFalsy();
+ expect(answerLeadingToDuplicate.nextQuestionSequence).toEqual(null);
+ expect(answerLeadingToDuplicate.originalNextQuestionSequence).toEqual(
+ duplicateQuestion.questionSequence
+ );
+ });
+ });
+ });
+ });
+
describe("navigateForward", () => {
describe("should go to parts-questions", () => {
test("single glass location has part question => go to parts-questions", async () => {
diff --git a/src/store/index.js b/src/store/index.js
index 34ec8a8a9..9c31bc9c8 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -303,13 +303,13 @@ export const mutations = {
state.applicationUser.saveSessionPromise = null;
},
// Misc Mutations
- updateStateWithOrderInformation(state, orderInformation) {
- state.order.referralNumber = orderInformation.referralNumber;
- state.order.referralDate = orderInformation.referralDate;
- state.order.referralCorrelationId = orderInformation.referralCorrelationId;
- state.order.eon = orderInformation.eon;
+ updateStateWithOrderInformation(state, sessionInformation) {
+ state.order.referralNumber = sessionInformation.order.referralNumber;
+ state.order.referralDate = sessionInformation.order.referralDate;
+ state.order.referralCorrelationId = sessionInformation.order.referralCorrelationId;
+ state.order.eon = sessionInformation.order.eon;
- if (state.order.vehicle.vin !== orderInformation.vehicle?.vin) {
+ if (state.order.vehicle.vin !== sessionInformation.order.vehicle?.vin) {
state.applicationUser.pageData[fmgPageValues.PART_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.VEHICLE_PARTS] = null;
state.applicationUser.pageData[fmgPageValues.MOLDING_QUESTIONS] = null;
@@ -317,44 +317,51 @@ export const mutations = {
}
state.order.vehicle = Object.assign(state.order.vehicle, {
- year: orderInformation.vehicle?.year,
- make: orderInformation.vehicle?.make,
- model: orderInformation.vehicle?.model,
- style: orderInformation.vehicle?.style,
- vin: orderInformation.vehicle?.vin,
- carId: orderInformation.vehicle?.carId,
- category: orderInformation.vehicle?.category,
- imageUrl: orderInformation.vehicle?.imageUrl,
- imageVifNumber: orderInformation.vehicle?.imageVifNumber,
- imageColor: orderInformation.vehicle?.imageVifColor,
+ year: sessionInformation.order.vehicle?.year,
+ make: sessionInformation.order.vehicle?.make,
+ model: sessionInformation.order.vehicle?.model,
+ style: sessionInformation.order.vehicle?.style,
+ vin: sessionInformation.order.vehicle?.vin,
+ carId: sessionInformation.order.vehicle?.carId,
+ category: sessionInformation.order.vehicle?.category,
+ imageUrl: sessionInformation.order.vehicle?.imageUrl,
+ imageVifNumber: sessionInformation.order.vehicle?.imageVifNumber,
+ imageColor: sessionInformation.order.vehicle?.imageVifColor,
registration: {
- firstName: orderInformation.vehicle.registration.firstName,
- lastName: orderInformation.vehicle.registration.lastName,
- address: orderInformation.vehicle.registration.streetAddress,
- city: orderInformation.vehicle.registration.city,
- state: orderInformation.vehicle.registration.state,
- zipCode: orderInformation.vehicle.registration.zipCode,
- licensePlate: orderInformation.vehicle.registration.licensePlateNumber,
+ firstName: sessionInformation.order.vehicle.registration.firstName,
+ lastName: sessionInformation.order.vehicle.registration.lastName,
+ address: sessionInformation.order.vehicle.registration.streetAddress,
+ city: sessionInformation.order.vehicle.registration.city,
+ state: sessionInformation.order.vehicle.registration.state,
+ zipCode: sessionInformation.order.vehicle.registration.zipCode,
+ licensePlate: sessionInformation.order.vehicle.registration.licensePlateNumber,
},
});
- state.order.damage.glassToReplace = orderInformation.damage.glassToReplace;
- state.order.damage.isRepair = orderInformation.damage.isRepair;
- state.order.damage.numberOfChips = orderInformation.damage.numberOfChips;
+ state.order.damage.glassToReplace = sessionInformation.order.damage.glassToReplace;
+ state.order.damage.isRepair = sessionInformation.order.damage.isRepair;
+ state.order.damage.numberOfChips = sessionInformation.order.damage.numberOfChips;
- state.order.lineItems.glassParts = orderInformation.parts;
- state.order.accountNumber = orderInformation.accountNumber;
- (state.order.serviceLocation.address = orderInformation.serviceLocation.streetAddress),
- (state.order.serviceLocation.city = orderInformation.serviceLocation.city),
- (state.order.serviceLocation.state = orderInformation.serviceLocation.state),
- (state.order.serviceLocation.zipCode = orderInformation.serviceLocation.zipCode);
+ state.order.lineItems.glassParts = sessionInformation.order.lineItems.parts;
+ state.order.accountNumber = sessionInformation.order.accountNumber;
+ state.order.providerNumber = sessionInformation.order.providerNumber;
+ (state.order.serviceLocation.address =
+ sessionInformation.order.serviceLocation.streetAddress),
+ (state.order.serviceLocation.city = sessionInformation.order.serviceLocation.city),
+ (state.order.serviceLocation.state = sessionInformation.order.serviceLocation.state),
+ (state.order.serviceLocation.zipCode =
+ sessionInformation.order.serviceLocation.zipCode);
- state.order.payment.isInsurance = orderInformation.IsInsuranceOrder;
+ state.order.payment.isInsurance = sessionInformation.order.payment.isInsurance;
state.order.payment.insuranceCoverage.isVerified =
- orderInformation?.insuranceInfo.coverageVerified;
+ sessionInformation?.order.payment.insuranceCoverage.isVerified;
- state.order.customer.emailAddress = orderInformation.customer.emailAddress;
- state.applicationUser.experiments = orderInformation.experiments;
+ state.order.customer.emailAddress = sessionInformation.order.customer.emailAddress;
+ state.order.existingPromoCode = sessionInformation.order.existingPromoCode;
+ state.applicationUser.experiments = sessionInformation.applicationUser.experiments;
+ state.applicationUser.crmCustomerId = sessionInformation.applicationUser.crmCustomerId;
+ state.applicationUser.pageData = sessionInformation.applicationUser.pageData;
+ state.applicationUser.lastPage = sessionInformation.applicationUser.lastPage;
},
updateExperiments(state, experiments) {
state.applicationUser.experiments = experiments;
@@ -984,17 +991,12 @@ export const actions = {
},
});
},
- loadSession(context, { referralNumber, referralDate, referralCorrelationId, accountNumber }) {
+ loadSession(context, { savedSessionId }) {
return globalMethods
.callHttpClient({
method: endpoints.LoadSession.method,
- endpoint: endpoints.LoadSession.url,
- payload: {
- referralNumber: referralNumber?.toString(),
- referralDate: referralDate,
- referralCorrelationId: referralCorrelationId,
- accountNumber: accountNumber?.toString(),
- },
+ endpoint:
+ endpoints.LoadSession.url + "?savedSessionId=" + savedSessionId?.toString(),
})
.then((response) => {
// Flatten location and name properties
@@ -1409,6 +1411,12 @@ function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
function convertGlassPieceNamingForApi(glassArray) {
if (!glassArray) return [];
+
+ // check if array already converted. (likely when a session has been saved previously and then reloaded)
+ if (glassArray[0].location !== undefined) {
+ return glassArray;
+ }
+
const converted = [];
glassArray.forEach((glass) => {
converted.push({
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index eb0807581..063dedd76 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -203,34 +203,65 @@ describe("Mutations", () => {
expect(storeState.applicationUser.pageData["vehicle-year"]).toEqual({});
});
- it("updateStateWithOrderInformation, should set order information in state", () => {
+ it("updateStateWithSessonInformation, should set session information in state", () => {
// Arrange
const storeState = state;
// Act
mutations.updateStateWithOrderInformation(storeState, {
- referralNumber: 123,
- referralDate: new Date().toUTCString(),
- referralCorrelationId: "xxx-xxx-xxx",
- vehicle: {
- year: "2019",
- make: "Acura",
- model: "ILX",
- style: "4 DOOR SEDAN",
- carId: "C0000001",
- category: "CAR",
- registration: {},
+ order: {
+ referralNumber: 123,
+ referralDate: new Date().toUTCString(),
+ referralCorrelationId: "xxx-xxx-xxx",
+ vehicle: {
+ year: "2019",
+ make: "Acura",
+ model: "ILX",
+ style: "4 DOOR SEDAN",
+ carId: "C0000001",
+ category: "CAR",
+ registration: {},
+ },
+ damage: {
+ glassToReplace: ["Windshield"],
+ isRepair: false,
+ numberOfChips: 0,
+ },
+ lineItems: {
+ glassParts: null,
+ },
+ payment: {
+ insuranceCoverage: {
+ isVerified: false,
+ },
+ isInsurance: false,
+ },
+ parts: [],
+ accountNumber: "123456789",
+ insuranceInfo: {},
+ serviceLocation: {},
+ customer: {},
},
- damage: {
- glassToReplace: ["Windshield"],
- isRepair: false,
- numberOfChips: 0,
+ applicationUser: {
+ experiments: [
+ {
+ universeName: "Concept Funnel Test With Rules",
+ universeId: 463,
+ testName: "Concept Dev Test",
+ testId: 392,
+ variationName: "Concept Test Variation",
+ variationId: 1133,
+ isActive: false,
+ isExposed: true,
+ userPartitionNumber: 84,
+ assignmentId: 12211739,
+ settings: {
+ someKey: "false",
+ sampleSetting: "Hi, my name is Vidya",
+ },
+ },
+ ],
},
- parts: [],
- accountNumber: "123456789",
- insuranceInfo: {},
- serviceLocation: {},
- customer: {},
});
// Assert
@@ -640,9 +671,7 @@ describe("Actions", () => {
// Act
const response = await actions.loadSession(context, {
- referralNumber: "123",
- referralDate: new Date().toUTCString(),
- referralCorrelationId: "xxx-xxx-xxx",
+ savedSessionId: "",
});
// Assert
@@ -667,9 +696,7 @@ describe("Actions", () => {
// Act
const response = await actions.loadSession(context, {
- referralNumber: "123",
- referralDate: new Date().toUTCString(),
- referralCorrelationId: "xxx-xxx-xxx",
+ savedSessionId: "",
});
// Assert
@@ -694,9 +721,7 @@ describe("Actions", () => {
// Act
const response = await actions.loadSession(context, {
- referralNumber: "123",
- referralDate: new Date().toUTCString(),
- referralCorrelationId: "xxx-xxx-xxx",
+ savedSessionId: "",
});
// Assert
diff --git a/src/styles/common-error-styles.scss b/src/styles/common-error-styles.scss
index d497ae6ce..a30ee8996 100644
--- a/src/styles/common-error-styles.scss
+++ b/src/styles/common-error-styles.scss
@@ -1,15 +1,42 @@
html {
.has-error {
+ // START HOVER
+ &.list-button-horizontal,
&.list-button,
- &.list-card,
- &.list-button-horizontal {
+ &.list-button.list-group,
+ &.list-card {
border: 1px solid $red;
+ position: relative;
+ z-index: 4;
.button-content {
border: none;
}
+
+ &:hover {
+ @include box-shadow-hover($red-200);
+ z-index: 5;
+ }
+ input[type="radio"]:focus + .list-button-content {
+ box-shadow: 0 0 0 2.5px $red;
+ }
}
+ &.ui-radio {
+ &:hover {
+ input[type="radio"],
+ input[type="checkbox"] {
+ @include box-shadow-hover($red-200);
+ }
+ }
+ }
+ .form-check-input {
+ &:focus {
+ box-shadow: 0 0 0 2.5px $red;
+ }
+ }
+ // END HOVER
+
&.list-button,
&.list-card {
color: $red;
@@ -22,27 +49,11 @@ html {
box-shadow: 0 0 0 1px $red;
}
&:hover {
- box-shadow: 0px 0px 0px 4px $red-200;
border-radius: 0.5rem;
}
- label {
- border: 1px solid $red;
- border-radius: 0.5rem;
- }
- label:hover {
- box-shadow: 0px 0px 0px 4px $red-200;
- border-radius: 10px;
- border: 1px solid $red;
- }
}
&.list-button-horizontal {
color: $red;
- label {
- border: 1px solid $red;
- &:hover {
- box-shadow: 0px 0px 0px 4px $red-200;
- }
- }
input[type="checkbox"]:focus + label,
input[type="radio"]:focus + label {
box-shadow: 0 0 1px $red;
@@ -75,23 +86,21 @@ html {
}
&.textbox-question,
&.dropdown-question {
- input:hover {
- box-shadow: 0px 0px 0px 4px $red-200;
- border-radius: 0.5rem;
- border: 1px solid $red;
- }
- input:focus {
- box-shadow: 0 0 0 2.5px $red;
- }
p {
color: $red;
}
input,
select {
- border: 1px solid transparent;
- box-shadow: 0 0 0 1px $red;
+ border: 1px solid $red;
&:focus {
border: 1px solid transparent;
+ box-shadow: 0 0 0 2.5px $red;
+ }
+
+ &:hover {
+ box-shadow: 0px 0px 0px 4px $red-200;
+ border-radius: 0.5rem;
+ border: 1px solid $red;
}
}
select {
diff --git a/src/styles/mixins/customMixins.scss b/src/styles/mixins/customMixins.scss
index 8620968f0..d0670ad6c 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-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..dbffa5b05
--- /dev/null
+++ b/src/styles/shared-input-button-styles.scss
@@ -0,0 +1,15 @@
+.base-input-button {
+ &:not(.has-error):hover {
+ cursor: pointer;
+
+ &.list-button,
+ &.list-button-horizontal,
+ &.list-card {
+ &:not(.selected) {
+ position: relative;
+ z-index: 4;
+ @include box-shadow-hover($blue-300);
+ }
+ }
+ }
+}
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 7d7f52b4e..df3a468ad 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 @@
@@ -88,18 +88,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..33df5568a 100644
--- a/src/ux-components/list-button/list-button.vue
+++ b/src/ux-components/list-button/list-button.vue
@@ -1,7 +1,7 @@