diff --git a/jest.config.js b/jest.config.js
index ce4aa3ad6..04f474e53 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -12,6 +12,7 @@ module.exports = {
"!src/constants/*.js",
"!src/router/**/*.js",
"!src/helpers/unit-test-helper.js",
+ "!src/helpers/logger.js",
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
"!src/layouts/reveal/**/*.vue",
"!src/layouts/payment-method/**/*.vue",
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/header-keys.js b/src/constants/header-keys.js
index d9b3578c4..ed88393b5 100644
--- a/src/constants/header-keys.js
+++ b/src/constants/header-keys.js
@@ -5,5 +5,5 @@ export const headerKeys = {
SESSION_SEQUENCE_NUMBER: "X-Session-Sequence-Number",
TRANSACTION_ID: "X-Transaction-Id",
EON: "X-Enterprise-Order-Number",
- LOG_ENABLED: "log-enabled"
+ LOG_ENABLED: "log-enabled",
};
diff --git a/src/constants/query-strings.js b/src/constants/query-strings.js
index 210ac28f0..f5881f005 100644
--- a/src/constants/query-strings.js
+++ b/src/constants/query-strings.js
@@ -46,6 +46,7 @@ const queryStrings = {
ORGANIC_SOCIAL: "organic_social",
EXPERIMENTS: "experiments",
FROM_HERITAGE: "fromheritage",
+ PHONE_NUMBER: "phonenumber",
};
export { queryStrings };
diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js
index aee8d705f..9ad6d9890 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",
@@ -76,6 +77,7 @@ const storeActions = {
SAVE_SERVICE_LOCATION: "saveServiceLocation",
SAVE_SCHEDULE: "saveSchedule",
SAVE_EMAIL: "saveEmail",
+ SAVE_PHONE_NUMBER: "savePhoneNumber",
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 f625e27cf..0836beb06 100644
--- a/src/constants/store-mutations.js
+++ b/src/constants/store-mutations.js
@@ -16,8 +16,6 @@ const storeMutations = {
UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor",
UPDATE_VEHICLE_VIN: "updateVehicleVin",
UPDATE_VEHICLE: "updateVehicle",
- UPDATE_VEHICLE_MOBILE_STATIC_RECALIBRATION_APPLICABLE:
- "updateIsMobileStaticRecalibrationApplicable",
UPDATE_IS_REPAIR: "updateIsRepair",
UPDATE_NUMBER_OF_CHIPS: "updateNumberOfChips",
@@ -41,6 +39,7 @@ const storeMutations = {
// CUSTOMER MUTATIONS
UPDATE_CUSTOMER_EMAIL_ADDRESS: "updateCustomerEmailAddress",
+ UPDATE_CUSTOMER_PHONE_NUMBER: "updateCustomerPhoneNumber",
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
// ORDER MUTATIONS
@@ -107,6 +106,7 @@ const storeMutations = {
UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION: "updateExternalParameterVinSelection",
UPDATE_EXTERNAL_PARAMETER_SERVICE_PACKAGE: "updateExternalParameterServicePackage",
UPDATE_EXTERNAL_PARAMETER_SOURCE: "updateExternalParameterSource",
+ UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER: "updateExternalParameterPhoneNumber",
//RESET EXTERNAL_PARAMETER MUTATIONS
RESET_EXTERNAL_PARAMETER_VEHICLE_STATE: "resetExternalParameterVehicleState",
@@ -115,6 +115,7 @@ const storeMutations = {
RESET_EXTERNAL_PARAMETER_SERVICEZIP_STATE: "resetExternalParameterServiceZipState",
RESET_EXTERNAL_PARAMETER_QUOTE_STATE: "resetExternalParameterQuoteState",
RESET_EXTERNAL_PARAMETER_SOURCE_STATE: "resetExternalParameterSourceState",
+ RESET_EXTERNAL_PARAMETER_CUSTOMER_STATE: "resetExternalParameterCustomerState",
RESET_IS_EXTERNAL_PARAMETER: "resetIsExternalParameter",
//Affiliate Cookies
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 873e58709..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
@@ -123,6 +123,7 @@ export default {
flex-direction: row;
justify-content: center;
align-items: center;
+ height: 3rem;
border-radius: 0.5rem;
&.progress-saved {
@@ -156,6 +157,10 @@ export default {
background: none;
box-shadow: none;
}
+ &:focus-visible span {
+ outline: 2px solid #005fcc;
+ border-radius: 0.25rem;
+ }
&.delay {
// fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;
diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js
index 4ff5c0c8e..6e78d1304 100644
--- a/src/helpers/heritage-integration/cookie-helper.js
+++ b/src/helpers/heritage-integration/cookie-helper.js
@@ -201,7 +201,8 @@ export function areAllSessionCookiesSet() {
export function refreshSessionExpiration() {
refreshCookieExpiration(cookieNames.SESSION_ID, cookieExpirations.SESSION_ID);
- refreshCookieExpiration(cookieNames.DXDEV, cookieExpirations.DXDEV);
+ // Change 2/4/25: Don't update DXDEV to avoid Safari constraints on client-set cookies.
+ // refreshCookieExpiration(cookieNames.DXDEV, cookieExpirations.DXDEV);
refreshCookieExpiration(cookieNames.FUNNEL_USER_ID, cookieExpirations.FUNNEL_USER_ID);
refreshCookieExpiration(cookieNames.FUNNEL_SESSION_KEY, cookieExpirations.FUNNEL_SESSION_KEY);
}
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 a239be8c5..deebc096a 100644
--- a/src/layouts/confirmation/confirmation.vue
+++ b/src/layouts/confirmation/confirmation.vue
@@ -125,29 +125,35 @@ export default {
const partsOrQuestions = orderFromStore.damage?.partQuestionAnswers;
- partsOrQuestions.forEach((pqa) => {
- const payloadPartQuestions = [];
- pqa.answeredQuestions.forEach((answer) => {
- payloadPartQuestions.push({
- questionSeq: answer?.questionNum,
- questionText: answer?.questionText,
- answerText: answer?.selectedAnswerText,
- basePart: pqa?.result,
+ if (partsOrQuestions) {
+ partsOrQuestions.forEach((pqa) => {
+ const payloadPartQuestions = [];
+ pqa.answeredQuestions.forEach((answer) => {
+ payloadPartQuestions.push({
+ questionSeq: answer?.questionNum,
+ questionText: answer?.questionText,
+ answerText: answer?.selectedAnswerText,
+ basePart: pqa?.result,
+ });
});
+
+ const payload = {
+ eon: orderFromStore.eon,
+ ctu: ctu,
+ workOrderId: orderFromStore.workOrderId,
+ workOrderNumber: orderFromStore.workOrderNumber,
+ carId: orderFromStore.vehicle.carId,
+ glassLocation: pqa?.glassLocation,
+ partQuestions: payloadPartQuestions,
+ };
+
+ baseMixin.methods.dispatchStoreAction(
+ storeActions.LOG_PART_QUESTIONS,
+ payload,
+ false
+ );
});
-
- const payload = {
- eon: orderFromStore.eon,
- ctu: ctu,
- workOrderId: orderFromStore.workOrderId,
- workOrderNumber: orderFromStore.workOrderNumber,
- carId: orderFromStore.vehicle.carId,
- glassLocation: pqa?.glassLocation,
- partQuestions: payloadPartQuestions,
- };
-
- baseMixin.methods.dispatchStoreAction(storeActions.LOG_PART_QUESTIONS, payload, false);
- });
+ }
// Create order
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER); // This nulls the Store order
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/service-location/service-location.spec.js b/src/layouts/service-location/service-location.spec.js
index 54f28a89c..68d2e948f 100644
--- a/src/layouts/service-location/service-location.spec.js
+++ b/src/layouts/service-location/service-location.spec.js
@@ -182,9 +182,6 @@ beforeEach(() => {
zipCode: "43235",
state: "OH",
},
- vehicle: {
- isMobileStaticRecalibrationApplicable: true,
- },
},
damage: {
isRepair: false,
diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue
index 9addea705..ef7a5491f 100644
--- a/src/layouts/service-location/service-location.vue
+++ b/src/layouts/service-location/service-location.vue
@@ -191,8 +191,6 @@ export default {
isRecalibrationServiceableInshop: null,
isGlassServiceableMobile: null,
isRecalibrationServiceableMobile: null,
- isVehicleMobileStaticRecalibrationApplicable:
- this.getIsVehicleMobileStaticRecalibrationApplicableFromStore(),
selectedAppointmentType: this.getSelectedAppointmentType(),
selectedProvider: this.getSelectedProvider(),
mobileFeePart: null,
@@ -322,9 +320,8 @@ export default {
isMobileStaticRecalibrationApplicable() {
return (
this.displayMSR &&
- this.isVehicleMobileStaticRecalibrationApplicable &&
this.mobileFeePart?.partNumber == partNumberStrings.MOBILE_STATIC_RECAL_FEE &&
- (this.isInsurance ? this.mobileFeePart?.isInsurable : true)
+ (this.isInsurance && !this.isITAC ? this.mobileFeePart?.isInsurable : true)
);
},
displayMSR() {
@@ -401,6 +398,9 @@ export default {
isInsurance() {
return store.getters.payment.isInsurance;
},
+ isITAC() {
+ return store.getters.order.policy.isItac;
+ },
},
methods: {
arePagePrerequisitesValid() {
@@ -509,9 +509,6 @@ export default {
getSelectedProvider() {
return store.getters.order.serviceLocation.provider;
},
- getIsVehicleMobileStaticRecalibrationApplicableFromStore() {
- return store.getters.order.vehicle.isMobileStaticRecalibrationApplicable;
- },
resetMobileLocation() {
this.streetAddress = "";
this.apartmentNumberOrBusinessName = "";
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..18a8b3362 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,
};
@@ -160,11 +161,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 +187,23 @@ export default {
},
async forwardButtonAction() {
const zipCodeData = await this.getZipCodeData(this.serviceZipCode);
- 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,
{
diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue
index c81dfa2b0..12e7268fa 100644
--- a/src/layouts/vehicle/vehicle.vue
+++ b/src/layouts/vehicle/vehicle.vue
@@ -80,7 +80,11 @@ import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { experimentUniverses } from "@/constants/experiments";
-import { getSessionKeyValue, getUserIdValue, getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
+import {
+ getSessionKeyValue,
+ getUserIdValue,
+ getDeviceIdValue,
+} from "@/helpers/heritage-integration/cookie-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
@@ -117,7 +121,6 @@ export default {
modelOptions: [],
styleOptions: [],
displayNoServiceAlert: false,
- isMobileStaticRecalibrationApplicable: this.getIsMobileStaticRecalibrationApplicable(),
};
},
@@ -183,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(),
@@ -440,8 +443,6 @@ export default {
this.imageVifNumber = result?.data.imageVifNumber;
this.imageVifColor = result?.data.imageVifColor;
this.displayNoServiceAlert = !result?.data.canSafeliteService;
- this.isMobileStaticRecalibrationApplicable =
- result?.data.isMobileStaticRecalibrationApplicable;
},
resetAlert() {
this.displayNoServiceAlert = false;
@@ -460,8 +461,6 @@ export default {
imageUrl: this.imageUrl,
imageVifNumber: this.imageVifNumber,
imageVifColor: this.imageVifColor,
- isMobileStaticRecalibrationApplicable:
- this.isMobileStaticRecalibrationApplicable,
},
false
);
@@ -537,9 +536,6 @@ export default {
getImageVifColorfromStore() {
return store.getters.vehicle.imageVifColor;
},
- getIsMobileStaticRecalibrationApplicable() {
- return store.getters.vehicle.isMobileStaticRecalibrationApplicable;
- },
},
components: {
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 76d1203b7..83004b38c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -837,6 +837,7 @@ function updateExternalParameterState() {
const externalParameterServicePackage = getQuerystringParameter(queryStrings.SERVICE_PACKAGE);
const externalParameterNumberOfChips = getQuerystringParameter(queryStrings.NUMBER_OF_CHIPS);
const externalParameterSource = getQuerystringParameter(queryStrings.EXPERIMENTS);
+ const externalParameterPhoneNumber = getQuerystringParameter(queryStrings.PHONE_NUMBER);
if (
externalParameterYear &&
externalParameterMake &&
@@ -892,6 +893,13 @@ function updateExternalParameterState() {
if (externalParameterSource) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource);
}
+ if (externalParameterPhoneNumber) {
+ store.commit(
+ storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
+ externalParameterPhoneNumber
+ );
+ store.dispatch(storeActions.SAVE_PHONE_NUMBER, externalParameterPhoneNumber);
+ }
}
// if there is an existing external parameter state then they have already been through from an external source(LeadGen) and
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 340db8a38..f0efe9ee5 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -68,7 +68,6 @@ const getDefaultState = () => {
registration: {
licensePlate: null,
},
- isMobileStaticRecalibrationApplicable: false,
},
serviceLocation: {
address: null,
@@ -226,10 +225,6 @@ export const mutations = {
updateVehicleVin(state, vin) {
state.order.vehicle.vin = vin;
},
- updateIsMobileStaticRecalibrationApplicable(state, isMobileStaticRecalibrationApplicable) {
- state.order.vehicle.isMobileStaticRecalibrationApplicable =
- isMobileStaticRecalibrationApplicable;
- },
updateIsRepair(state, isRepair) {
state.order.damage.isRepair = isRepair;
},
@@ -343,6 +338,9 @@ export const mutations = {
updateCustomerEmailAddress(state, customerEmailAddress) {
state.order.customer.emailAddress = customerEmailAddress;
},
+ updateCustomerPhoneNumber(state, phoneNumber) {
+ state.order.customer.phoneNumber = phoneNumber;
+ },
updateVehicle(state, vehicleInfo) {
state.order.vehicle.year = vehicleInfo.year;
state.order.vehicle.make = vehicleInfo.make;
@@ -355,8 +353,6 @@ export const mutations = {
state.order.vehicle.imageUrl = vehicleInfo.imageUrl;
state.order.vehicle.imageVifNumber = vehicleInfo.imageVifNumber;
state.order.vehicle.imageColor = vehicleInfo.imageVifColor;
- state.order.vehicle.isMobileStaticRecalibrationApplicable =
- vehicleInfo.isMobileStaticRecalibrationApplicable;
},
updateRegistration(state, registrationInfo) {
state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
@@ -495,6 +491,10 @@ export const mutations = {
externalParameterState.quote.servicePackage = servicePackage;
saveExternalParameterState(externalParameterState);
},
+ updateExternalParameterPhoneNumber(state, phoneNumber) {
+ externalParameterState.customer.phoneNumber = phoneNumber;
+ saveExternalParameterState(externalParameterState);
+ },
//RESET ExternalParameter MUTATIONS
resetExternalParameterVehicleState(state) {
externalParameterState.vehicle.year = null;
@@ -528,6 +528,10 @@ export const mutations = {
externalParameterState.isExternalParameter = externalParameterStatus.INACTIVE;
saveExternalParameterState(externalParameterState);
},
+ resetExternalParameterCustomerState(state) {
+ externalParameterState.customer.phoneNumber = null;
+ saveExternalParameterState(externalParameterState);
+ },
// RESET DEPENDENCY MUTATIONS
resetVehicleState(state) {
@@ -541,7 +545,6 @@ export const mutations = {
state.order.vehicle.imageUrl = null;
state.order.vehicle.imageVifNumber = null;
state.order.vehicle.imageColor = null;
- state.order.vehicle.isMobileStaticRecalibrationApplicable = false;
},
resetDamageState(state) {
state.order.damage.isRepair = null;
@@ -667,34 +670,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.
@@ -738,14 +745,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;
@@ -984,7 +992,29 @@ export const getters = {
externalParameterQuote: (state) => externalParameterState?.quote,
externalParameterServiceZip: (state) => externalParameterState?.serviceZip,
externalParameterEstimate: (state) => externalParameterState?.estimate,
+ externalParameterCustomer: (state) => externalParameterState?.customer,
isExternalParameter: (state) => externalParameterState?.isExternalParameter,
+
+ emailOrSms: (state) => {
+ const email =
+ externalParameterState.serviceZip.emailAddress ?? state.order.customer.emailAddress;
+ const phone = 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) {
@@ -1250,10 +1280,23 @@ 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) => {
+ ex.universeId == experiment.universeId &&
+ ex.testId == experiment.testIde &&
+ 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,
@@ -1644,8 +1687,6 @@ export const actions = {
const coverageStatus = coverageStatusEnum(order.payment?.insuranceCoverage?.coverageStatus);
const coverageType = coverageTypeEnum(order.payment?.insuranceCoverage?.coverageType);
const isItacOptimized = order.policy?.isItac ?? false;
- const isMobileStaticRecalibrationApplicable =
- order.vehicle?.isMobileStaticRecalibrationApplicable;
const zipCode =
serviceZipCode ??
order.serviceLocation?.provider?.address?.zipCode ??
@@ -1661,12 +1702,10 @@ export const actions = {
var endPoint = `${endpoints.GetMobileFeePart.url}/?serviceType=${serviceType}&facilityType=${facilityType}&parentAccountNumber=${parentAccountNumber}&billToAccountNumber=${billToAccountNumber}&providerNumber=${providerNumber}&isItacOptimized=${isItacOptimized}&zipCode=${zipCode}`;
- if (isMobileStaticRecalibrationApplicable) {
- const recalPartNumber = getRecalPartNumber(order.lineItems?.glassParts[0]);
- const carId = order.vehicle?.carId;
- if (recalPartNumber && carId) {
- endPoint = `${endPoint}&partNumbers=${recalPartNumber}&carId=${carId}`;
- }
+ const recalPartNumber = getRecalPartNumber(order.lineItems?.glassParts[0]);
+ const carId = order.vehicle?.carId;
+ if (recalPartNumber && carId) {
+ endPoint = `${endPoint}&partNumbers=${recalPartNumber}&carId=${carId}`;
}
if (coverageStatus) {
@@ -2242,7 +2281,7 @@ export const actions = {
response.data
);
- await resetScheduleIfUnavailable(context, response.data.order, pageNameToLog);
+ await resetScheduleIfUnavailable(context, context.state.order, pageNameToLog);
return response;
},
(error) => {
@@ -2269,18 +2308,7 @@ export const actions = {
// Vehicle
saveVehicle(
context,
- {
- year,
- make,
- model,
- style,
- carId,
- category,
- imageUrl,
- imageVifNumber,
- imageVifColor,
- isMobileStaticRecalibrationApplicable,
- }
+ { year, make, model, style, carId, category, imageUrl, imageVifNumber, imageVifColor }
) {
if (
context.state.order.vehicle.year != year ||
@@ -2301,10 +2329,6 @@ export const actions = {
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, imageUrl);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, imageVifNumber);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, imageVifColor);
- context.commit(
- storeMutations.UPDATE_VEHICLE_MOBILE_STATIC_RECALIBRATION_APPLICABLE,
- isMobileStaticRecalibrationApplicable
- );
}
},
@@ -3029,6 +3053,17 @@ export const actions = {
context.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, email === "" ? null : email);
},
+ savePhoneNumber(context, phoneNumber) {
+ context.commit(
+ storeMutations.UPDATE_CUSTOMER_PHONE_NUMBER,
+ phoneNumber === "" ? null : phoneNumber
+ );
+ },
+
+ savePageData(context, emailOrSms) {
+ context.commit(storeMutations.UPDATE_PAGE_DATA, emailOrSms);
+ },
+
saveVin(context, { isSelectedGlassAvailableForVehicle, vehicleInfo }) {
//Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
@@ -3122,6 +3157,7 @@ export const actions = {
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_ESTIMATE_STATE);
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_SERVICEZIP_STATE);
context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_QUOTE_STATE);
+ context.commit(storeMutations.RESET_EXTERNAL_PARAMETER_CUSTOMER_STATE);
context.commit(storeMutations.RESET_IS_EXTERNAL_PARAMETER);
}
},
@@ -3694,6 +3730,9 @@ function createExternalParameterDefaultState() {
isInsurance: null,
servicePackage: null,
},
+ customer: {
+ phoneNumber: null,
+ },
};
// set to session storage
saveExternalParameterState(externalParameterDefaultState);