From 4bff273b47f652c0c636f7b4f3cc2659416c4ddb Mon Sep 17 00:00:00 2001 From: Katie Kroell Date: Fri, 27 Mar 2026 11:42:46 -0400 Subject: [PATCH 1/8] fix recal logic --- src/helpers/recal-helper.js | 20 +++++++++++++++++++ .../coverage-statement.spec.js | 12 +++++++++-- .../coverage-statement/coverage-statement.vue | 3 +++ .../service-package-question.vue | 3 ++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index e72c2d63..429e2c72 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -52,3 +52,23 @@ export function getRecalPartNumbers(glassPartsArray) { } } +export function containsRecalParts(lineItems) { + if (!lineItems) { + return false; + } + + if (Array.isArray(lineItems)) { + return lineItems.some((li) => isRecalPartOrHasChildRecalPart(li)); + } else { + // complex object form -- flatten and re-call. + const flattened = [ + ...(lineItems.glassParts ?? []), + ...(lineItems.supportingItems ?? []), + ...(lineItems.vaps ?? []), + ...(lineItems.promos ?? []), + ]; + + return flattened.some((li) => isRecalPartOrHasChildRecalPart(li)); + } +} + diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js index a8b77aa5..dcccbed6 100644 --- a/src/layouts/coverage-statement/coverage-statement.spec.js +++ b/src/layouts/coverage-statement/coverage-statement.spec.js @@ -32,6 +32,12 @@ jest.mock('@/helpers/text-helper', () => ({ formatAmountInDollars: jest.fn() })); +jest.mock('@/helpers/recal-helper.js', () => ({ + containsRecalParts: jest.fn() +})); + +import { containsRecalParts } from '@/helpers/recal-helper.js'; + const SAFELITE_PROVIDER = 'Safelite'; const CANCEL_CLAIM_REF_NAME = 'CancelClaimModal'; @@ -337,15 +343,17 @@ describe('coverageStatement.vue', () => { // Assert expect(result).toBeFalsy(); }); - test('returns true when a part in glassParts require recalibration', () => { + test('returns true when a part in glassParts require recalibration and recalibration has been added to order', () => { // Arrange + containsRecalParts.mockReturnValue(true); const mainInitialState = { order: { lineItems: { glassParts: [ { partNumber: 123, - requiresRecalibration: true + requiresRecalibration: true, + partType: 'RECALIBRATION' }, { partNumber: 111, diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 4cc38651..70415327 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -147,6 +147,7 @@ import { getPriceOfLineItems } from '@/helpers/price-calculator'; import coverageStatuses from '@/constants/coverage-statuses'; import coverageType from '@/constants/coverage-type'; import oemEndorsementModal from '@/layouts/coverage-statement/oem-endorsement-modal/oem-endorsement-modal.vue'; +import { containsRecalParts } from '@/helpers/recal-helper'; const RECAL_MODAL_REF_NAME = 'RecalModal'; const CANCEL_CLAIM_REF_NAME = 'CancelClaimModal'; @@ -305,9 +306,11 @@ export default { }, isADAS() { const { glassParts } = useMainStore().order.lineItems; + const orderContainsRecalPart = containsRecalParts(glassParts); return ( glassParts !== null && !!glassParts.find((part) => part.requiresRecalibration) + && orderContainsRecalPart ); }, totalServicePrice() { diff --git a/src/layouts/service-packages/service-package-question/service-package-question.vue b/src/layouts/service-packages/service-package-question/service-package-question.vue index 73e29932..63bac64f 100644 --- a/src/layouts/service-packages/service-package-question/service-package-question.vue +++ b/src/layouts/service-packages/service-package-question/service-package-question.vue @@ -23,6 +23,7 @@ import partTypeStrings from '@/constants/part-type-strings'; import { useMainStore } from '@/store'; import { getPriceOfLineItem } from '@/helpers/price-calculator'; import { shallowRef } from 'vue'; +import { containsRecalParts } from '@/helpers/recal-helper'; const glassLocations = damageLocationsSelected; @@ -100,7 +101,7 @@ export default { return modifiedAnswers; }, isRecalibrationOnOrder() { - return this.mainStore.hasRecalibrationPart; + return this.mainStore.hasRecalibrationPart && containsRecalParts(this.mainStore.order.lineItems); }, frontWipersApplicableForTierTwo() { const frontWipersAreAvailable = this.lineItemsContainsPartType(partTypeStrings.FRONT_WIPER); From 744f1b47240ed2164f1c00e55f2f9702d01753c0 Mon Sep 17 00:00:00 2001 From: katiekroell <100247286+katiekroell@users.noreply.github.com> Date: Fri, 27 Mar 2026 11:51:40 -0400 Subject: [PATCH 2/8] Update src/helpers/recal-helper.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/helpers/recal-helper.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index 429e2c72..68fdd51c 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -64,8 +64,9 @@ export function containsRecalParts(lineItems) { const flattened = [ ...(lineItems.glassParts ?? []), ...(lineItems.supportingItems ?? []), + ...(lineItems.otherParts ?? []), + ...(lineItems.feeItems ?? []), ...(lineItems.vaps ?? []), - ...(lineItems.promos ?? []), ]; return flattened.some((li) => isRecalPartOrHasChildRecalPart(li)); From 94f1504ef9fd4bffaafa8bfd23f8ff791eda5dc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Mar 2026 15:54:58 +0000 Subject: [PATCH 3/8] fix: use .some() instead of .filter() in isRecalPartOrHasChildRecalPart to return boolean Agent-Logs-Url: https://github.com/Safelite/DigitalConsumer.ISS/sessions/af7c0e65-2f59-45e0-8c49-f5c468cafa1a Co-authored-by: katiekroell <100247286+katiekroell@users.noreply.github.com> --- src/helpers/recal-helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index 68fdd51c..c6cce97e 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -11,7 +11,7 @@ export function isRecalPartOrHasChildRecalPart(glassPart) { const isGlassPartRecalPart = isRecalPart(glassPart); if (!isGlassPartRecalPart && glassPart.childParts && glassPart.childParts.length > 0) { - return glassPart.childParts.filter((cp) => isRecalPartOrHasChildRecalPart(cp)); + return glassPart.childParts.some((cp) => isRecalPartOrHasChildRecalPart(cp)); } return isGlassPartRecalPart; From 2cf558c18fc248e04b2492eea22c3c2fd0ad1300 Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 1 Apr 2026 11:18:05 -0400 Subject: [PATCH 4/8] Add events to vehicle-damage, vin-lookup, and license-plate-lookup --- .../license-plate-lookup.vue | 17 ++++- src/layouts/vehicle-damage/vehicle-damage.vue | 72 +++++++++++++++++++ .../vin-location-information.vue | 4 ++ src/layouts/vin-lookup/vin-lookup.vue | 24 ++++++- src/mixins/analytics-mixin.js | 8 ++- 5 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index 32203b5c..86796e10 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -3,7 +3,7 @@ ref="theForm" v-slot="{ meta }" @submit="onSubmit" - @invalidSubmit="onInvalidSubmit"> + @invalidSubmit="customInvalidSubmit">
@@ -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,18 @@ export default { resetWarningsAndErrors() { this.displayVinNotFoundAlert = false; this.displayMatchedDifferentVehicleAlert = false; + }, + customInvalidSubmit({ errors }) { + if (errors.length > 0) { + const licensePlateError = errors.find( + (error) => error.field === 'license-plate-question' + ); + + if (licensePlateError) { + this.pushEventToGA("VehicleDamage", "LicensePlate_NoMatch", "Plate_Required", true, null, '0'); + } + } + this.onInvalidSubmit({ errors }); } } }; diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 47f7463d..82adfde4 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -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.DRIVERSIDE: + eventGlassLocation = "Driver's Side"; + break; + case damageLocationsSelected.PASSENGERSIDE: + 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); } } }; diff --git a/src/layouts/vin-lookup/vin-location-information/vin-location-information.vue b/src/layouts/vin-lookup/vin-location-information/vin-location-information.vue index 7bc12729..b462e860 100644 --- a/src/layouts/vin-lookup/vin-location-information/vin-location-information.vue +++ b/src/layouts/vin-lookup/vin-location-information/vin-location-information.vue @@ -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'); + } } } }; diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index a2efafc8..493683df 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -16,11 +16,12 @@ class="mt-4" /> - + Date: Wed, 1 Apr 2026 11:32:10 -0400 Subject: [PATCH 5/8] Remove console.log --- src/mixins/analytics-mixin.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index c43f8bd7..cfe48753 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -96,8 +96,6 @@ export default { const currentPageName = this.getPageNameByQueryString(); const labelToLog = getValueToLog(label, valueToLogType); - console.log(`Pushing event to GA: category=${category}, action=${action}, label=${labelToLog}, value=${value}`); - const eventToBePushed = { event: GaEvents.GENERIC_EVENT, category, From 19c7d41b6273132fb2d04e7b4cde4cfafb4cad6c Mon Sep 17 00:00:00 2001 From: Alex Humphries Date: Wed, 1 Apr 2026 13:43:30 -0400 Subject: [PATCH 6/8] INSR-8879: Various fixes - Fixed some cases for events for specific parts - Fixed error handling/detection in license plate lookup and vin lookup --- .../license-plate-lookup/license-plate-lookup.vue | 10 ++-------- src/layouts/vehicle-damage/vehicle-damage.vue | 4 ++-- src/layouts/vin-lookup/vin-lookup.vue | 7 +------ src/layouts/vin-lookup/vin-question/vin-question.vue | 4 ++++ 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index 86796e10..aeb58dcb 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -326,14 +326,8 @@ export default { this.displayMatchedDifferentVehicleAlert = false; }, customInvalidSubmit({ errors }) { - if (errors.length > 0) { - const licensePlateError = errors.find( - (error) => error.field === 'license-plate-question' - ); - - if (licensePlateError) { - this.pushEventToGA("VehicleDamage", "LicensePlate_NoMatch", "Plate_Required", true, null, '0'); - } + if (errors['license-plate-question']) { + this.pushEventToGA("VehicleDamage", "LicensePlate_NoMatch", "Plate_Required", true, null, '0'); } this.onInvalidSubmit({ errors }); } diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 82adfde4..08e41a09 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -505,10 +505,10 @@ export default { case damageLocationsSelected.WINDSHIELD: eventGlassLocation = 'Windshield Replace'; break; - case damageLocationsSelected.DRIVERSIDE: + case damageLocationsSelected.DRIVER: eventGlassLocation = "Driver's Side"; break; - case damageLocationsSelected.PASSENGERSIDE: + case damageLocationsSelected.PASSENGER: eventGlassLocation = "Passenger's Side"; break; case damageLocationsSelected.REAR: diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 493683df..af598359 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -291,12 +291,7 @@ export default { this.vehicleFromLookup = null; }, checkVinForErrors() { - const vinQuestionComponent = this.$refs['vin-question']; - if (vinQuestionComponent) { - const errorElement = vinQuestionComponent.$el.querySelector('.form-test-error'); - return errorElement && errorElement.checkVisibility(); - } - return false; + return this.$refs['vin-question'].hasErrors; }, resetDependentState() {} } diff --git a/src/layouts/vin-lookup/vin-question/vin-question.vue b/src/layouts/vin-lookup/vin-question/vin-question.vue index e3553229..8b7c730e 100644 --- a/src/layouts/vin-lookup/vin-question/vin-question.vue +++ b/src/layouts/vin-lookup/vin-question/vin-question.vue @@ -1,6 +1,7 @@