Merge remote-tracking branch 'origin/develop' into feature/skiener/INSR-2124

This commit is contained in:
scottkiener-at-safelite 2026-04-03 09:50:59 -04:00
commit fb8884be18
7 changed files with 113 additions and 6 deletions

View file

@ -3,7 +3,7 @@
ref="theForm"
v-slot="{ meta }"
@submit="onSubmit"
@invalidSubmit="onInvalidSubmit">
@invalidSubmit="customInvalidSubmit">
<div class="fade-on-route-transition">
<div class="justify-content-center">
<siteHeader cmsWidgetName="SiteHeaderWidget" />
@ -251,12 +251,15 @@ export default {
if (vinLookupResponse.error) {
this.displayVinNotFoundAlert = true;
this.previouslyEnteredCarId = null;
this.pushEventToGA("VehicleDamage", "LicensePlate_NoMatch", "Trouble_Finding", true, null, '0');
showIssLoadingModal(false);
return this.$refs.siteFooter.disableForwardButton();
}
// Vehicle found from VIN lookup
const vehicleFromLookup = vinLookupResponse.data.vehicle;
const vehicleString = vehicleFromLookup.year + '_' + vehicleFromLookup.make + '_' + vehicleFromLookup.model + '_' + vehicleFromLookup.style;
this.pushEventToGA("VehicleDamage", "LicensePlate_Vin_Match", vehicleString, true, null, '1');
if (!vehicleFromLookup.canSafeliteService) {
this.mainStore.setBailout({
type: 'HeavyTruckVehicle',
@ -321,6 +324,12 @@ export default {
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
},
customInvalidSubmit({ errors }) {
if (errors['license-plate-question']) {
this.pushEventToGA("VehicleDamage", "LicensePlate_NoMatch", "Plate_Required", true, null, '0');
}
this.onInvalidSubmit({ errors });
}
}
};

View file

@ -41,7 +41,8 @@ const mountOptions = {
methods: {
getCmsContent: jest.fn(),
getFooterInfoBoxHeight: jest.fn(() => 80),
getPageNameByQueryString: jest.fn(() => '')
getPageNameByQueryString: jest.fn(() => ''),
pushEventToGA: jest.fn()
}
}
],

View file

@ -412,6 +412,8 @@ export default {
this.selectedWindshieldOptions.selectedWindshieldChipCount
);
this.logEvents();
if (this.isWindshieldRepair) {
const results = await Promise.allSettled([useMainStore().getSupportingItems(), useMainStore().getRecalParts()]);
const supportingItems = results[0].value;
@ -481,6 +483,76 @@ export default {
}
return selectedGlassToReplace;
},
logEvents() {
const vehicleString = this.mainStore.order.vehicle.make + '_' + this.mainStore.order.vehicle.model + '_' + this.mainStore.order.vehicle.style;
this.pushEventToGA("CAR SUBMISSION", this.mainStore.order.vehicle.year?.toString(), vehicleString, true, null, 0);
if (this.isWindshieldRepair) {
this.pushEventToGA("damage", "selected", "repair", true, null, null);
this.pushEventToGA("VehicleDamage", "Repair", this.mainStore.damage.numberOfChips?.toString(), true, null, this.mainStore.damage.numberOfChips);
} else {
this.pushEventToGA("damage", "selected", "replace", true, null, null);
this.selectedGlassToReplace().forEach((glass) => {
this.logEventForPart(glass);
});
}
},
logEventForPart(glass) {
let eventGlassLocation = '';
let eventGlassName = '';
switch (glass.glassLocation) {
case damageLocationsSelected.WINDSHIELD:
eventGlassLocation = 'Windshield Replace';
break;
case damageLocationsSelected.DRIVER:
eventGlassLocation = "Driver's Side";
break;
case damageLocationsSelected.PASSENGER:
eventGlassLocation = "Passenger's Side";
break;
case damageLocationsSelected.REAR:
eventGlassLocation = 'Back Glass';
break;
default:
eventGlassLocation = glass.glassLocation;
}
switch (glass.glassName) {
// Windshield options
case damageLocationsSelected.DRIVER:
eventGlassName = "Left piece";
break;
case damageLocationsSelected.PASSENGER:
eventGlassName = "Right piece";
break;
// Bottom two cases here are for rear options, but they are handled the same as single windshield
case damageLocationsSelected.SINGLE:
case damageLocationsSelected.STATIONARY:
case damageLocationsSelected.SLIDER:
eventGlassName = '';
break;
// Side door options
case damageLocationsSelected.FRONT:
eventGlassName = "Front door";
break;
case damageLocationsSelected.BACK:
eventGlassName = "Rear door";
break;
case damageLocationsSelected.QUARTER:
eventGlassName = "Quarter";
break;
case damageLocationsSelected.VENT:
eventGlassName = "Vent";
break;
case damageLocationsSelected.SIDEDOOR:
eventGlassName = "Sliding door";
break;
default:
eventGlassName = glass.glassName;
}
const label = eventGlassName ? `${eventGlassLocation} - ${eventGlassName}` : eventGlassLocation;
this.pushEventToGA("VehicleDamage", "Replacement", label, true, null, 1);
}
}
};

View file

@ -38,6 +38,7 @@ export default {
isVinLocationDetailVisible: false
};
},
emits: ['vin-location-detail-shown'],
computed: {
textForToggle() {
return this.getCmsContent('WhereCanIFindMyVINToggle', 'HeaderText');
@ -52,6 +53,9 @@ export default {
methods: {
handleClickToggle() {
this.isVinLocationDetailVisible = !this.isVinLocationDetailVisible;
if (this.isVinLocationDetailVisible) {
this.$emit('vin-location-detail-shown');
}
}
}
};

View file

@ -16,11 +16,12 @@
class="mt-4" />
<vinQuestion
v-model="vin"
ref="vin-question"
class="mt-4"
:mask="vinMask"
:isDisabled="vinPopulatedOnPageLoad"
textPosition="left" />
<vinLocationInformation />
<vinLocationInformation @vin-location-detail-shown="handleVinLocationDetailShown" />
<vinLookupAlerts
:activeAlertType="activeVehicleLookupAlertType" />
<siteFooter
@ -178,6 +179,7 @@ export default {
if (this.needToLookupVehicle) {
try {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
this.pushEventToGA("VIN", "TEXT", "SUCCESS", true, null, '1');
if (!vehicleLookupResponse.data.canSafeliteService) {
this.mainStore.setBailout(bailoutMessage.HeavyTruckVehicle(vehicleLookupResponse.data.carId));
@ -201,6 +203,7 @@ export default {
// because the form itself actually passes its client-side validation.
// SSR-189 Scenario #4.
this.$refs.siteFooter.enableForwardAction();
this.pushEventToGA("VIN", "TEXT", "NO VEHICLE FOUND", true, null, '0');
showIssLoadingModal(false);
return;
}
@ -270,12 +273,26 @@ export default {
async lookupVehicleByVin(vin) {
return this.mainStore.lookupVehicleByVin(vin);
},
handleVinLocationDetailShown() {
if (!this.vin) {
this.pushEventToGA("VehicleDamage", "Where_Is_VIN", "VIN_Empty", true);
}
else if (this.checkVinForErrors()) {
this.pushEventToGA("VehicleDamage", "Where_Is_VIN", "VIN_Error", true);
}
else {
this.pushEventToGA("VehicleDamage", "Where_Is_VIN", "VIN_Field_Active", true);
}
},
resetActiveAlert() {
this.activeVehicleLookupAlertType = null;
},
resetVehicleFromLookup() {
this.vehicleFromLookup = null;
},
checkVinForErrors() {
return this.$refs['vin-question'].hasErrors;
},
resetDependentState() {}
}
};

View file

@ -1,6 +1,7 @@
<template>
<textboxQuestion
id="vin-question-wrapper"
ref="vin-question-wrapper"
v-model="vin"
cmsWidgetName="VinNumberQuestionWidget"
disableAutoFill
@ -38,6 +39,9 @@ export default {
set(newValue) {
this.$emit('update:modelValue', newValue);
}
},
hasErrors() {
return this.$refs['vin-question-wrapper']?.meta?.valid === false;
}
}
};

View file

@ -92,7 +92,7 @@ export default {
store.logCustomEvent(payload);
},
pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null) {
pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null, value = undefined) {
const currentPageName = this.getPageNameByQueryString();
const labelToLog = getValueToLog(label, valueToLogType);
@ -101,14 +101,14 @@ export default {
category,
action,
label: labelToLog,
value: undefined,
value: value,
path: `/iss/?${queryStrings.ISS_PAGE}=${currentPageName}`
};
pushToDataLayerIfDefined(eventToBePushed);
if (pushToLogApp) {
this.logCustomEvent(category, action, labelToLog, undefined);
this.logCustomEvent(category, action, labelToLog, value);
}
},