diff --git a/src/constants/error-messages.js b/src/constants/error-messages.js
index 4326a5412..45841f21f 100644
--- a/src/constants/error-messages.js
+++ b/src/constants/error-messages.js
@@ -18,6 +18,8 @@ const errorMessages = {
LAST_NAME_REQUIRED: "Please enter your last name",
EMAIL_ADDRESS_REQUIRED: "Please enter your email address",
EMAIL_ADDRESS_FORMAT: "Please enter a valid email address",
+ EMAIL_SMS_REQUIRED: "Please enter your mobile phone number or email",
+ EMAIL_SMS_FORMAT: "Please enter a valid mobile phone number or email",
SERVICE_ZIP_REQUIRED: "Please enter your service ZIP",
SERVICE_ZIP_FORMAT: "Please enter a valid service ZIP",
VIN_REQUIRED: "Please enter your VIN",
diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js
index ec6b0db0c..4750f1641 100644
--- a/src/constants/store-actions.js
+++ b/src/constants/store-actions.js
@@ -1,6 +1,7 @@
const storeActions = {
// Content Actions
GET_PAGE_DATA: "getPageData",
+ SAVE_PAGE_DATA: "savePageData",
// Vehicle Actions
GET_VEHICLE_YEARS: "getVehicleYears",
@@ -54,7 +55,7 @@ const storeActions = {
GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS: "getRecalPartsAndSaveToLineItems",
// Analytics
- LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
+ LOG_EXPERIMENT_EXPOSURE_AND_UPDATE_STORE: "logExperimentExposureAndUpdateStore",
LOG_PAGE_VIEW: "logPageView",
LOG_CUSTOM_EVENT: "logCustomEvent",
INITIALIZE_SESSION: "initializeSession",
@@ -77,6 +78,7 @@ const storeActions = {
SAVE_SCHEDULE: "saveSchedule",
SAVE_EMAIL: "saveEmail",
SAVE_PHONE_NUMBER: "savePhoneNumber",
+ SAVE_IS_SMS_OPT_IN: "saveIsSmsOptIn",
SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: "saveRegistrationLicensePlateLookup",
SAVE_VIN: "saveVin",
SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup",
diff --git a/src/constants/store-mutations.js b/src/constants/store-mutations.js
index 0836beb06..49ad6f507 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -40,6 +40,7 @@ const storeMutations = {
// CUSTOMER MUTATIONS
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
UPDATE_CUSTOMER_PHONE_NUMBER: "updateCustomerPhoneNumber",
+ UPDATE_CUSTOMER_IS_SMS_OPT_IN: "updateCustomerIsSmsOptin",
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
// ORDER MUTATIONS
diff --git a/src/fmg-components/save-progress-modal-question/save-progress-modal-question.vue b/src/fmg-components/save-progress-modal-question/save-progress-modal-question.vue
index 27ca1f479..c6e31b781 100644
--- a/src/fmg-components/save-progress-modal-question/save-progress-modal-question.vue
+++ b/src/fmg-components/save-progress-modal-question/save-progress-modal-question.vue
@@ -158,8 +158,8 @@ export default {
box-shadow: none;
}
&:focus-visible span {
- outline: 2px solid #005FCC;
- border-radius: .25rem;
+ outline: 2px solid #005fcc;
+ border-radius: 0.25rem;
}
&.delay {
// fixes flicker while transitioning between states
diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue
index 55d8a0499..e069ee48d 100644
--- a/src/layouts/address-lookup/address-lookup.vue
+++ b/src/layouts/address-lookup/address-lookup.vue
@@ -18,7 +18,7 @@
@@ -59,12 +59,12 @@ import textBlock from "@/digital-components/text-block/text-block";
// DEFINE VALIDATION RULES
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
defineRule("last-name-required", required(errorMessages.LAST_NAME_REQUIRED));
-defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
+defineRule("email-sms-required", required(errorMessages.EMAIL_SMS_REQUIRED));
defineRule(
- "email-address-format",
+ "email-sms-format",
regex(
- /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
- errorMessages.EMAIL_ADDRESS_FORMAT
+ /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
+ errorMessages.EMAIL_SMS_FORMAT
)
);
@@ -84,7 +84,7 @@ export default {
},
firstName: "",
lastName: "",
- emailAddress: "",
+ emailOrSms: "",
},
}),
},
diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue
index 0739a9af6..804ed5608 100644
--- a/src/layouts/confirmation/confirmation.vue
+++ b/src/layouts/confirmation/confirmation.vue
@@ -121,9 +121,9 @@ export default {
const partsOrQuestions = orderFromStore.damage?.partQuestionAnswers;
if (partsOrQuestions) {
- partsOrQuestions.forEach(pqa => {
+ partsOrQuestions.forEach((pqa) => {
const payloadPartQuestions = [];
- pqa.answeredQuestions.forEach(answer => {
+ pqa.answeredQuestions.forEach((answer) => {
payloadPartQuestions.push({
questionSeq: answer?.questionNum,
questionText: answer?.questionText,
diff --git a/src/layouts/estimate/estimate.vue b/src/layouts/estimate/estimate.vue
index 6a85ae349..b9fdf1958 100644
--- a/src/layouts/estimate/estimate.vue
+++ b/src/layouts/estimate/estimate.vue
@@ -145,6 +145,20 @@ export default {
vm.setCmsContent(resultMap.cmsContent);
if (store.getters.externalParameterState?.isExternalParameter) {
+ if (store.getters.externalParameterCustomer?.phoneNumber) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_PHONE_NUMBER,
+ store.getters.externalParameterCustomer.phoneNumber,
+ false
+ );
+
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_IS_SMS_OPT_IN,
+ true,
+ false
+ );
+ }
+
if (store.getters.externalParameterEstimate.vinSelection) {
vm.selectedVinLookupMethod = vinPagesMixin.methods.getVinlookupMethod(
store.getters.externalParameterEstimate.vinSelection
diff --git a/src/layouts/insurance-company/insurance-company.vue b/src/layouts/insurance-company/insurance-company.vue
index 79e238d47..452484e48 100644
--- a/src/layouts/insurance-company/insurance-company.vue
+++ b/src/layouts/insurance-company/insurance-company.vue
@@ -16,6 +16,13 @@
v-model="parentAccountNumber"
:originalList="originalList" />
+
diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js
index 93aee887a..2d4b729d8 100644
--- a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js
+++ b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js
@@ -68,7 +68,7 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({ emailAddress: mockEmail });
// ACT
- const customerEmail = wrapper.vm.getEmailFromStore();
+ const customerEmail = wrapper.vm.getEmailOrSmsFromStore();
// Assert
expect(customerEmail).toEqual(mockEmail);
@@ -665,6 +665,7 @@ function setupMocks({
},
store: {
getters: {
+ emailOrSms: emailAddress,
vehicle: {
registration: {
licensePlate: licensePlate,
diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue
index b374e8bb6..e1b3f721e 100644
--- a/src/layouts/license-plate-lookup/license-plate-lookup.vue
+++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue
@@ -28,10 +28,10 @@
@@ -110,17 +110,18 @@ import { Form, defineRule } from "vee-validate";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
+import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
defineRule("registration-zip-required", required(errorMessages.REGISTRATION_ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
-defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
+defineRule("email-sms-required", required(errorMessages.EMAIL_SMS_REQUIRED));
defineRule(
- "email-address-format",
+ "email-sms-format",
regex(
- /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
- errorMessages.EMAIL_ADDRESS_FORMAT
+ /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
+ errorMessages.EMAIL_SMS_FORMAT
)
);
@@ -155,7 +156,7 @@ export default {
return {
licensePlate: this.getLicensePlateFromStore(),
registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode,
- email: this.getEmailFromStore(),
+ emailOrSms: this.getEmailOrSmsFromStore(),
serviceZipCode: this.getServiceZipFromStore(),
displayNonServiceableZipAlert: false,
displayVinNotFoundAlert: false,
@@ -193,8 +194,8 @@ export default {
getRegistrationZipFromStore() {
return this.$store.getters.vehicle.registration.zipCode;
},
- getEmailFromStore() {
- return this.$store.getters.order.customer.emailAddress;
+ getEmailOrSmsFromStore() {
+ return this.$store.getters.emailOrSms;
},
getServiceZipFromStore() {
return this.$store.getters.order.serviceLocation.zipCode;
@@ -310,7 +311,21 @@ export default {
false
);
- await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.email, false);
+ if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
+ const phone = this.emailOrSms.replace(/[()]/g, "");
+ await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
+ } else {
+ await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
+ }
+
+ await this.dispatchStoreAction(
+ storeActions.SAVE_PAGE_DATA,
+ {
+ page: fmgPageValues.EMAIL_SMS_PAGES,
+ data: { emailOrSmsValue: this.emailOrSms },
+ },
+ false
+ );
await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
diff --git a/src/layouts/molding-questions/molding-questions.vue b/src/layouts/molding-questions/molding-questions.vue
index 1bcc3d7a8..2c5f5a7c3 100644
--- a/src/layouts/molding-questions/molding-questions.vue
+++ b/src/layouts/molding-questions/molding-questions.vue
@@ -78,6 +78,20 @@ export default {
);
}
+ if (store.getters.externalParameterCustomer?.phoneNumber) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_PHONE_NUMBER,
+ store.getters.externalParameterCustomer.phoneNumber,
+ false
+ );
+
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_IS_SMS_OPT_IN,
+ true,
+ false
+ );
+ }
+
baseMixin.methods.ResetExternalParamsAndHideModal();
}
});
diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue
index f905e86c7..d60ddbb70 100644
--- a/src/layouts/part-questions/part-questions.vue
+++ b/src/layouts/part-questions/part-questions.vue
@@ -79,6 +79,21 @@ export default {
false
);
}
+
+ if (store.getters.externalParameterCustomer?.phoneNumber) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_PHONE_NUMBER,
+ store.getters.externalParameterCustomer.phoneNumber,
+ false
+ );
+
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_IS_SMS_OPT_IN,
+ true,
+ false
+ );
+ }
+
baseMixin.methods.ResetExternalParamsAndHideModal();
}
});
diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js
index deca0d6d1..522bc4f2e 100644
--- a/src/layouts/quote/quote.spec.js
+++ b/src/layouts/quote/quote.spec.js
@@ -577,6 +577,56 @@ describe("quote.vue", () => {
//Assert
expect(wrapper.vm.isInsuranceSelected).toBe(false);
});
+ test("should default to cash if isCashSelected is true, despite all other checks pointing to insurance selection", async () => {
+ // Also needs no query parameter or previous selection in store to be present
+ //Arrange
+
+ store.getters = {
+ lineItems: {
+ glassParts: ["item", "item2"],
+ },
+ applicationUser: {
+ experiments: [],
+ },
+ order: {
+ lineItems: {
+ glassParts: ["item", "item2"],
+ },
+ payment: {
+ isInsurance: true,
+ },
+ customer: {
+ emailAddress: "test@test.com",
+ },
+ serviceLocation: {
+ state: null,
+ },
+ },
+ vehicle: {
+ cardId: "123",
+ },
+ experimentSettings: {
+ settingName: "SERVICE_PACKAGE_DISCOUNT",
+ },
+ };
+ mockTierOnePrice = 505;
+ const { wrapper } = setupMocks({});
+
+
+ //Act
+ await quote.beforeRouteEnter.call(
+ wrapper.vm,
+ { query: { fmgPage: "quote",
+ isInsuranceSelected: true,
+ isCashSelected: true,
+ } },
+ undefined,
+ (c) => c(wrapper.vm)
+ );
+
+ //Assert
+ expect(wrapper.vm.isInsuranceSelected).toBe(false);
+ });
test("should default to insurance if total economy package price is over $500", async () => {
// Also needs no query parameter or previous selection in store to be present
//Arrange
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue
index 4428f6e40..20dc16304 100644
--- a/src/layouts/quote/quote.vue
+++ b/src/layouts/quote/quote.vue
@@ -328,6 +328,10 @@ export default {
}
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
+ // query param checked here is set on insurance-selection "Pay on my own" link click
+ if (to.query?.isCashSelected || to.query?.iscashselected) {
+ return false;
+ }
const serviceLocationState = store.getters.order.serviceLocation.state;
// usually true when returning from heritage but can be false when returning from heritage on a save quote
diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js
index 863a04c82..91f26b64d 100644
--- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js
+++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.spec.js
@@ -203,7 +203,7 @@ describe("mobile-location-modal-questions.vue", () => {
expect(wrapper.vm.$refs.MobileLocationModalWidget.openModal).toHaveBeenCalled();
});
- it("Should emit update:modelValue on setMobileLocation for a valid address and vehicle protection answer", async () => {
+ it("Should emit updated-mobile-location-questions on setMobileLocation for a valid address and vehicle protection answer", async () => {
// Arrange
const mobileLocationQuestions = {
addressQuestions: {
@@ -240,17 +240,26 @@ describe("mobile-location-modal-questions.vue", () => {
});
wrapper.vm.$refs.MobileLocationModalWidget.closeModal = jest.fn();
+ // Mock the emitEvent function
+ wrapper.vm.emitEvent = jest.fn(async (eventName, payload) => {
+ return new Promise((resolve) => {
+ wrapper.vm.$emit(eventName, newMobileLocationQuestions, resolve);
+ resolve(newMobileLocationQuestions);
+ });
+ });
// Act
wrapper.vm.internalModel = newMobileLocationQuestions;
+
await wrapper.vm.setMobileLocation();
- let expectedEmit = [[newMobileLocationQuestions]];
-
// Assert
- expect(wrapper.emitted("update:modelValue")).toEqual(expectedEmit);
+ expect(wrapper.emitted()["updated-mobile-location-questions"]).toBeTruthy();
+ expect(wrapper.emitted()["updated-mobile-location-questions"][0][0]).toBe(
+ newMobileLocationQuestions
+ );
});
- it("Should not emit update:modelValue on setMobileLocation for an invalid address zip code", async () => {
+ it("Should not emit updated-mobile-location-questions on setMobileLocation for an invalid address zip code", async () => {
// Arrange
const mobileLocationQuestions = {
addressQuestions: {
@@ -293,7 +302,7 @@ describe("mobile-location-modal-questions.vue", () => {
await wrapper.vm.setMobileLocation();
// Assert
- expect(wrapper.emitted("update:modelValue")).not.toBeTruthy();
+ expect(wrapper.emitted("updated-mobile-location-questions")).not.toBeTruthy();
});
it("Should display invalid zip alert for invalid address zip inputs", async () => {
diff --git a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
index d88bd53e2..dadbaff8b 100644
--- a/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
+++ b/src/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue
@@ -98,6 +98,7 @@ export default {
"updated-contains-military-base",
"updated-bill-to-account-number",
"mobileLocationSelected",
+ "updated-mobile-location-questions",
],
data() {
return {
@@ -251,10 +252,15 @@ export default {
if (!zipCodeData.isValid) {
this.displayInvalidZipAlert = true;
this.resetModalButtonStyle();
+ return;
} else if (zipCodeData.state != this.internalModel.addressQuestions.state) {
this.displayMismatchStateAndZipAlert = true;
this.resetModalButtonStyle();
- } else {
+ return;
+ } else if (
+ this.internalModel.addressQuestions.zipCode !==
+ this.modelValue.addressQuestions.zipCode
+ ) {
// retrieve mobile fee part
const serviceZipCode = this.internalModel.addressQuestions.zipCode;
const mobileFeePart = await getPricedMobileFeePart(
@@ -279,13 +285,17 @@ export default {
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
this.$emit("updated-mobile-ctu", zipCodeData.zipCodeCtu);
this.$emit("updated-bill-to-account-number", billToAccountNumber);
-
- // update the page level model
- this.$emit("update:modelValue", this.internalModel);
-
- //Page advance to Schedule page
- this.$emit("mobileLocationSelected");
}
+ // update the page level model
+ await this.emitEvent("updated-mobile-location-questions", this.internalModel);
+
+ this.$emit("mobileLocationSelected");
+ },
+ //creating emitEvent function to raise events with resolve callback to handle events sequencing
+ async emitEvent(eventName, payload) {
+ return new Promise((resolve) => {
+ this.$emit(eventName, payload, resolve);
+ });
},
},
watch: {
diff --git a/src/layouts/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js
index 68d2e948f..3cd5d93e1 100644
--- a/src/layouts/service-location/service-location.spec.js
+++ b/src/layouts/service-location/service-location.spec.js
@@ -460,11 +460,23 @@ describe("service-location.vue", () => {
};
// Act
- mobileLocationQuestionsComponent.vm.$emit(
- "update:modelValue",
+
+ // Mock the emitEvent function
+ mobileLocationQuestionsComponent.vm.emitEvent = jest.fn(async (eventName, payload) => {
+ return new Promise((resolve) => {
+ mobileLocationQuestionsComponent.vm.$emit(eventName, payload, resolve);
+ });
+ });
+
+ // Trigger the event
+ await mobileLocationQuestionsComponent.vm.emitEvent(
+ "updated-mobile-location-questions",
newMobileLocationQuestions
);
+ await wrapper.vm.$nextTick(); // Wait for DOM updates
+ await new Promise((resolve) => setTimeout(resolve, 0)); // Wait for promise to resolve
+
// Assert
expect(wrapper.vm.mobileLocationQuestions).toStrictEqual(newMobileLocationQuestions);
});
@@ -529,11 +541,23 @@ describe("service-location.vue", () => {
};
// Act
- mobileLocationQuestionsComponent.vm.$emit(
- "update:modelValue",
+
+ // Mock the emitEvent function
+ mobileLocationQuestionsComponent.vm.emitEvent = jest.fn(async (eventName, payload) => {
+ return new Promise((resolve) => {
+ mobileLocationQuestionsComponent.vm.$emit(eventName, payload, resolve);
+ });
+ });
+
+ // Trigger the event
+ await mobileLocationQuestionsComponent.vm.emitEvent(
+ "updated-mobile-location-questions",
newMobileLocationQuestions
);
+ await wrapper.vm.$nextTick(); // Wait for DOM updates
+ await new Promise((resolve) => setTimeout(resolve, 0)); // Wait for promise to resolve
+
// Assert
expect(wrapper.vm.serviceZipCodeQuestion).toStrictEqual(newServiceZipCodeInfo);
});
diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue
index ef7a5491f..a17c0e02b 100644
--- a/src/layouts/service-location/service-location.vue
+++ b/src/layouts/service-location/service-location.vue
@@ -93,6 +93,7 @@
@updated-serviceability="setServiceabilityDetails"
@updated-contains-military-base="setContainsMilitaryBase"
@updated-mobile-ctu="setCtuForMobile"
+ @updated-mobile-location-questions="setMobileLocationQuestions"
validationRules="mobile-location-required"
ref="mobileLocationQuestions"
linkWidgetName="MobileLocationLinkWidget"
@@ -294,17 +295,18 @@ export default {
isVehicleProtected: this.isVehicleProtected,
};
},
- set: function (newValue) {
+ async set(newValue) {
if (newValue.addressQuestions.zipCode !== this.zipCode) {
- getShopProviderData(newValue.addressQuestions.zipCode).then((result) => {
+ await getShopProviderData(newValue.addressQuestions.zipCode).then((result) => {
this.shopProviderData = result.data;
this.selectedProvider = new Provider(
this.shopProviderData.mobileProviderNumber
);
});
}
-
this.setMobileLocation(newValue);
+ //handle promise
+ newValue.resolve?.();
},
},
isServiceableMobile() {
@@ -485,6 +487,10 @@ export default {
setMobileFeePart(mobileFeePart) {
this.mobileFeePart = mobileFeePart;
},
+ //creating async function as the computed property can not directly handle asynchronous operations or promises.
+ async setMobileLocationQuestions(newValue, resolve) {
+ this.mobileLocationQuestions = { ...newValue, resolve };
+ },
getServiceAddressFromStore() {
return store.getters.order.serviceLocation.address;
},
diff --git a/src/layouts/service-zip/service-zip.spec.js b/src/layouts/service-zip/service-zip.spec.js
index 214fd96f0..773157980 100644
--- a/src/layouts/service-zip/service-zip.spec.js
+++ b/src/layouts/service-zip/service-zip.spec.js
@@ -181,6 +181,7 @@ function applyMockStoreDataToGetters() {
payment: mockStoreData.payment,
policy: mockStoreData.policy,
externalParameterServiceZip: mockStoreData.externalParameterServiceZip,
+ emailOrSms: mockStoreData.customer.emailAddress,
};
store.state.order = mockStoreData;
store.state.applicationUser.experiments = mockExperimentSettings;
@@ -241,7 +242,7 @@ describe("service-zip.vue", () => {
// Assert
expect(wrapper.vm.serviceZipCode).toEqual("11111");
- expect(wrapper.vm.emailAddress).toEqual("builddigitaltest@safelite.com");
+ expect(wrapper.vm.emailOrSms).toEqual("builddigitaltest@safelite.com");
});
test("Zip in querystring -> pushed to data", () => {
diff --git a/src/layouts/service-zip/service-zip.vue b/src/layouts/service-zip/service-zip.vue
index b74db95dc..ae7609da8 100644
--- a/src/layouts/service-zip/service-zip.vue
+++ b/src/layouts/service-zip/service-zip.vue
@@ -23,11 +23,11 @@
@@ -88,16 +88,17 @@ import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
+import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
-defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
+defineRule("email-sms-required", required(errorMessages.EMAIL_SMS_REQUIRED));
defineRule(
- "email-address-format",
+ "email-sms-format",
regex(
- /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
- errorMessages.EMAIL_ADDRESS_FORMAT
+ /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
+ errorMessages.EMAIL_SMS_FORMAT
)
);
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
@@ -108,7 +109,7 @@ export default {
data() {
return {
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
- emailAddress: this.getEmailFromStore(),
+ emailOrSms: this.getEmailOrSmsFromStore(),
displayInvalidZipAlert: false,
displayNonServiceableZipAlert: false,
};
@@ -132,22 +133,36 @@ export default {
vm.setCmsContent(resultMap.cmsContent);
if (store.getters.externalParameterState?.isExternalParameter) {
+ if (store.getters.externalParameterServiceZip.zipCode) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
+ {
+ zipCode: store.getters.externalParameterServiceZip.zipCode,
+ state: null,
+ zipCodeCtu: null,
+ },
+ false
+ );
+ }
+
+ if (store.getters.externalParameterCustomer?.phoneNumber) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_PHONE_NUMBER,
+ store.getters.externalParameterCustomer.phoneNumber,
+ false
+ );
+
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_IS_SMS_OPT_IN,
+ true,
+ false
+ );
+ }
+
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
if (isValid) {
vm.forwardButtonAction();
} else {
- if (store.getters.externalParameterServiceZip.zipCode) {
- await baseMixin.methods.dispatchStoreAction(
- storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
- {
- zipCode: store.getters.externalParameterServiceZip.zipCode,
- state: null,
- zipCodeCtu: null,
- },
- false
- );
- }
-
baseMixin.methods.ResetExternalParamsAndHideModal();
}
}
@@ -160,11 +175,11 @@ export default {
store.getters.order.serviceLocation.zipCode
);
},
- getEmailFromStore() {
- return (
- store.getters.externalParameterServiceZip.emailAddress ??
- store.getters.order.customer.emailAddress
- );
+ getEmailOrSmsFromStore() {
+ return store.getters.emailOrSms;
+ },
+ getPhoneFromStore() {
+ return store.getters.order.customer.phoneNumber;
},
arePagePrerequisitesValid() {
return store.getters.damage.isRepair || store.getters.damage.glassToReplace?.length > 0;
@@ -186,7 +201,30 @@ export default {
},
async forwardButtonAction() {
const zipCodeData = await this.getZipCodeData(this.serviceZipCode);
- await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
+
+ // if no value due to field being optional, blank both phone and email address
+ if (!this.emailOrSms) {
+ await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
+ await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
+ }
+ else {
+ if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
+ const phone = this.emailOrSms.replace(/[()]/g, "");
+ await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
+ } else {
+ await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
+ }
+ }
+
+ await this.dispatchStoreAction(
+ storeActions.SAVE_PAGE_DATA,
+ {
+ page: fmgPageValues.EMAIL_SMS_PAGES,
+ data: { emailOrSmsValue: this.emailOrSms },
+ },
+ false
+ );
+
await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue
index 6e9c4b198..46efb4728 100644
--- a/src/layouts/vehicle-damage/vehicle-damage.vue
+++ b/src/layouts/vehicle-damage/vehicle-damage.vue
@@ -152,6 +152,20 @@ export default {
if (isValid) {
vm.forwardButtonAction();
} else {
+ if (store.getters.externalParameterCustomer?.phoneNumber) {
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_PHONE_NUMBER,
+ store.getters.externalParameterCustomer.phoneNumber,
+ false
+ );
+
+ await baseMixin.methods.dispatchStoreAction(
+ storeActions.SAVE_IS_SMS_OPT_IN,
+ true,
+ false
+ );
+ }
+
if (store.getters.externalParameterServiceZip.zipCode) {
await baseMixin.methods.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index 728e1dcfd..12e7268fa 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -186,7 +186,7 @@ export default {
if (experimentForLogging !== undefined) {
// Log experiment exposure
baseMixin.methods.dispatchStoreActionWithLogging(
- storeActions.LOG_EXPERIMENT_EXPOSURE,
+ storeActions.LOG_EXPERIMENT_EXPOSURE_AND_UPDATE_STORE,
{
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue
index eb184bd69..82c54d43a 100644
--- a/src/layouts/vin-lookup/vin-lookup.vue
+++ b/src/layouts/vin-lookup/vin-lookup.vue
@@ -46,10 +46,10 @@
@@ -151,16 +151,17 @@ import { routerParams } from "@/router/router-constants/router-params";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
+import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
-defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
+defineRule("email-sms-required", required(errorMessages.EMAIL_SMS_REQUIRED));
defineRule(
- "email-address-format",
+ "email-sms-format",
regex(
- /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/,
- errorMessages.EMAIL_ADDRESS_FORMAT
+ /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
+ errorMessages.EMAIL_SMS_FORMAT
)
);
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
@@ -195,7 +196,7 @@ export default {
return {
vin: this.getVinFromStore(),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
- emailAddress: this.getEmailFromStore(),
+ emailOrSms: this.getEmailOrSmsFromStore(),
isCarIdDifferent: false,
customAlertData: {},
previouslyEnteredCarId: "",
@@ -212,8 +213,8 @@ export default {
arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null;
},
- getEmailFromStore() {
- return this.$store.getters.order.customer.emailAddress;
+ getEmailOrSmsFromStore() {
+ return this.$store.getters.emailOrSms;
},
getVinFromStore() {
return this.$store.getters.vehicle.vin;
@@ -329,7 +330,21 @@ export default {
false
);
- await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
+ if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
+ const phone = this.emailOrSms.replace(/[()]/g, "");
+ await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
+ } else {
+ await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
+ }
+
+ await this.dispatchStoreAction(
+ storeActions.SAVE_PAGE_DATA,
+ {
+ page: fmgPageValues.EMAIL_SMS_PAGES,
+ data: { emailOrSmsValue: this.emailOrSms },
+ },
+ false
+ );
await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
@@ -365,7 +380,21 @@ export default {
);
}
- await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
+ if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
+ const phone = this.emailOrSms.replace(/[()]/g, "");
+ await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
+ } else {
+ await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
+ }
+
+ await this.dispatchStoreAction(
+ storeActions.SAVE_PAGE_DATA,
+ {
+ page: fmgPageValues.EMAIL_SMS_PAGES,
+ data: { emailOrSmsValue: this.emailOrSms },
+ },
+ false
+ );
return await this.navigateForward();
}
diff --git a/src/mixins/vin-pages-mixin.js b/src/mixins/vin-pages-mixin.js
index 7d15066c5..fc195d910 100644
--- a/src/mixins/vin-pages-mixin.js
+++ b/src/mixins/vin-pages-mixin.js
@@ -16,6 +16,11 @@ export default {
? "email-address-format"
: "email-address-required|email-address-format";
},
+ EmailOrSmsValidationRules() {
+ return this.IsEmailOptional
+ ? "email-sms-format"
+ : "email-sms-required|email-sms-format";
+ },
},
methods: {
async navigateForwardWithSingleCarMatch() {
@@ -56,5 +61,9 @@ export default {
false
);
},
+ isPhoneNumber(input) {
+ const phoneRegex = /^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/;
+ return phoneRegex.test(input);
+ },
},
};
diff --git a/src/router/index.js b/src/router/index.js
index 83004b38c..2230a652d 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -898,7 +898,6 @@ function updateExternalParameterState() {
storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
externalParameterPhoneNumber
);
- store.dispatch(storeActions.SAVE_PHONE_NUMBER, externalParameterPhoneNumber);
}
}
diff --git a/src/router/router-constants/fmgPage-values.js b/src/router/router-constants/fmgPage-values.js
index 5fade6506..1cba0414b 100644
--- a/src/router/router-constants/fmgPage-values.js
+++ b/src/router/router-constants/fmgPage-values.js
@@ -23,6 +23,7 @@ const fmgPageValues = {
PAYMENT_PIA_RETURN: "payment-pia-return",
CONFIRMATION: "confirmation",
RETURN_USER: "return-user",
+ EMAIL_SMS_PAGES: "email-or-sms-related-pages",
};
const funnelStartPageName = fmgPageValues.VEHICLE;
diff --git a/src/store/index.js b/src/store/index.js
index c07fffbd3..64b28415c 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -341,6 +341,9 @@ export const mutations = {
updateCustomerPhoneNumber(state, phoneNumber) {
state.order.customer.phoneNumber = phoneNumber;
},
+ updateCustomerIsSmsOptin(state, isSmsOptIn) {
+ state.order.customer.isSmsOptIn = isSmsOptIn;
+ },
updateVehicle(state, vehicleInfo) {
state.order.vehicle.year = vehicleInfo.year;
state.order.vehicle.make = vehicleInfo.make;
@@ -476,7 +479,7 @@ export const mutations = {
saveExternalParameterState(externalParameterState);
},
updateExternalParameterEmailAddress(state, emailAddress) {
- externalParameterState.serviceZip.emailAddress = emailAddress;
+ externalParameterState.customer.emailAddress = emailAddress;
saveExternalParameterState(externalParameterState);
},
updateExternalParameterIsInsurance(state, isInsurance) {
@@ -517,7 +520,6 @@ export const mutations = {
},
resetExternalParameterServiceZipState(state) {
externalParameterState.serviceZip.zipCode = null;
- externalParameterState.serviceZip.emailAddress = null;
saveExternalParameterState(externalParameterState);
},
resetExternalParameterQuoteState(state) {
@@ -529,6 +531,7 @@ export const mutations = {
saveExternalParameterState(externalParameterState);
},
resetExternalParameterCustomerState(state) {
+ externalParameterState.customer.emailAddress = null;
externalParameterState.customer.phoneNumber = null;
saveExternalParameterState(externalParameterState);
},
@@ -670,34 +673,38 @@ export const mutations = {
sessionInformation.order.payment.billToAccountNumber;
state.order.payment.inactivePromos = sessionInformation.order.payment.inactivePromos;
- state.order.serviceLocation.address =
- sessionInformation.order.serviceLocation.streetAddress;
- state.order.serviceLocation.address2 =
- sessionInformation.order.serviceLocation.streetAddress2;
- 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.serviceLocation.zipCodeCtu =
- sessionInformation.order.serviceLocation.zipCodeCtu;
+ //Do not assign default service type once user make service type selection
+ if (state.order.serviceLocation.appointmentType == null) {
+ state.order.serviceLocation.address =
+ sessionInformation.order.serviceLocation.streetAddress;
+ state.order.serviceLocation.address2 =
+ sessionInformation.order.serviceLocation.streetAddress2;
+ 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.serviceLocation.zipCodeCtu =
+ sessionInformation.order.serviceLocation.zipCodeCtu;
- state.order.serviceLocation.appointmentType =
- sessionInformation.order.serviceLocation.appointmentType;
- state.order.serviceLocation.isVehicleProtected =
- sessionInformation.order.serviceLocation.isVehicleProtected;
+ state.order.serviceLocation.appointmentType =
+ sessionInformation.order.serviceLocation.appointmentType;
+ state.order.serviceLocation.isVehicleProtected =
+ sessionInformation.order.serviceLocation.isVehicleProtected;
- state.order.serviceLocation.provider.providerNumber =
- sessionInformation.order.serviceLocation.provider?.providerNumber;
- state.order.serviceLocation.provider.address.streetAddress =
- sessionInformation.order.serviceLocation.provider?.address?.streetAddress;
- state.order.serviceLocation.provider.address.city =
- sessionInformation.order.serviceLocation.provider?.address?.city;
- state.order.serviceLocation.provider.address.state =
- sessionInformation.order.serviceLocation.provider?.address?.state;
- state.order.serviceLocation.provider.address.zipCode =
- sessionInformation.order.serviceLocation.provider?.address?.zipCode;
- state.order.serviceLocation.provider.address.zipCodeCtu =
- sessionInformation.order.serviceLocation.provider?.address?.zipCodeCtu;
- state.order.serviceLocation.techNotes = sessionInformation.order.serviceLocation.techNotes;
+ state.order.serviceLocation.provider.providerNumber =
+ sessionInformation.order.serviceLocation.provider?.providerNumber;
+ state.order.serviceLocation.provider.address.streetAddress =
+ sessionInformation.order.serviceLocation.provider?.address?.streetAddress;
+ state.order.serviceLocation.provider.address.city =
+ sessionInformation.order.serviceLocation.provider?.address?.city;
+ state.order.serviceLocation.provider.address.state =
+ sessionInformation.order.serviceLocation.provider?.address?.state;
+ state.order.serviceLocation.provider.address.zipCode =
+ sessionInformation.order.serviceLocation.provider?.address?.zipCode;
+ state.order.serviceLocation.provider.address.zipCodeCtu =
+ sessionInformation.order.serviceLocation.provider?.address?.zipCodeCtu;
+ state.order.serviceLocation.techNotes =
+ sessionInformation.order.serviceLocation.techNotes;
+ }
// if we're loading a session and we do not have a provider number yet, then set isInsurance to null so that
// a service package is not selected by default on the quote page.
@@ -741,14 +748,15 @@ export const mutations = {
state.applicationUser.savedSessionId =
sessionInformation.applicationUser.savedSessionId;
}
-
- state.order.schedule.date = sessionInformation.order.schedule?.date;
- state.order.schedule.startTime = sessionInformation.order.schedule?.startTime;
- state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
- state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
- state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
- state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
-
+ //Do not assign default schedule details once user make schedule selection
+ if (state.order.schedule.date == null) {
+ state.order.schedule.date = sessionInformation.order.schedule?.date;
+ state.order.schedule.startTime = sessionInformation.order.schedule?.startTime;
+ state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
+ state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
+ state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
+ state.order.schedule.jobMinMinutes = sessionInformation.order.schedule?.jobMinMinutes;
+ }
state.order.policy.currentDeductible = sessionInformation.order.policy?.currentDeductible;
state.order.policy.originalDeductible = sessionInformation.order.policy?.originalDeductible;
state.order.policy.additionalAuthFlag = sessionInformation.order.policy?.additionalAuthFlag;
@@ -989,6 +997,28 @@ export const getters = {
externalParameterEstimate: (state) => externalParameterState?.estimate,
externalParameterCustomer: (state) => externalParameterState?.customer,
isExternalParameter: (state) => externalParameterState?.isExternalParameter,
+
+ emailOrSms: (state) => {
+ const email =
+ externalParameterState.customer.emailAddress ?? state.order.customer.emailAddress;
+ const phone =
+ externalParameterState.customer.phoneNumber ?? state.order.customer.phoneNumber;
+
+ if (!phone && !email) {
+ return null;
+ }
+
+ if (phone && !email) {
+ return phone;
+ }
+
+ if (email && !phone) {
+ return email;
+ }
+
+ // if we're here, then we have both email and phone so get the value from pageData to reflect what they entered on the page
+ return state.applicationUser.pageData[fmgPageValues.EMAIL_SMS_PAGES]?.emailOrSmsValue;
+ },
};
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
@@ -1254,10 +1284,25 @@ export const actions = {
},
// Analytics Actions
- logExperimentExposure(
+ logExperimentExposureAndUpdateStore(
context,
{ payload: { userId, deviceId, sessionKey, pageName, experiment }, pageNameToLog }
) {
+ const experiments = deepClone(context.getters.applicationUser.experiments);
+ const experimentToMarkAsExposed = experiments.find((ex) => {
+ return (
+ ex.universeId == experiment.universeId &&
+ ex.testId == experiment.testId &&
+ ex.variationId == experiment.variationId &&
+ ex.assignmentId == experiment.assignmentId
+ );
+ });
+ if (experimentToMarkAsExposed) {
+ experimentToMarkAsExposed.isExposed = true;
+ }
+
+ context.commit(storeMutations.UPDATE_EXPERIMENTS, experiments);
+
return globalMethods.callHttpClient({
method: endpoints.LogExperimentExposureIfAssigned.method,
endpoint: endpoints.LogExperimentExposureIfAssigned.url,
@@ -2242,7 +2287,7 @@ export const actions = {
response.data
);
- await resetScheduleIfUnavailable(context, response.data.order, pageNameToLog);
+ await resetScheduleIfUnavailable(context, context.state.order, pageNameToLog);
return response;
},
(error) => {
@@ -3015,7 +3060,17 @@ export const actions = {
},
savePhoneNumber(context, phoneNumber) {
- context.commit(storeMutations.UPDATE_CUSTOMER_PHONE_NUMBER, phoneNumber === "" ? null : phoneNumber);
+ context.commit(
+ storeMutations.UPDATE_CUSTOMER_PHONE_NUMBER,
+ phoneNumber === "" ? null : phoneNumber
+ );
+ },
+ saveIsSmsOptIn(context, isSmsOptIn) {
+ context.commit(storeMutations.UPDATE_CUSTOMER_IS_SMS_OPT_IN, isSmsOptIn);
+ },
+
+ savePageData(context, emailOrSms) {
+ context.commit(storeMutations.UPDATE_PAGE_DATA, emailOrSms);
},
saveVin(context, { isSelectedGlassAvailableForVehicle, vehicleInfo }) {
@@ -3677,7 +3732,6 @@ function createExternalParameterDefaultState() {
vinSelection: null,
},
serviceZip: {
- emailAddress: null,
zipCode: null,
},
quote: {
@@ -3685,6 +3739,7 @@ function createExternalParameterDefaultState() {
servicePackage: null,
},
customer: {
+ emailAddress: null,
phoneNumber: null,
},
};