Merge branch 'develop' into feature/CASH-153
This commit is contained in:
commit
d860701f6d
28 changed files with 478 additions and 133 deletions
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
<customerQuestions
|
||||
ref="customerQuestions"
|
||||
v-model="customerQuestions"
|
||||
:validationRules="EmailValidationRules"
|
||||
:validationRules="EmailOrSmsValidationRules"
|
||||
:isEmailOptional="IsEmailOptional"
|
||||
:isAddressFieldFocused="IsAddressFieldFocused" />
|
||||
<alert
|
||||
|
|
@ -117,6 +117,7 @@ import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-help
|
|||
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 - Note: Additional rules are defined in Customer Questions and Address Questions components
|
||||
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
|
|
@ -161,7 +162,7 @@ export default {
|
|||
},
|
||||
firstName: this.getRegistrationFirstNameFromStore(),
|
||||
lastName: this.getRegistrationLastNameFromStore(),
|
||||
emailAddress: this.getEmailFromStore(),
|
||||
emailOrSms: this.getEmailOrSmsFromStore(),
|
||||
},
|
||||
serviceZipCode: this.getServiceZipFromStore(),
|
||||
displayNonServiceableZipAlert: false,
|
||||
|
|
@ -213,8 +214,8 @@ export default {
|
|||
getRegistrationLastNameFromStore() {
|
||||
return this.$store.getters.vehicle.registration.lastName;
|
||||
},
|
||||
getEmailFromStore() {
|
||||
return this.$store.getters.order.customer.emailAddress;
|
||||
getEmailOrSmsFromStore() {
|
||||
return this.$store.getters.emailOrSms;
|
||||
},
|
||||
getServiceZipFromStore() {
|
||||
return this.$store.getters.order.serviceLocation.zipCode;
|
||||
|
|
@ -356,9 +357,23 @@ export default {
|
|||
false
|
||||
);
|
||||
|
||||
if (vinPagesMixin.methods.isPhoneNumber(this.customerQuestions.emailOrSms)) {
|
||||
const phone = this.customerQuestions.emailOrSms.replace(/[()]/g, "");
|
||||
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
|
||||
} else {
|
||||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_EMAIL,
|
||||
this.customerQuestions.emailOrSms,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_EMAIL,
|
||||
this.customerQuestions.emailAddress,
|
||||
storeActions.SAVE_PAGE_DATA,
|
||||
{
|
||||
page: fmgPageValues.EMAIL_SMS_PAGES,
|
||||
data: { emailOrSmsValue: this.customerQuestions.emailOrSms },
|
||||
},
|
||||
false
|
||||
);
|
||||
await this.dispatchStoreAction(
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@
|
|||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="EmailAddressQuestionWidget"
|
||||
v-model="customerModel.emailAddress"
|
||||
v-model="customerModel.emailOrSms"
|
||||
ref="emailAddress"
|
||||
customInputId="emailAddress"
|
||||
customInputId="emailOrSms"
|
||||
:isRequired="!isEmailOptional"
|
||||
:validationRules="validationRules"
|
||||
:validationRules="EmailOrSmsvalidationRules"
|
||||
:addOptionalText="isEmailOptional"
|
||||
autocomplete="email" />
|
||||
</div>
|
||||
|
|
@ -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: "",
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@
|
|||
v-model="parentAccountNumber"
|
||||
:originalList="originalList" />
|
||||
</div>
|
||||
<textLink
|
||||
id="payOnMyOwnBackButton"
|
||||
useLoadingModal
|
||||
linkType="text"
|
||||
:text="payWithCashButtonCopy"
|
||||
href="javascript:void(0)"
|
||||
@click-event="backButtonAction(foreceCashSelectionOnQuote = true)" />
|
||||
|
||||
<navbar
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
|
|
@ -36,6 +43,7 @@ import navbar from "@/fmg-components/nav-bar/nav-bar";
|
|||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||
import insuranceCompanyQuestion from "@/layouts/insurance-company/insurance-company-question";
|
||||
import textLink from "../../ux-components/text-link/text-link.vue";
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
|
|
@ -92,6 +100,9 @@ export default {
|
|||
isParentAccountNumber() {
|
||||
return !!this.parentAccountNumber;
|
||||
},
|
||||
payWithCashButtonCopy() {
|
||||
return this.getCmsContent("PayWithCashWidget", "Text");
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isCashParentAccountNumber() {
|
||||
|
|
@ -109,8 +120,13 @@ export default {
|
|||
arePagePrerequisitesValid() {
|
||||
return store.getters.order.payment.isInsurance === true;
|
||||
},
|
||||
backButtonAction() {
|
||||
backButtonAction(forceCashSelectionOnQuote) {
|
||||
// Go back to Quote page
|
||||
if (forceCashSelectionOnQuote) {
|
||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route, {"isCashSelected": true});
|
||||
return;
|
||||
}
|
||||
|
||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
|
|
@ -157,6 +173,7 @@ export default {
|
|||
Form,
|
||||
loadingModal,
|
||||
insuranceCompanyQuestion,
|
||||
textLink,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@
|
|||
|
||||
<textboxQuestion
|
||||
cmsWidgetName="EmailAddressQuestionWidget"
|
||||
v-model="email"
|
||||
customInputId="email"
|
||||
v-model="emailOrSms"
|
||||
customInputId="emailOrSms"
|
||||
:isRequired="!IsEmailOptional"
|
||||
:validationRules="EmailValidationRules"
|
||||
:validationRules="EmailOrSmsValidationRules"
|
||||
:addOptionalText="IsEmailOptional" />
|
||||
|
||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 () => {
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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", () => {
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@
|
|||
<textboxQuestion
|
||||
class="mb-0"
|
||||
cmsWidgetName="EmailAddressQuestionWidget"
|
||||
v-model="emailAddress"
|
||||
inputId="emailAddress"
|
||||
v-model="emailOrSms"
|
||||
inputId="emailOrSms"
|
||||
:isRequired="!IsEmailOptional"
|
||||
disableAutoFill
|
||||
:validationRules="EmailValidationRules"
|
||||
:validationRules="EmailOrSmsValidationRules"
|
||||
:addOptionalText="IsEmailOptional" />
|
||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||
|
||||
|
|
@ -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,
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -46,10 +46,10 @@
|
|||
|
||||
<textboxQuestion
|
||||
cmsWidgetName="EmailAddressQuestionWidget"
|
||||
v-model="emailAddress"
|
||||
customInputId="emailAddress"
|
||||
v-model="emailOrSms"
|
||||
customInputId="emailOrSms"
|
||||
:isRequired="!IsEmailOptional"
|
||||
:validationRules="EmailValidationRules"
|
||||
:validationRules="EmailOrSmsValidationRules"
|
||||
:addOptionalText="IsEmailOptional" />
|
||||
|
||||
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -898,7 +898,6 @@ function updateExternalParameterState() {
|
|||
storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
|
||||
externalParameterPhoneNumber
|
||||
);
|
||||
store.dispatch(storeActions.SAVE_PHONE_NUMBER, externalParameterPhoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue