Merge pull request #2285 from Safelite/feature/CASH-176

CASH-176
This commit is contained in:
Johnny Shultz 2025-02-06 17:12:58 -05:00 committed by GitHub
commit c3d1ae6b5f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 107 additions and 46 deletions

View file

@ -158,8 +158,8 @@ export default {
box-shadow: none; box-shadow: none;
} }
&:focus-visible span { &:focus-visible span {
outline: 2px solid #005FCC; outline: 2px solid #005fcc;
border-radius: .25rem; border-radius: 0.25rem;
} }
&.delay { &.delay {
// fixes flicker while transitioning between states // fixes flicker while transitioning between states

View file

@ -18,7 +18,7 @@
<customerQuestions <customerQuestions
ref="customerQuestions" ref="customerQuestions"
v-model="customerQuestions" v-model="customerQuestions"
:validationRules="EmailValidationRules" :validationRules="EmailOrSmsValidationRules"
:isEmailOptional="IsEmailOptional" :isEmailOptional="IsEmailOptional"
:isAddressFieldFocused="IsAddressFieldFocused" /> :isAddressFieldFocused="IsAddressFieldFocused" />
<alert <alert
@ -117,6 +117,7 @@ import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-help
import baseMixin from "@/mixins/base-mixin.js"; import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store"; import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin"; 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 // DEFINE VALIDATION RULES - Note: Additional rules are defined in Customer Questions and Address Questions components
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED)); defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -161,7 +162,7 @@ export default {
}, },
firstName: this.getRegistrationFirstNameFromStore(), firstName: this.getRegistrationFirstNameFromStore(),
lastName: this.getRegistrationLastNameFromStore(), lastName: this.getRegistrationLastNameFromStore(),
emailAddress: this.getEmailFromStore(), emailOrSms: this.getEmailOrSmsFromStore(),
}, },
serviceZipCode: this.getServiceZipFromStore(), serviceZipCode: this.getServiceZipFromStore(),
displayNonServiceableZipAlert: false, displayNonServiceableZipAlert: false,
@ -213,8 +214,8 @@ export default {
getRegistrationLastNameFromStore() { getRegistrationLastNameFromStore() {
return this.$store.getters.vehicle.registration.lastName; return this.$store.getters.vehicle.registration.lastName;
}, },
getEmailFromStore() { getEmailOrSmsFromStore() {
return this.$store.getters.order.customer.emailAddress; return this.$store.getters.emailOrSms;
}, },
getServiceZipFromStore() { getServiceZipFromStore() {
return this.$store.getters.order.serviceLocation.zipCode; return this.$store.getters.order.serviceLocation.zipCode;
@ -356,9 +357,23 @@ export default {
false 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( await this.dispatchStoreAction(
storeActions.SAVE_EMAIL, storeActions.SAVE_PAGE_DATA,
this.customerQuestions.emailAddress, {
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.customerQuestions.emailOrSms },
},
false false
); );
await this.dispatchStoreAction( await this.dispatchStoreAction(

View file

@ -30,11 +30,11 @@
<div class="col"> <div class="col">
<textboxQuestion <textboxQuestion
cmsWidgetName="EmailAddressQuestionWidget" cmsWidgetName="EmailAddressQuestionWidget"
v-model="customerModel.emailAddress" v-model="customerModel.emailOrSms"
ref="emailAddress" ref="emailAddress"
customInputId="emailAddress" customInputId="emailOrSms"
:isRequired="!isEmailOptional" :isRequired="!isEmailOptional"
:validationRules="validationRules" :validationRules="EmailOrSmsvalidationRules"
:addOptionalText="isEmailOptional" :addOptionalText="isEmailOptional"
autocomplete="email" /> autocomplete="email" />
</div> </div>
@ -59,12 +59,12 @@ import textBlock from "@/digital-components/text-block/text-block";
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED)); defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
defineRule("last-name-required", required(errorMessages.LAST_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( defineRule(
"email-address-format", "email-sms-format",
regex( regex(
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
errorMessages.EMAIL_ADDRESS_FORMAT errorMessages.EMAIL_SMS_FORMAT
) )
); );
@ -84,7 +84,7 @@ export default {
}, },
firstName: "", firstName: "",
lastName: "", lastName: "",
emailAddress: "", emailOrSms: "",
}, },
}), }),
}, },

View file

@ -68,7 +68,7 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({ emailAddress: mockEmail }); const { wrapper } = setupMocks({ emailAddress: mockEmail });
// ACT // ACT
const customerEmail = wrapper.vm.getEmailFromStore(); const customerEmail = wrapper.vm.getEmailOrSmsFromStore();
// Assert // Assert
expect(customerEmail).toEqual(mockEmail); expect(customerEmail).toEqual(mockEmail);
@ -665,6 +665,7 @@ function setupMocks({
}, },
store: { store: {
getters: { getters: {
emailOrSms: emailAddress,
vehicle: { vehicle: {
registration: { registration: {
licensePlate: licensePlate, licensePlate: licensePlate,

View file

@ -28,10 +28,10 @@
<textboxQuestion <textboxQuestion
cmsWidgetName="EmailAddressQuestionWidget" cmsWidgetName="EmailAddressQuestionWidget"
v-model="email" v-model="emailOrSms"
customInputId="email" customInputId="emailOrSms"
:isRequired="!IsEmailOptional" :isRequired="!IsEmailOptional"
:validationRules="EmailValidationRules" :validationRules="EmailOrSmsValidationRules"
:addOptionalText="IsEmailOptional" /> :addOptionalText="IsEmailOptional" />
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" /> <textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" />
@ -110,17 +110,18 @@ import { Form, defineRule } from "vee-validate";
import baseMixin from "@/mixins/base-mixin.js"; import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store"; import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin"; import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED)); defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
defineRule("registration-zip-required", required(errorMessages.REGISTRATION_ZIP_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("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( defineRule(
"email-address-format", "email-sms-format",
regex( regex(
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
errorMessages.EMAIL_ADDRESS_FORMAT errorMessages.EMAIL_SMS_FORMAT
) )
); );
@ -155,7 +156,7 @@ export default {
return { return {
licensePlate: this.getLicensePlateFromStore(), licensePlate: this.getLicensePlateFromStore(),
registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode, registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode,
email: this.getEmailFromStore(), emailOrSms: this.getEmailOrSmsFromStore(),
serviceZipCode: this.getServiceZipFromStore(), serviceZipCode: this.getServiceZipFromStore(),
displayNonServiceableZipAlert: false, displayNonServiceableZipAlert: false,
displayVinNotFoundAlert: false, displayVinNotFoundAlert: false,
@ -193,8 +194,8 @@ export default {
getRegistrationZipFromStore() { getRegistrationZipFromStore() {
return this.$store.getters.vehicle.registration.zipCode; return this.$store.getters.vehicle.registration.zipCode;
}, },
getEmailFromStore() { getEmailOrSmsFromStore() {
return this.$store.getters.order.customer.emailAddress; return this.$store.getters.emailOrSms;
}, },
getServiceZipFromStore() { getServiceZipFromStore() {
return this.$store.getters.order.serviceLocation.zipCode; return this.$store.getters.order.serviceLocation.zipCode;
@ -310,7 +311,21 @@ export default {
false 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( await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO, storeActions.SAVE_SERVICE_ZIP_CODE_INFO,

View file

@ -46,10 +46,10 @@
<textboxQuestion <textboxQuestion
cmsWidgetName="EmailAddressQuestionWidget" cmsWidgetName="EmailAddressQuestionWidget"
v-model="emailAddress" v-model="emailOrSms"
customInputId="emailAddress" customInputId="emailOrSms"
:isRequired="!IsEmailOptional" :isRequired="!IsEmailOptional"
:validationRules="EmailValidationRules" :validationRules="EmailOrSmsValidationRules"
:addOptionalText="IsEmailOptional" /> :addOptionalText="IsEmailOptional" />
<textBlock cmsWidgetName="QuoteEmailTextBlockWidget" typeStyle="caption" /> <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 baseMixin from "@/mixins/base-mixin.js";
import store from "@/store"; import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin"; import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED)); defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT)); 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( defineRule(
"email-address-format", "email-sms-format",
regex( regex(
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$/, /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9-]+)\.([a-zA-Z]{2,})$|^\(?(\d{3})\)?[-. ]?(\d{3})[-. ]?(\d{4})$/,
errorMessages.EMAIL_ADDRESS_FORMAT errorMessages.EMAIL_SMS_FORMAT
) )
); );
defineRule("vin-required", required(errorMessages.VIN_REQUIRED)); defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
@ -195,7 +196,7 @@ export default {
return { return {
vin: this.getVinFromStore(), vin: this.getVinFromStore(),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode, serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
emailAddress: this.getEmailFromStore(), emailOrSms: this.getEmailOrSmsFromStore(),
isCarIdDifferent: false, isCarIdDifferent: false,
customAlertData: {}, customAlertData: {},
previouslyEnteredCarId: "", previouslyEnteredCarId: "",
@ -212,8 +213,8 @@ export default {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null; return store.getters.vehicle.carId !== null;
}, },
getEmailFromStore() { getEmailOrSmsFromStore() {
return this.$store.getters.order.customer.emailAddress; return this.$store.getters.emailOrSms;
}, },
getVinFromStore() { getVinFromStore() {
return this.$store.getters.vehicle.vin; return this.$store.getters.vehicle.vin;
@ -329,7 +330,21 @@ export default {
false 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( await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO, 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(); return await this.navigateForward();
} }

View file

@ -1004,7 +1004,8 @@ export const getters = {
isExternalParameter: (state) => externalParameterState?.isExternalParameter, isExternalParameter: (state) => externalParameterState?.isExternalParameter,
emailOrSms: (state) => { emailOrSms: (state) => {
const email = externalParameterState.serviceZip.emailAddress ?? state.order.customer.emailAddress; const email =
externalParameterState.serviceZip.emailAddress ?? state.order.customer.emailAddress;
const phone = state.order.customer.phoneNumber; const phone = state.order.customer.phoneNumber;
if (!phone && !email) { if (!phone && !email) {
@ -1292,16 +1293,16 @@ export const actions = {
{ payload: { userId, deviceId, sessionKey, pageName, experiment }, pageNameToLog } { payload: { userId, deviceId, sessionKey, pageName, experiment }, pageNameToLog }
) { ) {
const experiments = deepClone(context.getters.applicationUser.experiments); const experiments = deepClone(context.getters.applicationUser.experiments);
const experimentToMarkAsExposed = experiments.find(ex => { const experimentToMarkAsExposed = experiments.find((ex) => {
ex.universeId == experiment.universeId && ex.universeId == experiment.universeId &&
ex.testId == experiment.testIde && ex.testId == experiment.testIde &&
ex.variationId == experiment.variationId && ex.variationId == experiment.variationId &&
ex.assignmentId == experiment.assignmentId ex.assignmentId == experiment.assignmentId;
}); });
if (experimentToMarkAsExposed) { if (experimentToMarkAsExposed) {
experimentToMarkAsExposed.isExposed = true; experimentToMarkAsExposed.isExposed = true;
} }
context.commit(storeMutations.UPDATE_EXPERIMENTS, experiments); context.commit(storeMutations.UPDATE_EXPERIMENTS, experiments);
return globalMethods.callHttpClient({ return globalMethods.callHttpClient({