From c7f54b8b7e0d5ab11b219bf0b30b00b3c7bce5ab Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 13 Jul 2023 12:04:01 -0400 Subject: [PATCH 01/46] Initial add of SaveSession --- src/constants/endpoints.js | 270 +++++++++++++++++++------------------ src/store/index.js | 139 +++++++++++++++++-- src/store/store.spec.js | 8 +- 3 files changed, 273 insertions(+), 144 deletions(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index be1ad311..782b7cf4 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -1,136 +1,142 @@ const endpoints = { - GetRouteInfo: { - url: (applicationAbbreviation) => `/content/api/v1/content/${applicationAbbreviation}/RouteInfo`, - method: 'POST' - }, - GetHomepageInfo: { - url: (applicationAbbreviation) => `/content/api/v1/content/${applicationAbbreviation}/HomepageInfo`, - method: 'GET' - }, - GetPageData: { - url: (applicationAbbreviation, pageName) => `/content/api/v1/content/${applicationAbbreviation}/${pageName}`, - method: 'GET' - }, - GetVehicleYears: { - url: '/vehicle/api/v1/vehicle/years', - method: 'GET' - }, - GetVehicleMakes: { - url: '/vehicle/api/v1/vehicle/makes/', - method: 'GET' - }, - GetVehicleModels: { - url: '/vehicle/api/v1/vehicle/models', - method: 'GET' - }, - GetVehicleStyles: { - url: '/vehicle/api/v1/vehicle/styles', - method: 'GET' - }, - GetDamageOptions: { - url: '/parts/api/v1/parts/damage-options', - method: 'GET' - }, - GetPartsOrQuestions: { - url: '/parts/api/v1/parts/parts-or-questions', - method: 'POST' - }, - GetParts: { - url: '/parts/api/v1/parts/parts', - method: 'POST' - }, - GetPriceOrderItems: { - url: '/price/api/v1/price/order-items', - method: 'GET' - }, - GetCapabilityQuestions: { - url: '/parts/api/v1/parts/capability-questions', - method: 'GET' - }, - GetPartFromCapabilityAnswer: { - url: '/parts/api/v1/parts/part-from-capability-answer', - method: 'POST' - }, - GetWipers: { - url: '/parts/api/v1/parts/wipers', - method: 'GET' - }, - GetRainDefense: { - url: '/parts/api/v1/parts/rain-defense', - method: 'GET' - }, - GetSupportingItems: { - url: '/parts/api/v1/parts/supporting-items', - method: 'POST' + GetRouteInfo: { + url: (applicationAbbreviation) => + `/content/api/v1/content/${applicationAbbreviation}/RouteInfo`, + method: 'POST' }, - GetServiceabilityDetails: { - url: "/location/api/v1/location/serviceability-details", - method: "GET", - }, - GetVehicle: { - url: '/vehicle/api/v1/vehicle/lookup', - method: 'GET' - }, - LogExperimentExposureIfAssigned: { - url: '/experiments/api/v1/experiments/log-exposure', - method: 'POST' - }, - LogPageView: { - url: '/analytics/api/v1/analytics/log-page-view', - method: 'POST' - }, - LogCustomEvent: { - url: '/analytics/api/v1/analytics/log-custom-event', - method: 'POST' - }, - LookupVehicleByVin: { - url: '/vehicle/api/v1/vehicle/lookup', - method: 'POST' - }, - LookupVinByAddress: { - url: '/vehicle/api/v1/vehicle/lookup-vin-by-address', - method: 'POST' - }, - LookupVinByPlate: { - url: '/vehicle/api/v1/vehicle/lookup-vin-by-plate', - method: 'POST' - }, - InitializeSession: { - url: '/analytics/api/v1/analytics/initialize', - method: 'POST' - }, - GetExperimentsByUser: { - url: '/analytics/api/v1/analytics/get-experiments', - method: 'GET' - }, - RunExperimentsForTrigger: { - url: '/experiments/api/v1/experiments/run', - method: 'POST' - }, - ValidateZip: { - url: '/location/api/v1/location/zip', - method: 'GET' - }, - GooglePlaces: { - url: 'https://maps.googleapis.com/maps/api/js?key={apiKey}&libraries=places' - }, - ValidateClientTag: { - url: '/clientauth/api/v1/clientauth/validate-client-tag', - method: 'GET' - }, - IsVinbyAddressPermissible:{ - url:'/vehicle/api/v1/vehicle/is-vin-by-address-permissible', - method:'Get' - }, - CoveragePolicyInfo: { - url: '/coverage/api/v1/coverage/get-policy-information', - method: 'POST' - }, - RegisterClaim: { - url: '/coverage/api/v1/coverage/register-claim', - method: 'POST' - } + GetHomepageInfo: { + url: (applicationAbbreviation) => + `/content/api/v1/content/${applicationAbbreviation}/HomepageInfo`, + method: 'GET' + }, + GetPageData: { + url: (applicationAbbreviation, pageName) => + `/content/api/v1/content/${applicationAbbreviation}/${pageName}`, + method: 'GET' + }, + GetVehicleYears: { + url: '/vehicle/api/v1/vehicle/years', + method: 'GET' + }, + GetVehicleMakes: { + url: '/vehicle/api/v1/vehicle/makes/', + method: 'GET' + }, + GetVehicleModels: { + url: '/vehicle/api/v1/vehicle/models', + method: 'GET' + }, + GetVehicleStyles: { + url: '/vehicle/api/v1/vehicle/styles', + method: 'GET' + }, + GetDamageOptions: { + url: '/parts/api/v1/parts/damage-options', + method: 'GET' + }, + GetPartsOrQuestions: { + url: '/parts/api/v1/parts/parts-or-questions', + method: 'POST' + }, + GetParts: { + url: '/parts/api/v1/parts/parts', + method: 'POST' + }, + GetPriceOrderItems: { + url: '/price/api/v1/price/order-items', + method: 'GET' + }, + GetCapabilityQuestions: { + url: '/parts/api/v1/parts/capability-questions', + method: 'GET' + }, + GetPartFromCapabilityAnswer: { + url: '/parts/api/v1/parts/part-from-capability-answer', + method: 'POST' + }, + GetWipers: { + url: '/parts/api/v1/parts/wipers', + method: 'GET' + }, + GetRainDefense: { + url: '/parts/api/v1/parts/rain-defense', + method: 'GET' + }, + GetSupportingItems: { + url: '/parts/api/v1/parts/supporting-items', + method: 'POST' + }, + GetServiceabilityDetails: { + url: '/location/api/v1/location/serviceability-details', + method: 'GET' + }, + GetVehicle: { + url: '/vehicle/api/v1/vehicle/lookup', + method: 'GET' + }, + LogExperimentExposureIfAssigned: { + url: '/experiments/api/v1/experiments/log-exposure', + method: 'POST' + }, + LogPageView: { + url: '/analytics/api/v1/analytics/log-page-view', + method: 'POST' + }, + LogCustomEvent: { + url: '/analytics/api/v1/analytics/log-custom-event', + method: 'POST' + }, + LookupVehicleByVin: { + url: '/vehicle/api/v1/vehicle/lookup', + method: 'POST' + }, + LookupVinByAddress: { + url: '/vehicle/api/v1/vehicle/lookup-vin-by-address', + method: 'POST' + }, + LookupVinByPlate: { + url: '/vehicle/api/v1/vehicle/lookup-vin-by-plate', + method: 'POST' + }, + InitializeSession: { + url: '/analytics/api/v1/analytics/initialize', + method: 'POST' + }, + GetExperimentsByUser: { + url: '/analytics/api/v1/analytics/get-experiments', + method: 'GET' + }, + RunExperimentsForTrigger: { + url: '/experiments/api/v1/experiments/run', + method: 'POST' + }, + ValidateZip: { + url: '/location/api/v1/location/zip', + method: 'GET' + }, + GooglePlaces: { + url: 'https://maps.googleapis.com/maps/api/js?key={apiKey}&libraries=places' + }, + ValidateClientTag: { + url: '/clientauth/api/v1/clientauth/validate-client-tag', + method: 'GET' + }, + IsVinbyAddressPermissible:{ + url: '/vehicle/api/v1/vehicle/is-vin-by-address-permissible', + method: 'Get' + }, + CoveragePolicyInfo: { + url: '/coverage/api/v1/coverage/get-policy-information', + method: 'POST' + }, + RegisterClaim: { + url: '/coverage/api/v1/coverage/register-claim', + method: 'POST' + }, + SaveSession: { + url: '/order/api/v1/order/save-session', + method: 'POST' + } }; - + export { endpoints }; - \ No newline at end of file diff --git a/src/store/index.js b/src/store/index.js index f04f4c68..d1b7f508 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,3 +1,5 @@ +/* eslint-disable no-shadow */ +/* eslint-disable no-use-before-define */ /* eslint-disable max-len */ import { defineStore } from 'pinia'; import { endpoints } from '@/constants/endpoints'; @@ -16,6 +18,7 @@ const storeId = 'main'; const getDefaultState = () => ({ order: { + // Same as FMG vehicle: { year: null, make: null, @@ -37,6 +40,7 @@ const getDefaultState = () => lastName: null } }, + // Same as FMG damage: { isRepair: null, numberOfChips: null, @@ -45,6 +49,7 @@ const getDefaultState = () => moldingQuestionAnswers: null, capabilityQuestionAnswers: null }, + // DNE in FMG policy: { policyNumber: null, policyZipCode: null, @@ -59,6 +64,7 @@ const getDefaultState = () => replace: null // numerical value; how much customer owes on deductible in replace case, } }, + // FMG only has email customer: { address: { streetAddress: null, @@ -72,6 +78,7 @@ const getDefaultState = () => emailAddress: null, phoneNumber: null }, + // Many more details in FMG serviceLocation: { address: null, city: null, @@ -79,21 +86,24 @@ const getDefaultState = () => zipCode: null, zipCodeCtu: null }, + // otherParts vs serverData lineItems: { glassParts: null, - otherParts: null, + otherParts: null, // TODO what is this? supportingItems: null, - vaps: null + vaps: null, + serverData: null // TODO what is this for and should it be added? }, + // Add parent account number from FMG payment: { isInsurance: true, insuranceCoverage: { isVerified: false, coverageStatus: coverageStatuses.PENDING - } + }, + parentAccountNumber: 0 // TODO what is this for and where set? }, - referralNumber: null, - referralDate: null, + // DNE in FMG contactInfo: { firstName: null, lastName: null, @@ -101,7 +111,18 @@ const getDefaultState = () => phoneNumber: null, requestTextUpdates: false, notesForTechnician: '' - } + }, + schedule: { + date: null, + startTime: null, + endTime: null, + routeCode: null, + jobMaxMinutes: null + }, + referralNumber: null, + referralDate: null, + referralCorrelationId: null, // TODO when is this set + eon: null // TODO what is this }, applicationUser: { experiments: [], @@ -679,6 +700,108 @@ export const useMainStore = defineStore({ }); }, + saveSession() { + // TODO use pieces of actual store + const { vehicle, damage, order, applicationUser, lineItems } = this.order; + + // TODO what does this method do + const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace); + + return globalMethods.callHttpClient({ + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + // TODO update with payload for our store + payload: { + applicationUser: { + crmCustomerId: applicationUser.crmCustomerId, + experiments: applicationUser.experiments, + lastPage: applicationUser.lastPageVisited, + pageData: applicationUser.pageData, + savedSessionId: applicationUser.savedSessionId, + }, + order: { + vehicle: { + carId: vehicle.carId, + year: vehicle.year, + make: vehicle.make, + model: vehicle.model, + style: vehicle.style, + vin: vehicle.vin, + registration: { + firstName: vehicle.registration.firstName, + lastName: vehicle.registration.lastName, + streetAddress: vehicle.registration.address, + city: vehicle.registration.city, + state: vehicle.registration.state, + zipCode: vehicle.registration.zipCode, + licensePlateNumber: vehicle.registration.licensePlate, + }, + }, + customer: { + emailAddress: order.customer.emailAddress, + }, + damage: { + numberOfChips: damage.numberOfChips, + glassToReplace: newGlassToReplace, + isRepair: damage.isRepair, + partQuestionAnswers: order.damage.partQuestionAnswers, + moldingQuestionAnswers: order.damage.moldingQuestionAnswers, + capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers, + }, + lineItems: { + glassParts: lineItems.glassParts, + supportingItems: lineItems.supportingItems, + vaps: lineItems.vaps, + serverData: lineItems.serverData, + }, + payment: { + InsuranceCoverage: { + isVerified: order.payment.insuranceCoverage.isVerified ?? false, + }, + isInsurance: order.payment.isInsurance ?? false, + parentAccountNumber: order.payment.parentAccountNumber, + }, + serviceLocation: { + streetAddress: order.serviceLocation.address, + streetAddress2: order.serviceLocation.address2, + city: order.serviceLocation.city, + state: order.serviceLocation.state, + zipCode: order.serviceLocation.zipCode, + zipCodeCtu: order.serviceLocation.zipCodeCtu, + appointmentType: order.serviceLocation.appointmentType, + isVehicleProtected: order.serviceLocation.isVehicleProtected, + provider: { + providerNumber: order.serviceLocation.provider?.providerNumber, + address: { + streetAddress: + order.serviceLocation.provider?.address?.streetAddress, + city: order.serviceLocation.provider?.address?.city, + state: order.serviceLocation.provider?.address?.state, + zipCode: order.serviceLocation.provider?.address?.zipCode, + zipCodeCtu: order.serviceLocation.provider?.address?.zipCodeCtu, + }, + }, + }, + schedule: { + date: order.schedule?.date, + startTime: order.schedule?.startTime, + endTime: order.schedule?.endTime, + routeCode: order.schedule?.routeCode, + jobMaxMinutes: order.schedule?.jobMaxMinutes, + }, + existingPromoCode: null, + referralCorrelationId: order.referralCorrelationId, + referralDate: order.referralDate, + referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place + referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it + eon: order.eon + } + }, + additionalSuccessEventDataHandler: (response) => + `Email provided: ${order.customer.emailAddress ? 'true' : 'false'}` + }); + }, + saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); const isGlassToReplaceTheSame @@ -1177,14 +1300,14 @@ export const useMainStore = defineStore({ }, async validateZip({ zip }) { - return await globalMethods.callHttpClient({ + return globalMethods.callHttpClient({ methods: endpoints.ValidateZip.method, endpoint: `${endpoints.ValidateZip.url}/${zip}` }); }, async validateClientTag(clientTag) { - return await globalMethods.callHttpClient({ + return globalMethods.callHttpClient({ methods: endpoints.ValidateClientTag.method, endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}` }); diff --git a/src/store/store.spec.js b/src/store/store.spec.js index da26b1ac..8a629fdc 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -7,11 +7,10 @@ import { getRandomString, getRandomGuid, getRandomInt, getRandomBoolean } from ' import { coverageStatuses } from "@/constants/coverage-statuses.js"; describe("Store", () => { - let store; const vueApp = createApp(App); - + beforeEach(() => { const pinia = createPinia(); setActivePinia(pinia); @@ -20,8 +19,7 @@ describe("Store", () => { store.applicationUser.eventBus = []; jest.resetAllMocks(); }); - - + it("Should Store Vehicle Year", () => { let testYear = "2001"; store.updateVehicleYear(testYear); @@ -463,4 +461,6 @@ describe("Store", () => { expect(store.contactInfo.notesForTechnician).toEqual(''); }); }); + // TODO add tests + describe('saveSession method', () => {}); }); From 242b947b14bae0194b6f43d2b3c74bc760fd51d4 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Fri, 14 Jul 2023 08:38:08 -0400 Subject: [PATCH 02/46] Adding consumer model to save session --- src/store/index.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index d1b7f508..96cda682 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -720,6 +720,7 @@ export const useMainStore = defineStore({ savedSessionId: applicationUser.savedSessionId, }, order: { + // done vehicle: { carId: vehicle.carId, year: vehicle.year, @@ -737,9 +738,7 @@ export const useMainStore = defineStore({ licensePlateNumber: vehicle.registration.licensePlate, }, }, - customer: { - emailAddress: order.customer.emailAddress, - }, + // done damage: { numberOfChips: damage.numberOfChips, glassToReplace: newGlassToReplace, @@ -748,6 +747,13 @@ export const useMainStore = defineStore({ moldingQuestionAnswers: order.damage.moldingQuestionAnswers, capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers, }, + customer: { + emailAddress: order.customer.emailAddress, + firstName: order.customer.firstName, + lastName: order.customer.lastName, + phoneNumber: order.customer.phone, // TODO contact info or customer? + optInSms: order.contactInfo.requestTextUpdates + }, lineItems: { glassParts: lineItems.glassParts, supportingItems: lineItems.supportingItems, From 244b098dcf6c49ec56e67cd3ddf92f23b6c4c7db Mon Sep 17 00:00:00 2001 From: brydon1 Date: Fri, 14 Jul 2023 10:46:59 -0400 Subject: [PATCH 03/46] Removing trailing commas --- src/store/index.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 96cda682..648832b9 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -65,6 +65,7 @@ const getDefaultState = () => } }, // FMG only has email + // CSR-1358 and CSR-1359 customer: { address: { streetAddress: null, @@ -92,11 +93,11 @@ const getDefaultState = () => otherParts: null, // TODO what is this? supportingItems: null, vaps: null, - serverData: null // TODO what is this for and should it be added? + serverData: null // TODO add }, // Add parent account number from FMG payment: { - isInsurance: true, + isInsurance: true, // TODO delete; irrelevant to ISS insuranceCoverage: { isVerified: false, coverageStatus: coverageStatuses.PENDING @@ -121,8 +122,7 @@ const getDefaultState = () => }, referralNumber: null, referralDate: null, - referralCorrelationId: null, // TODO when is this set - eon: null // TODO what is this + eon: null // TODO add }, applicationUser: { experiments: [], @@ -717,7 +717,7 @@ export const useMainStore = defineStore({ experiments: applicationUser.experiments, lastPage: applicationUser.lastPageVisited, pageData: applicationUser.pageData, - savedSessionId: applicationUser.savedSessionId, + savedSessionId: applicationUser.savedSessionId }, order: { // done @@ -735,8 +735,8 @@ export const useMainStore = defineStore({ city: vehicle.registration.city, state: vehicle.registration.state, zipCode: vehicle.registration.zipCode, - licensePlateNumber: vehicle.registration.licensePlate, - }, + licensePlateNumber: vehicle.registration.licensePlate + } }, // done damage: { @@ -745,14 +745,14 @@ export const useMainStore = defineStore({ isRepair: damage.isRepair, partQuestionAnswers: order.damage.partQuestionAnswers, moldingQuestionAnswers: order.damage.moldingQuestionAnswers, - capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers, + capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers }, customer: { - emailAddress: order.customer.emailAddress, - firstName: order.customer.firstName, - lastName: order.customer.lastName, - phoneNumber: order.customer.phone, // TODO contact info or customer? - optInSms: order.contactInfo.requestTextUpdates + emailAddress: order.contactInfo.emailAddress ?? order.customer.emailAddress, + firstName: order.contactInfo.firstName ?? order.customer.firstName, + lastName: order.contactInfo.lastName ?? order.customer.lastName, + phoneNumber: order.contactInfo.phoneNumber ?? order.customer.phoneNumber, // TODO contact info or customer? + optInSms: order.contactInfo.requestTextUpdates ?? false }, lineItems: { glassParts: lineItems.glassParts, From cbb80a0cd54bf990370b754ce971a1f9b07ee555 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 20 Jul 2023 14:37:19 -0400 Subject: [PATCH 04/46] Partial work --- src/store/index.js | 81 +++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 0e662b91..a490ac86 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,16 +2,16 @@ /* eslint-disable no-use-before-define */ /* eslint-disable max-len */ import { defineStore } from 'pinia'; -import { endpoints } from '@/constants/endpoints'; +import { endpoints } from '@/constants/endpoints.js'; // eslint-disable-next-line import/no-cycle -import { getDateForSavedSessionTimeout } from '@/helpers/session-helper'; +import { getDateForSavedSessionTimeout } from '@/helpers/session-helper.js'; // eslint-disable-next-line import/no-cycle -import globalMethods from '@/global-methods'; -import { experimentTriggers } from '@/constants/experiments'; -import { applicationConfig } from '@/constants/application-config'; -import { issPageValues } from '@/router/router-constants/issPage-values'; -import { damageLocationsSelected } from '@/constants/damage-locations-selected'; -import { coverageStatuses } from '@/constants/coverage-statuses'; +import globalMethods from '@/global-methods.js'; +import { experimentTriggers } from '@/constants/experiments.js'; +import { applicationConfig } from '@/constants/application-config.js'; +import { issPageValues } from '@/router/router-constants/issPage-values.js'; +import { damageLocationsSelected } from '@/constants/damage-locations-selected.js'; +import { coverageStatuses } from '@/constants/coverage-statuses.js'; const storeId = 'main'; @@ -121,8 +121,7 @@ const getDefaultState = () => jobMaxMinutes: null }, referralNumber: null, - referralDate: null, - eon: null // TODO add + referralDate: null }, applicationUser: { experiments: [], @@ -709,7 +708,7 @@ export const useMainStore = defineStore({ saveSession() { // TODO use pieces of actual store - const { vehicle, damage, order, applicationUser, lineItems } = this.order; + const { vehicle, damage, policy, order, applicationUser, lineItems } = this.order; // TODO what does this method do const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace); @@ -717,8 +716,8 @@ export const useMainStore = defineStore({ return globalMethods.callHttpClient({ method: endpoints.SaveSession.method, endpoint: endpoints.SaveSession.url, - // TODO update with payload for our store payload: { + // done applicationUser: { crmCustomerId: applicationUser.crmCustomerId, experiments: applicationUser.experiments, @@ -754,46 +753,48 @@ export const useMainStore = defineStore({ moldingQuestionAnswers: order.damage.moldingQuestionAnswers, capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers }, + policy: { + policyNumber: policy.policyNumber, + policyZipCode: policy.policyZipCode, + dateOfLoss: policy.dateOfLoss, + damageCause: policy.damageCause, + damageState: policy.damageState, + damageCity: policy.damageCity, + isDamageGlassOnly: policy.isDamageGlassOnly, + noCoverage: policy.noCoverage + // deductible: { + // repair: policy.deductible.repair, + // replace: policy.deductible.replace + // } + }, + // NOTE using only customer info for now; ignoring contact details customer: { - emailAddress: order.contactInfo.emailAddress ?? order.customer.emailAddress, - firstName: order.contactInfo.firstName ?? order.customer.firstName, - lastName: order.contactInfo.lastName ?? order.customer.lastName, - phoneNumber: order.contactInfo.phoneNumber ?? order.customer.phoneNumber, // TODO contact info or customer? + emailAddress: order.customer.emailAddress, + firstName: order.customer.firstName, + lastName: order.customer.lastName, + phoneNumber: order.customer.phoneNumber, optInSms: order.contactInfo.requestTextUpdates ?? false }, lineItems: { glassParts: lineItems.glassParts, + otherData: lineItems.otherData, supportingItems: lineItems.supportingItems, - vaps: lineItems.vaps, - serverData: lineItems.serverData, + vaps: lineItems.vaps }, payment: { InsuranceCoverage: { isVerified: order.payment.insuranceCoverage.isVerified ?? false, + coverageStatus: order.payment.insuranceCoverage.coverageStatus }, - isInsurance: order.payment.isInsurance ?? false, - parentAccountNumber: order.payment.parentAccountNumber, + isInsurance: order.payment.isInsurance ?? true, + parentAccountNumber: order.payment.parentAccountNumber }, serviceLocation: { streetAddress: order.serviceLocation.address, - streetAddress2: order.serviceLocation.address2, city: order.serviceLocation.city, state: order.serviceLocation.state, zipCode: order.serviceLocation.zipCode, - zipCodeCtu: order.serviceLocation.zipCodeCtu, - appointmentType: order.serviceLocation.appointmentType, - isVehicleProtected: order.serviceLocation.isVehicleProtected, - provider: { - providerNumber: order.serviceLocation.provider?.providerNumber, - address: { - streetAddress: - order.serviceLocation.provider?.address?.streetAddress, - city: order.serviceLocation.provider?.address?.city, - state: order.serviceLocation.provider?.address?.state, - zipCode: order.serviceLocation.provider?.address?.zipCode, - zipCodeCtu: order.serviceLocation.provider?.address?.zipCodeCtu, - }, - }, + zipCodeCtu: order.serviceLocation.zipCodeCtu }, schedule: { date: order.schedule?.date, @@ -802,14 +803,14 @@ export const useMainStore = defineStore({ routeCode: order.schedule?.routeCode, jobMaxMinutes: order.schedule?.jobMaxMinutes, }, - existingPromoCode: null, - referralCorrelationId: order.referralCorrelationId, referralDate: order.referralDate, - referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place - referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it - eon: order.eon + referralNumber: order.referralNumber?.toString(), + // TODO set + originalDeductible: 0, + currentDeductible: 0 } }, + // TODO maybe modify additionalSuccessEventDataHandler: (response) => `Email provided: ${order.customer.emailAddress ? 'true' : 'false'}` }); From 0ba2a79d5feb2a8ab64184a99e116791be1adc4c Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 24 Jul 2023 14:22:37 -0400 Subject: [PATCH 05/46] Finalizing --- src/store/index.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index a490ac86..67fad3d6 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -762,17 +762,14 @@ export const useMainStore = defineStore({ damageCity: policy.damageCity, isDamageGlassOnly: policy.isDamageGlassOnly, noCoverage: policy.noCoverage - // deductible: { - // repair: policy.deductible.repair, - // replace: policy.deductible.replace - // } }, - // NOTE using only customer info for now; ignoring contact details + // TODO incorporate name and email contact details where appropriate customer: { emailAddress: order.customer.emailAddress, firstName: order.customer.firstName, lastName: order.customer.lastName, - phoneNumber: order.customer.phoneNumber, + policyPhoneNumber: order.customer.phoneNumber, + smsPhoneNumber: order.contactInfo.requestTextUpdates ? order.contactInfo.phoneNumber : null, optInSms: order.contactInfo.requestTextUpdates ?? false }, lineItems: { @@ -787,7 +784,7 @@ export const useMainStore = defineStore({ coverageStatus: order.payment.insuranceCoverage.coverageStatus }, isInsurance: order.payment.isInsurance ?? true, - parentAccountNumber: order.payment.parentAccountNumber + parentAccountNumber: this.issConfig.accountNumber }, serviceLocation: { streetAddress: order.serviceLocation.address, @@ -801,13 +798,12 @@ export const useMainStore = defineStore({ startTime: order.schedule?.startTime, endTime: order.schedule?.endTime, routeCode: order.schedule?.routeCode, - jobMaxMinutes: order.schedule?.jobMaxMinutes, + jobMaxMinutes: order.schedule?.jobMaxMinutes }, referralDate: order.referralDate, referralNumber: order.referralNumber?.toString(), - // TODO set - originalDeductible: 0, - currentDeductible: 0 + originalDeductible: order.originalDeductible, + currentDeductible: order.currentDeductible } }, // TODO maybe modify From 20ca807c37ae830802f4d81d104d1e77527bba6c Mon Sep 17 00:00:00 2001 From: brydon1 Date: Fri, 28 Jul 2023 16:00:37 -0400 Subject: [PATCH 06/46] Adding content to save session request --- src/store/index.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/store/index.js b/src/store/index.js index 67fad3d6..2ff0dc8a 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -734,6 +734,9 @@ export const useMainStore = defineStore({ model: vehicle.model, style: vehicle.style, vin: vehicle.vin, + imageUrl: vehicle.imageUrl, + imageVifColor: vehicle.imageColor, + imageVifNumber: vehicle.imageVifNumber, registration: { firstName: vehicle.registration.firstName, lastName: vehicle.registration.lastName, @@ -765,6 +768,13 @@ export const useMainStore = defineStore({ }, // TODO incorporate name and email contact details where appropriate customer: { + address: { + streetAddress: order.customer.address.streetAddress, + streetAddress2: order.customer.address.streetAddress2, + city: order.customer.address.city, + state: order.customer.address.state, + zipCode: order.customer.address.zipCode + }, emailAddress: order.customer.emailAddress, firstName: order.customer.firstName, lastName: order.customer.lastName, From 4aa9777260abc21d734118d0ff3afd9fdeebf4f7 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 10 Aug 2023 09:51:40 -0400 Subject: [PATCH 07/46] Updating store --- src/store/index.js | 89 +++++++++++----------------------------------- 1 file changed, 20 insertions(+), 69 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 58693b42..5a545eb6 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -79,68 +79,7 @@ const getDefaultState = () => ({ emailAddress: null, phoneNumber: null }, -<<<<<<< HEAD - - // Many more details in FMG - serviceLocation: { -======= -const getDefaultState = () => ({ - order: { - vehicle: { - registration: { - licensePlate: null, ->>>>>>> 6caff3c296f1e024969552bab3b96862ea26c170 - address: null, - city: null, - state: null, - zipCode: null, -<<<<<<< HEAD - zipCodeCtu: null - }, - // otherParts vs serverData - lineItems: { - glassParts: null, - otherParts: null, // TODO what is this? - supportingItems: null, - vaps: null, - serverData: null // TODO add - }, - // Add parent account number from FMG - payment: { - isInsurance: true, // TODO delete; irrelevant to ISS - insuranceCoverage: { - isVerified: false, - coverageStatus: coverageStatuses.PENDING - }, - parentAccountNumber: 0 // TODO what is this for and where set? - }, - // DNE in FMG - contactInfo: { - firstName: null, - lastName: null, - emailAddress: null, - phoneNumber: null, - requestTextUpdates: false, - notesForTechnician: '' - }, - schedule: { - date: null, - startTime: null, - endTime: null, - routeCode: null, - jobMaxMinutes: null - }, - referralNumber: null, - referralDate: null -======= - firstName: null, - lastName: null - } ->>>>>>> 6caff3c296f1e024969552bab3b96862ea26c170 - }, - - - + // Many more details in FMG serviceLocation: { address: null, city: null, @@ -148,14 +87,16 @@ const getDefaultState = () => ({ zipCode: null, zipCodeCtu: null }, + // otherParts vs serverData lineItems: { glassParts: null, - otherParts: null, + otherParts: null, // TODO what is this? supportingItems: null, vaps: null }, + // Add parent account number from FMG payment: { - isInsurance: true, + isInsurance: true, // TODO delete; irrelevant to ISS insuranceCoverage: { isVerified: false, coverageStatus: coverageStatuses.PENDING @@ -163,6 +104,7 @@ const getDefaultState = () => ({ }, referralNumber: null, referralDate: null, + // DNE in FMG contactInfo: { firstName: null, lastName: null, @@ -170,6 +112,13 @@ const getDefaultState = () => ({ phoneNumber: null, requestTextUpdates: false, notesForTechnician: '' + }, + schedule: { + date: null, + startTime: null, + endTime: null, + routeCode: null, + jobMaxMinutes: null } }, applicationUser: { @@ -801,7 +750,10 @@ export const useMainStore = defineStore({ damageState: policy.damageState, damageCity: policy.damageCity, isDamageGlassOnly: policy.isDamageGlassOnly, - noCoverage: policy.noCoverage + noCoverage: policy.noCoverage, + policyLookupSuccessful: policy.policyLookupSuccessful, + originalDeductible: order.originalDeductible, + currentDeductible: order.currentDeductible }, // TODO incorporate name and email contact details where appropriate customer: { @@ -838,7 +790,8 @@ export const useMainStore = defineStore({ city: order.serviceLocation.city, state: order.serviceLocation.state, zipCode: order.serviceLocation.zipCode, - zipCodeCtu: order.serviceLocation.zipCodeCtu + zipCodeCtu: order.serviceLocation.zipCodeCtu, + techNotes: order.contactInfo.notesForTechnician }, schedule: { date: order.schedule?.date, @@ -848,9 +801,7 @@ export const useMainStore = defineStore({ jobMaxMinutes: order.schedule?.jobMaxMinutes }, referralDate: order.referralDate, - referralNumber: order.referralNumber?.toString(), - originalDeductible: order.originalDeductible, - currentDeductible: order.currentDeductible + referralNumber: order.referralNumber?.toString() } }, // TODO maybe modify From 5cbba40bb173f49aa136bbb13a2d946344447a51 Mon Sep 17 00:00:00 2001 From: DavidAtSafelite Date: Thu, 24 Aug 2023 07:43:10 -0400 Subject: [PATCH 08/46] Linting for the last of the layout pages, mixins and prefer default for navigation-scenarios. --- src/helpers/unit-test-helper.js | 2 +- .../address-lookup/address-lookup.spec.js | 2 +- .../contact-details/contact-details.spec.js | 2 +- .../coverage-statement.spec.js | 2 +- .../coverage-statement/coverage-statement.vue | 2 +- .../license-plate-lookup.spec.js | 2 +- .../policy-holder-details.spec.js | 2 +- .../policy-vehicles/policy-vehicles.spec.js | 2 +- .../provider-preference.spec.js | 2 +- .../tpa-confirmation/tpa-confirmation.vue | 9 +- src/layouts/tpa-search/tpa-search.vue | 8 +- src/layouts/tpa-submit/tpa-submit.vue | 9 +- .../damage-location-question.spec.js | 71 +++---- .../damage-location-question.vue | 2 +- .../replace-options-question.spec.js | 130 ++++++------- .../replace-options-question.vue | 2 +- .../side-door-options.spec.js | 174 +++++++++--------- .../side-door-options/side-door-options.vue | 4 +- .../vehicle-damage/vehicle-damage.spec.js | 2 +- src/layouts/vehicle-damage/vehicle-damage.vue | 29 ++- .../windshield-chip-count-question.spec.js | 46 ++--- .../windshield-chip-count-question.vue | 2 +- .../windshield-damage-type-question.spec.js | 36 ++-- .../windshield-damage-type-question.vue | 2 +- .../windshield-options/windshield-options.vue | 12 +- .../vehicle-lookup/vehicle-lookup.spec.js | 4 +- src/layouts/vehicle-lookup/vehicle-lookup.vue | 39 ++-- .../vin-lookup-methods/vin-lookup-methods.vue | 2 +- .../glass-part-question.spec.js | 59 +++--- .../glass-part-question.vue | 5 +- .../vehicle-parts/vehicle-parts.spec.js | 106 ++++++----- src/layouts/vehicle-parts/vehicle-parts.vue | 11 +- .../vehicle-question/vehicle-question.vue | 2 +- .../vehicle-selection/vehicle-selection.vue | 22 +-- .../vin-location-information.vue | 2 +- .../perfect-match-alert.vue | 2 +- .../two-identical-ymm-vehicle-alert.vue | 2 +- .../vehicle-not-found-alert.vue | 2 +- .../vehicle-not-matched-alert.vue | 2 +- .../vin-lookup-alerts.spec.js | 2 +- .../vin-lookup-alerts/vin-lookup-alerts.vue | 8 +- src/layouts/vin-lookup/vin-lookup.spec.js | 52 +++--- src/layouts/vin-lookup/vin-lookup.vue | 5 +- .../vin-lookup/vin-question/vin-question.vue | 2 +- src/layouts/welcome-page/welcome-page.spec.js | 2 +- src/layouts/welcome-page/welcome-page.vue | 59 +++--- src/mixins/analytics-mixin.js | 29 ++- src/mixins/analytics-mixin.spec.js | 3 +- src/mixins/base-form-mixin.js | 17 +- src/mixins/base-mixin.js | 2 +- src/mixins/experiment-mixin.spec.js | 67 +++---- src/mixins/vehicle-questions-mixin.js | 15 +- src/mixins/vehicle-questions-mixin.spec.js | 89 ++++----- src/mixins/vin-pages-mixin.spec.js | 1 + .../dynamic-routing/component-loader.js | 2 +- src/router/index.js | 4 +- .../router-constants/navigation-scenarios.js | 6 +- src/router/router-constants/routing-table.js | 2 +- src/router/router.spec.js | 2 +- 59 files changed, 602 insertions(+), 583 deletions(-) diff --git a/src/helpers/unit-test-helper.js b/src/helpers/unit-test-helper.js index 76029faa..2bcfc8af 100644 --- a/src/helpers/unit-test-helper.js +++ b/src/helpers/unit-test-helper.js @@ -1,6 +1,6 @@ import { RouterLinkStub } from '@vue/test-utils'; import { createTestingPinia } from '@pinia/testing'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios.js'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; import vehicleCategories from '@/constants/vehicle-categories.js'; import issPageValues from '@/router/router-constants/issPage-values'; import cookieNames from '@/constants/cookie-names'; diff --git a/src/layouts/address-lookup/address-lookup.spec.js b/src/layouts/address-lookup/address-lookup.spec.js index 0aef1ab5..a891af3e 100644 --- a/src/layouts/address-lookup/address-lookup.spec.js +++ b/src/layouts/address-lookup/address-lookup.spec.js @@ -6,7 +6,7 @@ import { settleAllPromises } from '@/helpers/layout-helper.js'; import { shallowMount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios'; jest.mock('@/helpers/damage-helper', () => ({ isGlassAvailableForCarId: jest.fn().mockImplementation(() => true), diff --git a/src/layouts/contact-details/contact-details.spec.js b/src/layouts/contact-details/contact-details.spec.js index 5f6440fc..c6938e58 100644 --- a/src/layouts/contact-details/contact-details.spec.js +++ b/src/layouts/contact-details/contact-details.spec.js @@ -6,7 +6,7 @@ import { shallowMount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { getRandomString, getRandomInt, getRandomBoolean } from '@/helpers/data-generation.js'; import { createTestingPinia } from '@pinia/testing'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios.js'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; import { useMainStore } from '@/store/index.js'; describe('contactDetails.vue', () => { diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js index ba1a6dd1..fea224c5 100644 --- a/src/layouts/coverage-statement/coverage-statement.spec.js +++ b/src/layouts/coverage-statement/coverage-statement.spec.js @@ -5,7 +5,7 @@ import coverageStatement from '@/layouts/coverage-statement/coverage-statement.v import { mount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { createTestingPinia } from '@pinia/testing'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios.js'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; import { getRandomString, getRandomInt } from '@/helpers/data-generation.js'; import { settleAllPromises } from '@/helpers/layout-helper.js'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 08647f77..c1c6cb3b 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -119,7 +119,7 @@ import { useMainStore } from '@/store/index.js'; import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js'; import globalRules from '@/constants/global-rules.js'; import baseFormMixin from '@/mixins/base-form-mixin.js'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios.js'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; export default { name: 'coverage-statement', 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 35e57491..8705494c 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.spec.js +++ b/src/layouts/license-plate-lookup/license-plate-lookup.spec.js @@ -6,7 +6,7 @@ import { settleAllPromises } from '@/helpers/layout-helper.js'; import { shallowMount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios'; jest.mock('@/helpers/damage-helper', () => ({ isGlassAvailableForCarId: jest.fn().mockImplementation(() => true), diff --git a/src/layouts/policy-holder-details/policy-holder-details.spec.js b/src/layouts/policy-holder-details/policy-holder-details.spec.js index ffcd9931..e36b99a5 100644 --- a/src/layouts/policy-holder-details/policy-holder-details.spec.js +++ b/src/layouts/policy-holder-details/policy-holder-details.spec.js @@ -6,7 +6,7 @@ import { shallowMount } from '@vue/test-utils'; import { settleAllPromises } from '@/helpers/layout-helper.js'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios'; // Mock our module for promises. jest.mock('@/helpers/layout-helper.js', () => ({ diff --git a/src/layouts/policy-vehicles/policy-vehicles.spec.js b/src/layouts/policy-vehicles/policy-vehicles.spec.js index 4e15c74c..993071aa 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.spec.js +++ b/src/layouts/policy-vehicles/policy-vehicles.spec.js @@ -4,7 +4,7 @@ import { shallowMount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper'; import { useMainStore } from '@/store'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios'; import baseMixin from '@/mixins/base-mixin'; import { getRandomString, getRandomInt } from '@/helpers/data-generation'; import endorsementOptions from '@/constants/endorsement-options'; diff --git a/src/layouts/provider-preference/provider-preference.spec.js b/src/layouts/provider-preference/provider-preference.spec.js index e4cce112..1857b749 100644 --- a/src/layouts/provider-preference/provider-preference.spec.js +++ b/src/layouts/provider-preference/provider-preference.spec.js @@ -5,7 +5,7 @@ import { settleAllPromises } from '@/helpers/layout-helper.js'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; -import { navigationScenarios } from '@/router/router-constants/navigation-scenarios'; +import navigationScenarios from '@/router/router-constants/navigation-scenarios'; // Mock our module for promises. jest.mock('@/helpers/layout-helper.js', () => ({ diff --git a/src/layouts/tpa-confirmation/tpa-confirmation.vue b/src/layouts/tpa-confirmation/tpa-confirmation.vue index a59222eb..0fde2bcc 100644 --- a/src/layouts/tpa-confirmation/tpa-confirmation.vue +++ b/src/layouts/tpa-confirmation/tpa-confirmation.vue @@ -3,7 +3,7 @@ ref="theForm" v-slot="{ meta }" @submit="onSubmit" - @invalid-submit="onInvalidSubmit"> + @invalidSubmit="onInvalidSubmit">
@@ -14,7 +14,7 @@ cmsWidgetName="SiteFooterWidget" :isForwardActionDisabled="!meta.valid" @ForwardClicked="forwardButtonAction" - @back-clicked="backButtonAction" /> + @backClicked="backButtonAction" />
@@ -22,8 +22,8 @@ + + diff --git a/src/router/index.js b/src/router/index.js index bcf2fd46..1b2e8ace 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ import { createWebHistory, createRouter } from 'vue-router'; import lazyLoadComponent from '@/router/dynamic-routing/component-loader'; import issPageValues from '@/router/router-constants/issPage-values'; @@ -6,11 +7,8 @@ import { useMainStore } from '@/store'; import eventBus from '@/helpers/event-bus/event-bus'; import { globalEvents, globalEventTypes } from '@/constants/events'; import baseMixin from '@/mixins/base-mixin'; -import { - getDeviceIdValue, - updateOrCreateISSCookie, - updateSessionIdCookie -} from '@/helpers/cookie-helper'; +import { isSavedSessionStillActive } from '@/helpers/session-helper'; +import { getDeviceIdValue, getISSCookie, updateOrCreateISSCookie, updateSessionIdCookie } from '@/helpers/cookie-helper'; import { experimentTriggers } from '@/constants/experiments'; import applicationConfig from '@/constants/application-config'; @@ -23,29 +21,52 @@ const routes = [ name: 'root', async beforeEnter(to, from, next) { try { - to.query.issPage = !to.query.issPage - ? issPageValues.WELCOME_PAGE - : to.query.issPage; + const issPageToUse = !to.query.issPage ? issPageValues.WELCOME_PAGE : to.query.issPage; + + if ((issPageToUse === issPageValues.ACCESS_DENIED + || (issPageToUse !== issPageValues.ENTRY_PAGE && !useMainStore().issConfig.accountNumber)) + && process.env.VUE_APP_CURRENT_ENVIRONMENT !== 'Localhost' + ) { + return await GoToAccessIsDenied(next); + } // Do not run these for the main entry page - as it is not part of the user flow. - if (to.query.issPage !== issPageValues.ENTRY_PAGE) { + if (issPageToUse !== issPageValues.ENTRY_PAGE) { if (analyticsMixin.methods.noSession()) { await analyticsMixin.methods.initSession(); } else { updateSessionIdCookie(); } - await runExperiments(to.query.issPage); + await runExperiments(issPageToUse); // fmg has this further down + } + + // If the saved session has timed out, clear the session, execute 404 logic. + if (getISSCookie() !== null && !isSavedSessionStillActive()) { + // await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE); + await GoToStartOn404(next); } // Process ISS cookie. updateOrCreateISSCookie(); - if (router.hasRoute(to.query.issPage)) { - return next({ name: to.query.issPage, query: to.query, params: to.params }); + if (router.hasRoute(issPageToUse)) { + // Since our route is already in scope, we can grab the component and call the arePagePrerequisitesValid function. + let component = router.getRoutes().filter((x) => x.name === issPageToUse)[0].components; + + // If the component hasn't been loaded fully, load it before we check prerequisites. + if (component.default.methods === undefined) { + component = await component.default(); + } + + if (!arePagePrerequisitesValid(component)) { + await GoToStartOn404(next); + } + + return next({ name: issPageToUse, query: to.query, params: to.params }); } - const routeData = await GetRouteInfoFromPageName(to.query.issPage); + const routeData = await GetRouteInfoFromPageName(issPageToUse); if (routeData[0].name.toLowerCase() === 'error') { throw new Error('Page not found!'); @@ -58,6 +79,19 @@ const routes = [ component: routeData[0].component }); + // Call the next components arePagePrerequisitesValid method before load. + // If it returns false, use the 404 logic. + const nextComponent = await router + .getRoutes() + .filter((x) => x.name === routeData[0].name)[0] + .components.default(); + + if (!arePagePrerequisitesValid(nextComponent)) { + const tempMsgCopy = 'Pre Requisites failed, need to handle. Default is Welcome Page.'; + const tempMsgHeadline = `${issPageToUse}: pre-req failed...`; + await GoToStartOn404(next, tempMsgCopy, tempMsgHeadline); + } + // Assign current query string parameters, as well as our issPage one. next({ name: routeData[0].name, @@ -66,7 +100,7 @@ const routes = [ }); } catch (error) { window.console.warn(error); - GoToStartOn404(next); + await GoToStartOn404(next); } return null; } @@ -76,15 +110,13 @@ const routes = [ const router = createRouter({ history: createWebHistory('/'), routes, - scrollBehavior(to, from, savedPosition) { + scrollBehavior() { // always scroll to top return { top: 0 }; } }); -router.afterEach((to, from) => { - /*eslint-disable-line*/ - +router.afterEach((to) => { const store = useMainStore(); // Update lastPageVisited in the store store.updateLastPageVisited(to.name); @@ -119,36 +151,33 @@ async function GetRouteInfoFromPageName(pageName) { } // Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example. -router.overrideNavigation = (scenario, +router.overrideNavigation = ( + scenario, currentRoute, next, isSavingNavigation, optionalQuery = {}, optionalParams = {}, - optionalPageData) => { - navigate(scenario, - currentRoute, - isSavingNavigation, - optionalQuery, - optionalParams, - optionalPageData); + optionalPageData = {} +) => { + navigate( + scenario, currentRoute, isSavingNavigation, optionalQuery, optionalParams, optionalPageData + ); next(); }; -router.navigate = (scenario, - currentRoute, - optionalQuery = {}, - optionalParams = {}, - optionalPageData = {}) => { - navigate(scenario, currentRoute, optionalQuery, optionalParams, optionalPageData); +router.navigate = ( + scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} +) => { + navigate( + scenario, currentRoute, optionalQuery, optionalParams, optionalPageData + ); }; // Navigate to the next route, depending on the scenario. -function navigate(scenario, - currentRoute, - optionalQuery = {}, - optionalParams = {}, - optionalPageData = {}) { +function navigate( + scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} +) { /*eslint-disable-line*/ if (!scenario) { window.console.error('No scenario provided. Please review the routing table.'); @@ -172,9 +201,7 @@ function navigate(scenario, // Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object const existingPageDataForPage = useMainStore().pageData(matchingScenarioMap.destinationIssPageValue); baseMixin.methods.savePageDataToStore(matchingScenarioMap.destinationIssPageValue, - Object.keys(optionalPageData).length > 0 - ? optionalPageData - : existingPageDataForPage ?? {}); + Object.keys(optionalPageData).length > 0 ? optionalPageData : existingPageDataForPage ?? {}); // We're always pushing the same path, just changing query strings. // Make sure our optional query strings get combined with our issPage one. @@ -194,7 +221,7 @@ function navigate(scenario, function navigateToUrl(url, optionalQuery = {}) { // possibly show some loading screen in the future here. const externalUrl = new URL(url); - // eslint-disable-next-line no-restricted-syntax + // eslint-disable-next-line no-restricted-syntax, guard-for-in for (const queryKey in optionalQuery) { externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]); } @@ -207,9 +234,7 @@ function getNavigationMap(scenario, currentRoute) { const issPageValue = currentRoute.query.issPage; try { const matchedQueryValue = routingTable(useMainStore()) - .filter((item) => - item.issPageValue === issPageValue - && item.maps.filter((map) => map.scenario === scenario).length > 0); + .filter((item) => item.issPageValue === issPageValue && item.maps.filter((map) => map.scenario === scenario).length > 0); const maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined; @@ -220,7 +245,21 @@ function getNavigationMap(scenario, currentRoute) { } } -function GoToStartOn404(next) { +async function GoToAccessIsDenied(next) { + const errorPageName = issPageValues.ACCESS_DENIED; + router.addRoute({ + path: '/', + name: errorPageName, + component: lazyLoadComponent(errorPageName) + }); + + next({ + name: errorPageName, + query: { issPage: errorPageName } + }); +} + +async function GoToStartOn404(next, msgCopy = null, msgHeadline = null) { const errorPageName = issPageValues.WELCOME_PAGE; router.addRoute({ path: '/', @@ -229,14 +268,12 @@ function GoToStartOn404(next) { }); // Put item on the bus - eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT, - globalEvents.SubCategories.PAGE_NOT_FOUND, - { - isDismissible: true, - messageCopy: 'You can get a quote by starting on this page.', - messageHeadline: "We're sorry, something went wrong.", - type: globalEventTypes.Danger - }); + eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.PAGE_NOT_FOUND, { + isDismissible: true, + messageCopy: msgCopy ?? 'You can get a quote by starting on this page.', + messageHeadline: msgHeadline ?? "We're sorry, something went wrong.", + type: globalEventTypes.Danger + }); next({ name: errorPageName, @@ -244,6 +281,11 @@ function GoToStartOn404(next) { }); } +// Checks arePagePrerequisitesValid on the component passed in. +function arePagePrerequisitesValid(component) { + return component.default.methods.arePagePrerequisitesValid === undefined || component.default.methods.arePagePrerequisitesValid(); +} + // Run SiteEntry and PageEntry triggers for experiments async function runExperiments(nextPage) { const store = useMainStore(); diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js index 9ddfab8c..68ad4a08 100644 --- a/src/router/router-constants/issPage-values.js +++ b/src/router/router-constants/issPage-values.js @@ -1,4 +1,5 @@ const issPageValues = Object.freeze({ + ACCESS_DENIED: 'access-denied', ENTRY_PAGE: 'entry-page', WELCOME_PAGE: 'welcome-page', diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 4af22d4f..7830bac3 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -319,6 +319,15 @@ const routingTable = () => [ } ] }, + { + issPageValue: issPageValues.ACCESS_DENIED, + maps: [ + { + scenario: navigationScenarios.CLICKED_BACK, + destinationIssPageValue: issPageValues.ACCESS_DENIED + } + ] + }, { issPageValue: issPageValues.ENTRY_PAGE, maps: [ diff --git a/vue.config.js b/vue.config.js index 5018024e..a13ba34c 100644 --- a/vue.config.js +++ b/vue.config.js @@ -1,14 +1,14 @@ +/* eslint-disable max-len */ process.env.VUE_APP_CONSUMER_CF_DISTRO = 'https://digitalapi.dev.safelite.io'; process.env.VUE_APP_CURRENT_ENVIRONMENT = 'Localhost'; -process.env.VUE_APP_GOOGLE_PLACES_API_KEY - = 'AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0'; +process.env.VUE_APP_GOOGLE_PLACES_API_KEY = 'AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0'; // GA & GTM // NOTE: Using the old ISS site GTM Cotnainer ID for now, will create a new one soon. -process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY - = "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');"; -process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC - = 'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x'; +process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = + "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');"; +process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC = + 'https://www.googletagmanager.com/ns.html?id=GTM-KKNWZ3>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x'; module.exports = { publicPath: '/', From 406476d6a6ce43d2d50e05d7f70a148642f9c7c3 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Mon, 28 Aug 2023 12:32:42 -0400 Subject: [PATCH 12/46] linting update --- .eslintrc.js | 5 +++-- src/router/index.js | 22 ++++++++-------------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c9deb6a3..440245f9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,8 +18,8 @@ module.exports = { 'vue/attribute-hyphenation': ['warn', 'never'], 'vue/v-on-event-hyphenation': ['warn', 'never'], 'object-curly-newline': ['error', { consistent: true }], - 'function-paren-newline': ['error', 'never'], - 'operator-linebreak': ['error', 'before', { overrides: { '=': 'after' }}], + 'function-paren-newline': ['error', 'multiline'], + 'operator-linebreak': ['error', 'before', { overrides: { '=': 'after' } }], 'implicit-arrow-linebreak': ['off'], 'comma-dangle': ['error', 'never'], indent: ['error', 4, { SwitchCase: 1 }], @@ -33,6 +33,7 @@ module.exports = { 'jsdoc/check-tag-names': ['error', { definedTags: ['store', 'endpoint', 'category', 'subcategory', 'remarks'] }], + 'jsdoc/require-jsdoc': 0, 'vue/html-self-closing': ['error', { html: { void: 'any', diff --git a/src/router/index.js b/src/router/index.js index 1b2e8ace..2fa73c97 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -160,24 +160,16 @@ router.overrideNavigation = ( optionalParams = {}, optionalPageData = {} ) => { - navigate( - scenario, currentRoute, isSavingNavigation, optionalQuery, optionalParams, optionalPageData - ); + navigate(scenario, currentRoute, isSavingNavigation, optionalQuery, optionalParams, optionalPageData); next(); }; -router.navigate = ( - scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} -) => { - navigate( - scenario, currentRoute, optionalQuery, optionalParams, optionalPageData - ); +router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) => { + navigate(scenario, currentRoute, optionalQuery, optionalParams, optionalPageData); }; // Navigate to the next route, depending on the scenario. -function navigate( - scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} -) { +function navigate(scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) { /*eslint-disable-line*/ if (!scenario) { window.console.error('No scenario provided. Please review the routing table.'); @@ -200,8 +192,10 @@ function navigate( } else if (matchingScenarioMap.destinationIssPageValue) { // Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object const existingPageDataForPage = useMainStore().pageData(matchingScenarioMap.destinationIssPageValue); - baseMixin.methods.savePageDataToStore(matchingScenarioMap.destinationIssPageValue, - Object.keys(optionalPageData).length > 0 ? optionalPageData : existingPageDataForPage ?? {}); + baseMixin.methods.savePageDataToStore( + matchingScenarioMap.destinationIssPageValue, + Object.keys(optionalPageData).length > 0 ? optionalPageData : existingPageDataForPage ?? {} + ); // We're always pushing the same path, just changing query strings. // Make sure our optional query strings get combined with our issPage one. From 70ef75bbc85a36ce88c1e14253b13c9c230ee754 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Mon, 28 Aug 2023 13:43:59 -0400 Subject: [PATCH 13/46] this.mainStore not available in preReq, some linting --- src/layouts/vehicle-damage/vehicle-damage.vue | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index fc8401eb..63e1a02d 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -138,8 +138,10 @@ export default { next((vm) => { vm.setCmsContent(resultMap.cmsContent); vm.$refs.damageLocation.initializeComponent(resultMap.damageOptions); - vm.$refs.sideDoorOptions.initializeComponent(resultMap.damageOptions.driverSideOptions.availableReplacementOptions, - resultMap.damageOptions.passengerSideOptions.availableReplacementOptions); + vm.$refs.sideDoorOptions.initializeComponent( + resultMap.damageOptions.driverSideOptions.availableReplacementOptions, + resultMap.damageOptions.passengerSideOptions.availableReplacementOptions + ); vm.$refs.windshieldOptions.initializeComponent(resultMap.damageOptions.windshieldOptions.availableReplacementOptions); vm.$refs.backGlassOptions.initializeComponent(resultMap.damageOptions.backGlassOptions.availableReplacementOptions); }); @@ -228,7 +230,7 @@ export default { }, methods: { arePagePrerequisitesValid() { - if (this.mainStore.order.vehicle.carId) { + if (useMainStore().order.vehicle.carId) { return true; } return false; @@ -362,23 +364,22 @@ export default { }, async forwardButtonAction() { - await this.mainStore.saveVehicleDamage(this.isWindshieldRepair, + await this.mainStore.saveVehicleDamage( + this.isWindshieldRepair, this.selectedGlassToReplace(), - this.selectedWindshieldOptions.selectedWindshieldChipCount); + this.selectedWindshieldOptions.selectedWindshieldChipCount + ); return this.navigateForward(); }, navigateForward() { if (this.mainStore.damage.isRepair) { - this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR, - this.$route); + this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR, this.$route); } else if (this.mainStore.order.vehicle.vin) { // If vin already exists, navigate directly to vin-lookup - this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, - this.$route); + this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, this.$route); } else { - this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, - this.$route); + this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, this.$route); } }, From 65ba44105d55f03f65d8d9316d09559a8db160a5 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 13:53:53 -0400 Subject: [PATCH 14/46] Finalizing save session call --- src/store/index.js | 58 ++++++++++++++++++----------------------- src/store/store.spec.js | 2 +- 2 files changed, 26 insertions(+), 34 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 5a545eb6..831bf1fe 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -712,50 +712,42 @@ export const useMainStore = defineStore({ savedSessionId: applicationUser.savedSessionId }, order: { - // done vehicle: { - carId: vehicle.carId, year: vehicle.year, make: vehicle.make, model: vehicle.model, style: vehicle.style, vin: vehicle.vin, - imageUrl: vehicle.imageUrl, - imageVifColor: vehicle.imageColor, - imageVifNumber: vehicle.imageVifNumber, - registration: { - firstName: vehicle.registration.firstName, - lastName: vehicle.registration.lastName, - streetAddress: vehicle.registration.address, - city: vehicle.registration.city, - state: vehicle.registration.state, - zipCode: vehicle.registration.zipCode, - licensePlateNumber: vehicle.registration.licensePlate - } + carId: vehicle.carId, + licensePlateNumber: vehicle.registration.licensePlate }, - // done damage: { numberOfChips: damage.numberOfChips, glassToReplace: newGlassToReplace, isRepair: damage.isRepair, partQuestionAnswers: order.damage.partQuestionAnswers, moldingQuestionAnswers: order.damage.moldingQuestionAnswers, - capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers - }, - policy: { - policyNumber: policy.policyNumber, - policyZipCode: policy.policyZipCode, + capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers, dateOfLoss: policy.dateOfLoss, damageCause: policy.damageCause, damageState: policy.damageState, damageCity: policy.damageCity, - isDamageGlassOnly: policy.isDamageGlassOnly, + isDamageGlassOnly: policy.isDamageGlassOnly + }, + policy: { + policyHolder: { + policyFirstName: order.customer.firstName, + policyLastName: order.customer.lastName, + policyPhoneNumber: order.customer.phoneNumber, + policyEmail: order.customer.emailAddress + }, + policyNumber: policy.policyNumber, + policyZipCode: policy.policyZipCode, noCoverage: policy.noCoverage, policyLookupSuccessful: policy.policyLookupSuccessful, originalDeductible: order.originalDeductible, currentDeductible: order.currentDeductible }, - // TODO incorporate name and email contact details where appropriate customer: { address: { streetAddress: order.customer.address.streetAddress, @@ -764,16 +756,14 @@ export const useMainStore = defineStore({ state: order.customer.address.state, zipCode: order.customer.address.zipCode }, - emailAddress: order.customer.emailAddress, - firstName: order.customer.firstName, - lastName: order.customer.lastName, - policyPhoneNumber: order.customer.phoneNumber, - smsPhoneNumber: order.contactInfo.requestTextUpdates ? order.contactInfo.phoneNumber : null, + emailAddress: order.contactInfo.emailAddress, + firstName: order.contactInfo.firstName, + lastName: order.contactInfo.lastName, + phoneNumber: order.contactInfo.phoneNumber, optInSms: order.contactInfo.requestTextUpdates ?? false }, lineItems: { glassParts: lineItems.glassParts, - otherData: lineItems.otherData, supportingItems: lineItems.supportingItems, vaps: lineItems.vaps }, @@ -786,11 +776,13 @@ export const useMainStore = defineStore({ parentAccountNumber: this.issConfig.accountNumber }, serviceLocation: { - streetAddress: order.serviceLocation.address, - city: order.serviceLocation.city, - state: order.serviceLocation.state, - zipCode: order.serviceLocation.zipCode, - zipCodeCtu: order.serviceLocation.zipCodeCtu, + address: { + streetAddress: order.serviceLocation.address, + city: order.serviceLocation.city, + state: order.serviceLocation.state, + zipCode: order.serviceLocation.zipCode, + zipCodeCtu: order.serviceLocation.zipCodeCtu + }, techNotes: order.contactInfo.notesForTechnician }, schedule: { diff --git a/src/store/store.spec.js b/src/store/store.spec.js index c8be5dbc..a4d02857 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -74,7 +74,7 @@ describe('Store', () => { expect(store.applicationUser.eventBus.length).toBe(1); // Act - store.removeEventFromBus({ category: event.category, subCategory: event.subCategory }) + store.removeEventFromBus({ category: event.category, subCategory: event.subCategory }); // Assert expect(store.applicationUser.eventBus.length).toBe(0); From 521485ad6e02b13ba1f49927956501161bebcd56 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 14:03:09 -0400 Subject: [PATCH 15/46] Cleaning up store --- src/store/index.js | 86 ++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 48 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index f71aa9cd..ed1be634 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -17,7 +17,6 @@ const storeId = 'main'; const getDefaultState = () => ({ order: { - // Same as FMG vehicle: { year: null, make: null, @@ -39,7 +38,6 @@ const getDefaultState = () => ({ lastName: null } }, - // Same as FMG damage: { isRepair: null, numberOfChips: null, @@ -48,7 +46,6 @@ const getDefaultState = () => ({ moldingQuestionAnswers: null, capabilityQuestionAnswers: null }, - // DNE in FMG policy: { policyNumber: null, policyZipCode: null, @@ -64,8 +61,6 @@ const getDefaultState = () => ({ replace: null // numerical value; how much customer owes on deductible in replace case, } }, - // FMG only has email - // CSR-1358 and CSR-1359 customer: { address: { streetAddress: null, @@ -79,7 +74,6 @@ const getDefaultState = () => ({ emailAddress: null, phoneNumber: null }, - // Many more details in FMG serviceLocation: { address: null, city: null, @@ -696,17 +690,14 @@ export const useMainStore = defineStore({ }, saveSession() { - // TODO use pieces of actual store - const { vehicle, damage, policy, order, applicationUser, lineItems } = this.order; - - // TODO what does this method do + const { vehicle, damage, policy, customer, contactInfo, payment, applicationUser, + lineItems, serviceLocation, schedule } = this.order; const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace); return globalMethods.callHttpClient({ method: endpoints.SaveSession.method, endpoint: endpoints.SaveSession.url, payload: { - // done applicationUser: { crmCustomerId: applicationUser.crmCustomerId, experiments: applicationUser.experiments, @@ -728,9 +719,9 @@ export const useMainStore = defineStore({ numberOfChips: damage.numberOfChips, glassToReplace: newGlassToReplace, isRepair: damage.isRepair, - partQuestionAnswers: order.damage.partQuestionAnswers, - moldingQuestionAnswers: order.damage.moldingQuestionAnswers, - capabilityQuestionAnswers: order.damage.capabilityQuestionAnswers, + partQuestionAnswers: damage.partQuestionAnswers, + moldingQuestionAnswers: damage.moldingQuestionAnswers, + capabilityQuestionAnswers: damage.capabilityQuestionAnswers, dateOfLoss: policy.dateOfLoss, damageCause: policy.damageCause, damageState: policy.damageState, @@ -739,31 +730,31 @@ export const useMainStore = defineStore({ }, policy: { policyHolder: { - policyFirstName: order.customer.firstName, - policyLastName: order.customer.lastName, - policyPhoneNumber: order.customer.phoneNumber, - policyEmail: order.customer.emailAddress + policyFirstName: customer.firstName, + policyLastName: customer.lastName, + policyPhoneNumber: customer.phoneNumber, + policyEmail: customer.emailAddress }, policyNumber: policy.policyNumber, policyZipCode: policy.policyZipCode, noCoverage: policy.noCoverage, policyLookupSuccessful: policy.policyLookupSuccessful, - originalDeductible: order.originalDeductible, - currentDeductible: order.currentDeductible + originalDeductible: this.order.originalDeductible, + currentDeductible: this.order.currentDeductible }, customer: { address: { - streetAddress: order.customer.address.streetAddress, - streetAddress2: order.customer.address.streetAddress2, - city: order.customer.address.city, - state: order.customer.address.state, - zipCode: order.customer.address.zipCode + streetAddress: customer.address.streetAddress, + streetAddress2: customer.address.streetAddress2, + city: customer.address.city, + state: customer.address.state, + zipCode: customer.address.zipCode }, - emailAddress: order.contactInfo.emailAddress, - firstName: order.contactInfo.firstName, - lastName: order.contactInfo.lastName, - phoneNumber: order.contactInfo.phoneNumber, - optInSms: order.contactInfo.requestTextUpdates ?? false + emailAddress: contactInfo.emailAddress, + firstName: contactInfo.firstName, + lastName: contactInfo.lastName, + phoneNumber: contactInfo.phoneNumber, + optInSms: contactInfo.requestTextUpdates ?? false }, lineItems: { glassParts: lineItems.glassParts, @@ -772,36 +763,35 @@ export const useMainStore = defineStore({ }, payment: { InsuranceCoverage: { - isVerified: order.payment.insuranceCoverage.isVerified ?? false, - coverageStatus: order.payment.insuranceCoverage.coverageStatus + isVerified: payment.insuranceCoverage.isVerified ?? false, + coverageStatus: payment.insuranceCoverage.coverageStatus }, - isInsurance: order.payment.isInsurance ?? true, + isInsurance: payment.isInsurance ?? true, parentAccountNumber: this.issConfig.accountNumber }, serviceLocation: { address: { - streetAddress: order.serviceLocation.address, - city: order.serviceLocation.city, - state: order.serviceLocation.state, - zipCode: order.serviceLocation.zipCode, - zipCodeCtu: order.serviceLocation.zipCodeCtu + streetAddress: serviceLocation.address, + city: serviceLocation.city, + state: serviceLocation.state, + zipCode: serviceLocation.zipCode, + zipCodeCtu: serviceLocation.zipCodeCtu }, - techNotes: order.contactInfo.notesForTechnician + techNotes: contactInfo.notesForTechnician }, schedule: { - date: order.schedule?.date, - startTime: order.schedule?.startTime, - endTime: order.schedule?.endTime, - routeCode: order.schedule?.routeCode, - jobMaxMinutes: order.schedule?.jobMaxMinutes + date: schedule?.date, + startTime: schedule?.startTime, + endTime: schedule?.endTime, + routeCode: schedule?.routeCode, + jobMaxMinutes: schedule?.jobMaxMinutes }, - referralDate: order.referralDate, - referralNumber: order.referralNumber?.toString() + referralDate: this.order.referralDate, + referralNumber: this.order.referralNumber?.toString() } }, - // TODO maybe modify additionalSuccessEventDataHandler: (response) => - `Email provided: ${order.customer.emailAddress ? 'true' : 'false'}` + `Email provided: ${customer.emailAddress ? 'true' : 'false'}` }); }, From 260287e6a616d987449636789d02455fde87a1c3 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 14:06:46 -0400 Subject: [PATCH 16/46] Call save session with every route --- src/router/index.js | 1 + src/store/index.js | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index bcf2fd46..44e5e5a8 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -88,6 +88,7 @@ router.afterEach((to, from) => { const store = useMainStore(); // Update lastPageVisited in the store store.updateLastPageVisited(to.name); + store.saveSession(); if (to.query.issPage !== issPageValues.ENTRY_PAGE) { // Push page view to GA diff --git a/src/store/index.js b/src/store/index.js index ed1be634..bc3d8566 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -81,10 +81,9 @@ const getDefaultState = () => ({ zipCode: null, zipCodeCtu: null }, - // otherParts vs serverData lineItems: { glassParts: null, - otherParts: null, // TODO what is this? + otherParts: null, supportingItems: null, vaps: null }, @@ -98,7 +97,6 @@ const getDefaultState = () => ({ }, referralNumber: null, referralDate: null, - // DNE in FMG contactInfo: { firstName: null, lastName: null, From 845604bd0fa2acb07041f0e42fe467a5218a7cf3 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 14:08:18 -0400 Subject: [PATCH 17/46] Updating save session endpoint --- src/constants/endpoints.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 925fde7a..a213e2f4 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -131,7 +131,7 @@ const endpoints = Object.freeze({ method: 'POST' }, SaveSession: { - url: '/order/api/v1/order/save-session', + url: '/order/api/v1/order/save-session/iss', method: 'POST' } }); From e8a1f9f17951256917ddd7cb95923cc835beef65 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 14:10:10 -0400 Subject: [PATCH 18/46] Reverting needless updated --- src/store/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index bc3d8566..4c8603e0 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -2,9 +2,9 @@ /* eslint-disable no-use-before-define */ /* eslint-disable max-len */ import { defineStore } from 'pinia'; -import { endpoints } from '@/constants/endpoints.js'; +import { endpoints } from '@/constants/endpoints'; // eslint-disable-next-line import/no-cycle -import { getDateForSavedSessionTimeout } from '@/helpers/session-helper.js'; +import { getDateForSavedSessionTimeout } from '@/helpers/session-helper'; // eslint-disable-next-line import/no-cycle import globalMethods from '@/global-methods'; import { experimentTriggers } from '@/constants/experiments'; @@ -87,7 +87,6 @@ const getDefaultState = () => ({ supportingItems: null, vaps: null }, - // Add parent account number from FMG payment: { isInsurance: true, // TODO delete; irrelevant to ISS insuranceCoverage: { From 712858dea2678982d2b5dae95f53d70c5e8eeeb3 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 28 Aug 2023 14:11:14 -0400 Subject: [PATCH 19/46] Remove unnecessary eslint ignore --- src/store/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 4c8603e0..e89cdb27 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,5 +1,3 @@ -/* eslint-disable no-shadow */ -/* eslint-disable no-use-before-define */ /* eslint-disable max-len */ import { defineStore } from 'pinia'; import { endpoints } from '@/constants/endpoints'; From 2b4587c1f9b983f19989e540135db3df227f8c5e Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Tue, 29 Aug 2023 13:46:12 -0400 Subject: [PATCH 20/46] save supporting items on windshield repair --- src/layouts/vehicle-damage/vehicle-damage.vue | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 595aef6f..cb8338a8 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -364,11 +364,17 @@ export default { }, async forwardButtonAction() { - await this.mainStore.saveVehicleDamage( + this.mainStore.saveVehicleDamage( this.isWindshieldRepair, this.selectedGlassToReplace(), this.selectedWindshieldOptions.selectedWindshieldChipCount ); + + if (this.isWindshieldRepair) { + const supportingItems = await useMainStore().getSupportingItems(); + useMainStore().saveSupportingItems(supportingItems.data); + } + return this.navigateForward(); }, From 6f63484dffcd4e279a6735948214cf0358859308 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Tue, 29 Aug 2023 15:57:23 -0400 Subject: [PATCH 21/46] updates to vehicle damage page. --- src/digital-components/base-input-button/base-input-button.vue | 3 ++- src/layouts/vehicle-damage/vehicle-damage.vue | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/digital-components/base-input-button/base-input-button.vue b/src/digital-components/base-input-button/base-input-button.vue index 301bb52e..f619a16e 100644 --- a/src/digital-components/base-input-button/base-input-button.vue +++ b/src/digital-components/base-input-button/base-input-button.vue @@ -74,7 +74,8 @@ export default { return this.modelValue.includes(this.value); } if (!this.isMultiSelect) { - return this.modelValue === this.value; + // eslint-disable-next-line eqeqeq + return this.modelValue == this.value; } return false; }, diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index cb8338a8..4a53e854 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -372,7 +372,7 @@ export default { if (this.isWindshieldRepair) { const supportingItems = await useMainStore().getSupportingItems(); - useMainStore().saveSupportingItems(supportingItems.data); + this.mainStore.saveSupportingItems(supportingItems.data); } return this.navigateForward(); From 8e5dddd7ccd6aa0d239631501b7d350e89984c17 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 30 Aug 2023 11:29:25 -0400 Subject: [PATCH 22/46] fix test --- .../vehicle-damage/vehicle-damage.spec.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index 56a6c4dd..f2f911f7 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -3,6 +3,7 @@ import { mount, flushPromises } from '@vue/test-utils'; import { createTestingPinia } from '@pinia/testing'; import navigationScenarios from '@/router/router-constants/navigation-scenarios'; import routerParams from '@/router/router-constants/router-params'; +import { useMainStore } from '@/store'; import vehicleCategories from '@/constants/vehicle-categories'; import VehicleDamageComponent from '@/layouts/vehicle-damage/vehicle-damage.vue'; @@ -69,6 +70,21 @@ describe('vehicle-damage.vue', () => { const wrapper = mount(VehicleDamageComponent, mountOptions); const siteFooterWrapper = wrapper.getComponent({ ref: 'siteFooter' }); + useMainStore().getSupportingItems = jest.fn().mockImplementation(() => Promise.resolve({ + data: { data: [ + { + description: null, + partNumber: 'SUPPLIES-REPAIR', + partType: 'REPAIR FEE' + }, + { + description: null, + partNumber: 'WSREPAIR', + partType: 'REPAIR FEE' + } + ] } + })); + siteFooterWrapper.vm.$emit('forwardClicked'); await flushPromises(); From d7cc2a3ed99fbe21b8011e76b7e814656b2e1c7c Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 30 Aug 2023 13:16:14 -0400 Subject: [PATCH 23/46] bailout-confirmation renamed to contact-confirmation --- .../contact-confirmation.vue} | 0 src/router/router-constants/issPage-values.js | 2 +- src/router/router-constants/routing-table.js | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename src/layouts/{bailout-confirmation/bailout-confirmation.vue => contact-confirmation/contact-confirmation.vue} (100%) diff --git a/src/layouts/bailout-confirmation/bailout-confirmation.vue b/src/layouts/contact-confirmation/contact-confirmation.vue similarity index 100% rename from src/layouts/bailout-confirmation/bailout-confirmation.vue rename to src/layouts/contact-confirmation/contact-confirmation.vue diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js index 68ad4a08..d79f748f 100644 --- a/src/router/router-constants/issPage-values.js +++ b/src/router/router-constants/issPage-values.js @@ -5,9 +5,9 @@ const issPageValues = Object.freeze({ ADDRESS_LOOKUP: 'address-lookup', ADDRESS_VEHICLES: 'address-vehicles', - BAILOUT_CONFIRMATION: 'bailout-confirmation', BAILOUT_PAGE: 'bailout-page', CAPABILITY_QUESTIONS: 'capability-questions', + CONTACT_CONFIRMATION: 'contact-confirmation', CONTACT_DETAILS: 'contact-details', ESTIMATE: 'estimate', COVERAGE_STATEMENT: 'coverage-statement', diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 7830bac3..c3fbe633 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -609,7 +609,7 @@ const routingTable = () => [ }, { scenario: navigationScenarios.CLICKED_FORWARD, - destinationIssPageValue: issPageValues.BAILOUT_CONFIRMATION + destinationIssPageValue: issPageValues.CONTACT_CONFIRMATION } ] } From b8a53d94d9b93bb7830782b7428be6e046b0e4bc Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Tue, 29 Aug 2023 13:44:09 -0400 Subject: [PATCH 24/46] preReqs --- .../service-location/service-location.vue | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 939f5aa6..31a0a9fc 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -118,10 +118,7 @@ export default { next((vm) => { vm.setCmsContent(resultMap.cmsContent); - vm.setData( - resultMap.zipCodeData, - resultMap.serviceabilityDetails - ); + vm.setData(resultMap.zipCodeData, resultMap.serviceabilityDetails); }); }, setup() { @@ -172,8 +169,15 @@ export default { } }, methods: { - arePagePrerequisiteValid() { - return true; + arePagePrerequisitesValid() { + console.log('hi'); + console.log(useMainStore().lineItems.supportingItems); + console.log(useMainStore().order.serviceLocation.zipCode); + + return ( + useMainStore().lineItems.supportingItems !== null + && useMainStore().order.serviceLocation.zipCode !== null + ); }, backButtonAction() { /** From 9fc06b097c631a1e4dfff820fdc436febba3521c Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 30 Aug 2023 13:57:32 -0400 Subject: [PATCH 25/46] update servicelocation zipcode in store to match customer zipcode --- src/layouts/welcome-page/welcome-page.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/layouts/welcome-page/welcome-page.vue b/src/layouts/welcome-page/welcome-page.vue index 0607f008..e9943ba6 100644 --- a/src/layouts/welcome-page/welcome-page.vue +++ b/src/layouts/welcome-page/welcome-page.vue @@ -325,14 +325,16 @@ export default { const policy = policyInfo.policies?.[0]; if (policy) { // populate policy holder details from policy lookup - this.mainStore.order.customer.address.streetAddress = - policy.insureds?.[0]?.address; + this.mainStore.order.customer.address.streetAddress = policy.insureds?.[0]?.address; this.mainStore.order.customer.address.city = policy.insureds?.[0]?.city; this.mainStore.order.customer.address.state = policy.insureds?.[0]?.state; this.mainStore.order.customer.address.zipCode = policy.insureds?.[0]?.zipCode; this.mainStore.order.customer.firstName = policy.insureds?.[0]?.firstName; this.mainStore.order.customer.lastName = policy.insureds?.[0]?.lastName; + // populate additional fields + this.mainStore.order.serviceLocation.zipCode = policy.insureds?.[0]?.zipCode; + // populate vehicles this.vehiclesFound = policy.vehicles; } From d3882a8d96caecb5f679f270d9d79dce560fda53 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 30 Aug 2023 13:59:09 -0400 Subject: [PATCH 26/46] remove console logs --- src/layouts/service-location/service-location.vue | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 31a0a9fc..252741c1 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -170,10 +170,6 @@ export default { }, methods: { arePagePrerequisitesValid() { - console.log('hi'); - console.log(useMainStore().lineItems.supportingItems); - console.log(useMainStore().order.serviceLocation.zipCode); - return ( useMainStore().lineItems.supportingItems !== null && useMainStore().order.serviceLocation.zipCode !== null From 8a93a379499b13f2bdc65f0337d1a13b6f6b3743 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Wed, 30 Aug 2023 15:57:46 -0400 Subject: [PATCH 27/46] add servicelocation zipcode to --- src/store/index.js | 146 ++++++++++++++++++++++----------------------- 1 file changed, 70 insertions(+), 76 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 24014a3c..01d36851 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,3 +1,4 @@ +/* eslint-disable no-use-before-define */ /* eslint-disable max-len */ import { defineStore } from 'pinia'; import { endpoints } from '@/constants/endpoints'; @@ -203,26 +204,33 @@ export const useMainStore = defineStore({ issIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified, issHasRecalibrationPart: getHasRecalibrationPart(state), issSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1, - issSelectedWindshieldGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, - 'glassLocation').includes(damageLocationsSelected.WINDSHIELD), - issSelectedBackGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, - 'glassLocation').includes(damageLocationsSelected.REAR), - issSelectedDriverSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, - 'glassLocation').includes(damageLocationsSelected.DRIVER), - issSelectedPassengerSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, - 'glassLocation').includes(damageLocationsSelected.PASSENGER), + issSelectedWindshieldGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, 'glassLocation') + .includes(damageLocationsSelected.WINDSHIELD), + issSelectedBackGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, 'glassLocation') + .includes(damageLocationsSelected.REAR), + issSelectedDriverSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, 'glassLocation') + .includes(damageLocationsSelected.DRIVER), + issSelectedPassengerSideGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, 'glassLocation') + .includes(damageLocationsSelected.PASSENGER), issOrderPartNumbers: [ - ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, - 'partNumber'), - ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, - 'partNumber') + ...getNonFalseValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + 'partNumber' + ), + ...getNonFalseValuesOfPropertyInArrayOfObjects( + state.order.lineItems.otherParts, + 'partNumber' + ) ], - issOrderPartTypes: [ - ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, - 'recalibrationType'), - ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, - 'recalibrationType') + ...getNonFalseValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + 'recalibrationType' + ), + ...getNonFalseValuesOfPropertyInArrayOfObjects( + state.order.lineItems.otherParts, + 'recalibrationType' + ) ] }), experimentSettings: (state) => state.applicationUser.experiments @@ -599,8 +607,7 @@ export const useMainStore = defineStore({ async getPriceOrderItems(availableLineItems) { let zipCodeToUse = this.order.serviceLocation.zipCode; let ctuToUse = this.order.serviceLocation.zipCodeCtu; - const availableLineItemsFormattedForRequest - = getLineItemQueryStringForPricing(availableLineItems); + const availableLineItemsFormattedForRequest = getLineItemQueryStringForPricing(availableLineItems); const { vehicle } = this.order; // WARNING @@ -608,8 +615,8 @@ export const useMainStore = defineStore({ // and ctu is available. Also, EON may need to be implemented. zipCodeToUse = '44902'; ctuToUse = '01820'; - const queryString - = `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` + const queryString = + `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` + `&CTU=${ctuToUse}` + `&CarId=${vehicle.carId}` + `&Make=${vehicle.make}` @@ -637,16 +644,14 @@ export const useMainStore = defineStore({ const lineItemsWithOnlyPartNumbers = this.order.lineItems.glassParts.map((glassPart) => ({ partNumber: glassPart.partNumber })); - const lineItems = buildQueryStringParameterFromArrayOfComplexObjects(lineItemsWithOnlyPartNumbers, - 'lineItems'); + const lineItems = buildQueryStringParameterFromArrayOfComplexObjects(lineItemsWithOnlyPartNumbers, 'lineItems'); const { vehicle } = this.order; const { carId } = vehicle; const { damage } = this.order; const glassArray = convertGlassPieceNamingForApi(damage.glassToReplace); - const glassPieces = buildQueryStringParameterFromArrayOfComplexObjects(glassArray, - 'glassPieces'); + const glassPieces = buildQueryStringParameterFromArrayOfComplexObjects(glassArray, 'glassPieces'); return globalMethods.callHttpClient({ method: endpoints.GetServiceabilityDetails.method, @@ -679,23 +684,16 @@ export const useMainStore = defineStore({ saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); - const isGlassToReplaceTheSame - = this.order.damage.glassToReplace?.length === selectedGlassToReplace.length - && this.order.damage.glassToReplace - .slice() - .sort() - .every((obj, index) => obj.glassLocation === selectedGlassPassedInSorted[index].glassLocation + const isGlassToReplaceTheSame = this.order.damage.glassToReplace?.length === selectedGlassToReplace.length + && this.order.damage.glassToReplace + .slice() + .sort() + .every((obj, index) => obj.glassLocation === selectedGlassPassedInSorted[index].glassLocation && obj.glassName === selectedGlassPassedInSorted[index].glassName); - const isWindshieldRepairTheSame - = isWindshieldRepair === this.order.damage.isRepair; - - const isChipCountTheSame - = selectedWindshieldChipCount === this.order.damage.numberOfChips; - - const isDamageChanging - = !isGlassToReplaceTheSame - || !isWindshieldRepairTheSame - || (isWindshieldRepair && !isChipCountTheSame); + const isWindshieldRepairTheSame = isWindshieldRepair === this.order.damage.isRepair; + const isChipCountTheSame = selectedWindshieldChipCount === this.order.damage.numberOfChips; + const isDamageChanging = !isGlassToReplaceTheSame || !isWindshieldRepairTheSame + || (isWindshieldRepair && !isChipCountTheSame); if (isDamageChanging) { // Reset dependent state when changing @@ -927,16 +925,14 @@ export const useMainStore = defineStore({ this.order.customer.address.zipCode = customerQuestions.addressQuestions.zipCode; this.order.customer.firstName = customerQuestions.firstName; this.order.customer.lastName = customerQuestions.lastName; + this.order.serviceLocation.zipCode = customerQuestions.addressQuestions.zipCode; }, savePartQuestionAnswers(partQuestionAnswersArray) { // if part question answers have changed, reset subsequent question answers - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.partQuestionAnswers, - 'result'); - const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(partQuestionAnswersArray, - 'result'); - const havePartQuestionAnswersChanged - = sortedPreviousResultsArray?.length !== sortedPartQuestionAnswersArray.length - || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedPartQuestionAnswersArray[i].result); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.partQuestionAnswers, 'result'); + const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(partQuestionAnswersArray, 'result'); + const havePartQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedPartQuestionAnswersArray.length + || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedPartQuestionAnswersArray[i].result); if (havePartQuestionAnswersChanged) { this.updateGlassParts(null); @@ -954,13 +950,10 @@ export const useMainStore = defineStore({ this.updatePartQuestionAnswers(partQuestionAnswersArray); }, saveMoldingQuestionAnswers(moldingQuestionAnswersArray) { - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.moldingQuestionAnswers, - 'result'); - const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(moldingQuestionAnswersArray, - 'result'); - const haveMoldingQuestionAnswersChanged - = sortedPreviousResultsArray?.length !== sortedMoldingQuestionAnswersArray.length - || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedMoldingQuestionAnswersArray[i].result); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.moldingQuestionAnswers, 'result'); + const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(moldingQuestionAnswersArray, 'result'); + const haveMoldingQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedMoldingQuestionAnswersArray.length + || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedMoldingQuestionAnswersArray[i].result); if (haveMoldingQuestionAnswersChanged) { this.updateGlassParts(null); @@ -974,13 +967,10 @@ export const useMainStore = defineStore({ }, saveCapabilityQuestionAnswers(capabilityQuestionAnswersArray) { - const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.capabilityQuestionAnswers, - 'result'); - const sortedCapabilityQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswersArray, - 'result'); - const haveCapabilityQuestionAnswersChanged - = sortedPreviousResultsArray?.length !== sortedCapabilityQuestionAnswersArray.length - || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result); + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.damage.capabilityQuestionAnswers, 'result'); + const sortedCapabilityQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswersArray, 'result'); + const haveCapabilityQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedCapabilityQuestionAnswersArray.length + || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result); if (haveCapabilityQuestionAnswersChanged) { this.updateGlassParts(null); @@ -1064,10 +1054,12 @@ export const useMainStore = defineStore({ endpoint: endpoints.LogPageView.url, payload, logApiCall: false - }).then((response) => response, + }).then( + (response) => response, (error) => { console.log(`Analytics Service Error: ${error.data}`); - }); + } + ); }, logCustomEvent({ userId, sessionKey, pageName, sessionId, category, action, label, value, shouldUseSessionId, experimentsForUser }) { if (pageName == null || pageName.length === 0) { pageName = 'none'; } @@ -1091,10 +1083,12 @@ export const useMainStore = defineStore({ endpoint: endpoints.LogCustomEvent.url, payload, logApiCall: false - }).then((response) => response, + }).then( + (response) => response, (error) => { console.log(`Analytics Service Error: ${error.data}`); - }); + } + ); }, initializeSession({ userId, sessionId, userAgent, referrer }) { const payload = { @@ -1113,10 +1107,12 @@ export const useMainStore = defineStore({ endpoint: endpoints.InitializeSession.url, payload, logApiCall: false - }).then((response) => response, + }).then( + (response) => response, (error) => { console.log(`Analytics Service Error: ${error.data}`); - }); + } + ); }, updateLastPageVisited(lastPageVisited) { @@ -1290,19 +1286,17 @@ export const useMainStore = defineStore({ // Private Functions function getHasRecalibrationPart(state) { - const hasRequiresRecalibration - = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, - 'requiresRecalibration')?.length > 0; - const hasRecalibrationType - = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, - 'recalibrationType')?.length > 0; + const hasRequiresRecalibration = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'requiresRecalibration')?.length > 0; + const hasRecalibrationType = getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, 'recalibrationType')?.length > 0; if (hasRequiresRecalibration) { if (hasRecalibrationType) { // Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType' return ( - getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, - 'recalibrationType')[0].toLowerCase() !== 'unknown' + getNonFalseValuesOfPropertyInArrayOfObjects( + state.order.lineItems.glassParts, + 'recalibrationType' + )[0].toLowerCase() !== 'unknown' ); } // Has 'requiresRecalibration' but no 'recalibrationType' at all From 81e6e3a9a62a73a07c305a4fd4c8e18ae8a7c243 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 09:33:19 -0400 Subject: [PATCH 28/46] Adding save session after every navigation --- src/constants/coverage-statuses.js | 6 +- src/router/index.js | 12 +- .../router-constants/navigation-scenarios.js | 3 +- src/router/router-constants/routing-table.js | 4 + src/store/index.js | 64 +-- src/store/store.spec.js | 509 +++++++++++++++++- 6 files changed, 559 insertions(+), 39 deletions(-) diff --git a/src/constants/coverage-statuses.js b/src/constants/coverage-statuses.js index 5f794cc9..4142121a 100644 --- a/src/constants/coverage-statuses.js +++ b/src/constants/coverage-statuses.js @@ -1,7 +1,7 @@ const coverageStatuses = Object.freeze({ - PENDING: 'Pending', - NO_COMP: 'No Comp', - VERIFIED: 'Verified' + PENDING: 0, + NO_COMP: 1, + VERIFIED: 2 }); export default coverageStatuses; diff --git a/src/router/index.js b/src/router/index.js index 44e5e5a8..5f8f3cdc 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -82,13 +82,19 @@ const router = createRouter({ } }); -router.afterEach((to, from) => { +router.afterEach(async (to, from) => { /*eslint-disable-line*/ - const store = useMainStore(); // Update lastPageVisited in the store store.updateLastPageVisited(to.name); - store.saveSession(); + await store.saveSession()?.catch(() => { + console.log("failed :("); + if(from.name === issPageValues.WELCOME_PAGE) { + console.log("welcome!"); + router.navigate(navigationScenarios.SAVE_SESSION_FAILED, {query: {issPage: issPageValues.WELCOME_PAGE}}) + // TODO bail out if save session fails + } + }); if (to.query.issPage !== issPageValues.ENTRY_PAGE) { // Push page view to GA diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index f732786a..6fb510d2 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -11,6 +11,7 @@ const navigationScenarios = Object.freeze({ CLICKED_FORWARD_POLICY_UNVERIFIED: 'CLICKED_FORWARD_POLICY_UNVERIFIED', CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES', CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES: 'CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES', + SAVE_SESSION_FAILED: 'SAVE_SESSION_FAILED', // YMMS SELECTED_YEAR: 'SELECTED_YEAR', @@ -63,7 +64,7 @@ const navigationScenarios = Object.freeze({ CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES: 'CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES', // Bailout - CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT' + CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT', }); export default navigationScenarios; diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 4af22d4f..e2a0dc85 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -354,6 +354,10 @@ const routingTable = () => [ { scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES, destinationIssPageValue: issPageValues.POLICY_VEHICLES + }, + { + scenario: navigationScenarios.SAVE_SESSION_FAILED, + destinationIssPageValue: issPageValues.BAILOUT_PAGE } ] }, diff --git a/src/store/index.js b/src/store/index.js index e89cdb27..2765a5f2 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -685,22 +685,22 @@ export const useMainStore = defineStore({ }, saveSession() { - const { vehicle, damage, policy, customer, contactInfo, payment, applicationUser, + const { vehicle, damage, policy, customer, contactInfo, payment, lineItems, serviceLocation, schedule } = this.order; const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace); - return globalMethods.callHttpClient({ - method: endpoints.SaveSession.method, - endpoint: endpoints.SaveSession.url, - payload: { - applicationUser: { - crmCustomerId: applicationUser.crmCustomerId, - experiments: applicationUser.experiments, - lastPage: applicationUser.lastPageVisited, - pageData: applicationUser.pageData, - savedSessionId: applicationUser.savedSessionId - }, - order: { + return new Promise((resolve, reject) => { + globalMethods.callHttpClient({ + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + payload: { + applicationUser: { + crmCustomerId: this.applicationUser.crmCustomerId, + experiments: this.applicationUser.experiments, + lastPage: this.applicationUser.lastPageVisited, + pageData: this.applicationUser.pageData, + savedSessionId: this.applicationUser.savedSessionId + }, vehicle: { year: vehicle.year, make: vehicle.make, @@ -708,7 +708,7 @@ export const useMainStore = defineStore({ style: vehicle.style, vin: vehicle.vin, carId: vehicle.carId, - licensePlateNumber: vehicle.registration.licensePlate + licensePlateNumber: vehicle.registration?.licensePlate }, damage: { numberOfChips: damage.numberOfChips, @@ -739,11 +739,11 @@ export const useMainStore = defineStore({ }, customer: { address: { - streetAddress: customer.address.streetAddress, - streetAddress2: customer.address.streetAddress2, - city: customer.address.city, - state: customer.address.state, - zipCode: customer.address.zipCode + streetAddress: customer.address?.streetAddress, + streetAddress2: customer.address?.streetAddress2, + city: customer.address?.city, + state: customer.address?.state, + zipCode: customer.address?.zipCode }, emailAddress: contactInfo.emailAddress, firstName: contactInfo.firstName, @@ -758,8 +758,8 @@ export const useMainStore = defineStore({ }, payment: { InsuranceCoverage: { - isVerified: payment.insuranceCoverage.isVerified ?? false, - coverageStatus: payment.insuranceCoverage.coverageStatus + isVerified: payment.insuranceCoverage?.isVerified ?? false, + coverageStatus: payment.insuranceCoverage?.coverageStatus }, isInsurance: payment.isInsurance ?? true, parentAccountNumber: this.issConfig.accountNumber @@ -775,18 +775,22 @@ export const useMainStore = defineStore({ techNotes: contactInfo.notesForTechnician }, schedule: { - date: schedule?.date, - startTime: schedule?.startTime, - endTime: schedule?.endTime, - routeCode: schedule?.routeCode, - jobMaxMinutes: schedule?.jobMaxMinutes + date: schedule.date, + startTime: schedule.startTime, + endTime: schedule.endTime, + routeCode: schedule.routeCode, + jobMaxMinutes: schedule.jobMaxMinutes }, referralDate: this.order.referralDate, referralNumber: this.order.referralNumber?.toString() - } - }, - additionalSuccessEventDataHandler: (response) => - `Email provided: ${customer.emailAddress ? 'true' : 'false'}` + }, + additionalSuccessEventDataHandler: (response) => + `Email provided: ${customer.emailAddress ? 'true' : 'false'}` + }).then((response) => { + return resolve(response); + }).catch((error) => { + return reject(error); + }); }); }, diff --git a/src/store/store.spec.js b/src/store/store.spec.js index 6a7339ef..bbaf7dc1 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -3,6 +3,7 @@ import { setActivePinia, createPinia } from 'pinia'; import globalMethods from '@/global-methods.js'; import { getRandomString, getRandomGuid, getRandomInt, getRandomBoolean } from '@/helpers/data-generation.js'; import coverageStatuses from '@/constants/coverage-statuses.js'; +import { endpoints } from '@/constants/endpoints'; describe('Store', () => { let store; @@ -478,6 +479,510 @@ describe('Store', () => { expect(store.contactInfo.notesForTechnician).toEqual(''); }); }); - // TODO add tests - describe('saveSession method', () => {}); + + describe('saveSession method', () => { + describe('successful method call', () => { + it('calls save session api endpoint', () => { + // Arrange + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url + } + )); + }); + it('Returns expected response object', async () => { + // Arrange + var response = { ReferralNumber: getRandomString(6, 6) }; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response)); + + // Act + const result = store.saveSession(); + + // Asserts + await expect(result).resolves.toBe(response); + }) + it('calls api with expected application user data', () => { + // Arrange + var applicationUser = { + crmCustomerId: getRandomString(6, 6), + experiments: getRandomString(6, 6), + lastPageVisited: getRandomString(6, 6), + pageData: getRandomString(6, 6), + savedSessionId: getRandomString(6, 6) + }; + store.applicationUser = applicationUser; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + const result = store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + applicationUser: expect.objectContaining({ + crmCustomerId: applicationUser.crmCustomerId, + experiments: applicationUser.experiments, + lastPage: applicationUser.lastPageVisited, + pageData: applicationUser.pageData, + savedSessionId: applicationUser.savedSessionId + }) + }) + }) + ); + }); + it('calls api with expected vehicle', () => { + var vehicle = { + year: getRandomString(6, 6), + make: getRandomString(6, 6), + model: getRandomString(6, 6), + style: getRandomString(6, 6), + carId: getRandomString(6, 6), + vin: getRandomString(6, 6), + registration: { licensePlate: getRandomString(6, 6) } + }; + store.order.vehicle = vehicle; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + vehicle: expect.objectContaining({ + year: vehicle.year, + make: vehicle.make, + model: vehicle.model, + style: vehicle.style, + carId: vehicle.carId, + vin: vehicle.vin, + licensePlateNumber: vehicle.registration.licensePlate + }) + }) + }) + } + )); + }); + it('calls api with expected damage', () => { + // Arrange + var damage = { + isRepair: getRandomString(6, 6), + numberOfChips: getRandomString(6, 6), + glassToReplace: [], + partQuestionAnswers: getRandomString(6, 6), + moldingQuestionAnswers: getRandomString(6, 6), + capabilityQuestionAnswers: getRandomString(6, 6) + }; + var policy = { + dateOfLoss: getRandomString(6, 6), + damageCause: getRandomString(6, 6), + damageState: getRandomString(6, 6), + damageCity: getRandomString(6, 6), + isDamageGlassOnly: getRandomString(6, 6) + }; + store.order.damage = damage; + store.order.policy = policy; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + damage: expect.objectContaining({ + numberOfChips: damage.numberOfChips, + isRepair: damage.isRepair, + partQuestionAnswers: damage.partQuestionAnswers, + moldingQuestionAnswers: damage.moldingQuestionAnswers, + capabilityQuestionAnswers: damage.capabilityQuestionAnswers, + dateOfLoss: policy.dateOfLoss, + damageCause: policy.damageCause, + damageState: policy.damageState, + damageCity: policy.damageCity, + isDamageGlassOnly: policy.isDamageGlassOnly + }) + }) + }) + }) + ); + }); + it('calls api with expected policy', () => { + // Arrange + var customer = { + firstName: getRandomString(6, 6), + lastName: getRandomString(6, 6), + emailAddress: getRandomString(6, 6), + phoneNumber: getRandomString(6, 6) + }; + var policy = { + policyNumber: getRandomString(6, 6), + policyZipCode: getRandomString(6, 6), + policyLookupSuccessful: getRandomString(6, 6), + noCoverage: getRandomString(6, 6) + }; + var originalDeductible = getRandomString(6, 6); + var currentDeductible = getRandomString(6, 6); + store.order.originalDeductible = originalDeductible; + store.order.currentDeductible = currentDeductible; + store.order.customer = customer; + store.order.policy = policy; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + policy: expect.objectContaining({ + policyHolder: expect.objectContaining({ + policyFirstName: customer.firstName, + policyLastName: customer.lastName, + policyPhoneNumber: customer.phoneNumber, + policyEmail: customer.emailAddress + }), + policyNumber: policy.policyNumber, + policyZipCode: policy.policyZipCode, + noCoverage: policy.noCoverage, + policyLookupSuccessful: policy.policyLookupSuccessful, + originalDeductible, + currentDeductible + }) + }) + }) + }) + ); + }); + it('calls api with expected customer', () => { + // Arrange + var customer = { + address: { + streetAddress: getRandomString(6, 6), + streetAddress2: getRandomString(6, 6), + city: getRandomString(6, 6), + state: getRandomString(6, 6), + zipCode: getRandomString(6, 6) + } + }; + var contactInfo = { + firstName: getRandomString(6, 6), + lastName: getRandomString(6, 6), + emailAddress: getRandomString(6, 6), + phoneNumber: getRandomString(6, 6), + requestTextUpdates: getRandomBoolean() + }; + store.order.contactInfo = contactInfo; + store.order.customer = customer; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + customer: expect.objectContaining({ + address: expect.objectContaining({ + streetAddress: customer.address.streetAddress, + streetAddress2: customer.address.streetAddress2, + city: customer.address.city, + state: customer.address.state, + zipCode: customer.address.zipCode + }), + emailAddress: contactInfo.emailAddress, + firstName: contactInfo.firstName, + lastName: contactInfo.lastName, + phoneNumber: contactInfo.phoneNumber, + optInSms: contactInfo.requestTextUpdates + }) + }) + }) + }) + ); + }); + it('calls api with expected lineItems', () => { + // Arrange + var lineItems = { + glassParts: getRandomString(6, 6), + supportingItems: getRandomString(6, 6), + vaps: getRandomString(6, 6) + }; + store.order.lineItems = lineItems; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + lineItems: expect.objectContaining({ + glassParts: lineItems.glassParts, + supportingItems: lineItems.supportingItems, + vaps: lineItems.vaps + }) + }) + }) + }) + ); + }); + it.each([ + [coverageStatuses.PENDING], + [coverageStatuses.NO_COMP], + [coverageStatuses.VERIFIED] + ])('calls api with expected payment', (coverageStatus) => { + // Arrange + const accountNumber = getRandomString(6, 6); + const payment = { + isInsurance: getRandomBoolean(), + insuranceCoverage: { + isVerified: getRandomBoolean(), + coverageStatus + } + }; + store.issConfig.accountNumber = accountNumber; + store.order.payment = payment; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + payment: expect.objectContaining({ + InsuranceCoverage: expect.objectContaining({ + isVerified: payment.insuranceCoverage.isVerified, + coverageStatus: coverageStatus + }), + isInsurance: payment.isInsurance, + parentAccountNumber: accountNumber + }) + }) + }) + }) + ); + }); + it('calls api with expected service location', () => { + // Arrange + var notesForTechnician = getRandomString(6, 6); + var serviceLocation = { + address: getRandomString(6, 6), + city: getRandomString(6, 6), + state: getRandomString(6, 6), + zipCode: getRandomString(6, 6), + zipCodeCtu: getRandomString(6, 6) + }; + store.order.contactInfo.notesForTechnician = notesForTechnician; + store.order.serviceLocation = serviceLocation; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + serviceLocation: expect.objectContaining({ + address: expect.objectContaining({ + streetAddress: serviceLocation.address, + city: serviceLocation.city, + state: serviceLocation.state, + zipCode: serviceLocation.zipCode, + zipCodeCtu: serviceLocation.zipCodeCtu + }), + techNotes: notesForTechnician + }) + }) + }) + }) + ); + }); + it('calls api with expected schedule', () => { + // Arrange + var schedule = { + date: getRandomString(6, 6), + startTime: getRandomString(6, 6), + endTime: getRandomString(6, 6), + routeCode: getRandomString(6, 6), + jobMaxMinutes: getRandomString(6, 6) + }; + store.order.schedule = schedule; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ + schedule: expect.objectContaining({ + date: schedule.date, + startTime: schedule.startTime, + endTime: schedule.endTime, + routeCode: schedule.routeCode, + jobMaxMinutes: schedule.jobMaxMinutes + }) + }) + }) + }) + ); + }); + it('calls api with expected referral date', () => { + // Arrange + var referralDate = getRandomString(6, 6); + store.order.referralDate = referralDate; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ referralDate: referralDate }) + }) + }) + ); + }); + it('calls api with expected referral number', () => { + // Arrange + var referralNumber = getRandomString(6, 6); + store.order.referralNumber = referralNumber; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + store.saveSession(); + + // Assert + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + payload: expect.objectContaining({ + order: expect.objectContaining({ referralNumber: referralNumber }) + }) + } + )); + }); + }); + it('No glassArray => empty list', async () => { + store.damage.glassToReplace = null; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + await store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + payload: expect.objectContaining({ + order: expect.objectContaining({ + damage: expect.objectContaining({ + glassToReplace: [] + }) + }) + }) + }) + ); + }); + it('glassArray empty => empty list', async () => { + store.damage.glassToReplace = []; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + await store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + payload: expect.objectContaining({ + order: expect.objectContaining({ + damage: expect.objectContaining({ + glassToReplace: [] + }) + }) + }) + }) + ); + }); + it('Nonempty glass array => expected glass array sent', async () => { + const location1 = getRandomString(5); + const location2 = getRandomString(5); + const name1 = getRandomString(10); + const name2 = getRandomString(10); + store.damage.glassToReplace = [ + {glassLocation: location1, glassName: name1}, + {glassLocation: location2, glassName: name2} + ], + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve({})); + + // Act + await store.saveSession(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + payload: expect.objectContaining({ + order: expect.objectContaining({ + damage: expect.objectContaining({ + glassToReplace: expect.arrayContaining([ + {location: location1, name: name1}, + {location: location2, name: name2} + ]) + }) + }) + }) + }) + ); + }); + it('api call throws exception', async () => { + expect.assertions(2); + const error = 'this is the error'; + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject(error)); + + // Act + await store.saveSession().catch((e) => { + expect(e).toEqual(error); + }); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( + { + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url + }) + ); + }); + }); }); From df86541d30a2f5db9040c429f41de6d6f366c909 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 09:40:30 -0400 Subject: [PATCH 29/46] Removing comments --- src/router/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index 5f8f3cdc..6406096d 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -88,11 +88,8 @@ router.afterEach(async (to, from) => { // Update lastPageVisited in the store store.updateLastPageVisited(to.name); await store.saveSession()?.catch(() => { - console.log("failed :("); if(from.name === issPageValues.WELCOME_PAGE) { - console.log("welcome!"); router.navigate(navigationScenarios.SAVE_SESSION_FAILED, {query: {issPage: issPageValues.WELCOME_PAGE}}) - // TODO bail out if save session fails } }); From cc893b6eacc8d217e295b83ca0e4d4da3fafcb73 Mon Sep 17 00:00:00 2001 From: Bill Richardson Date: Thu, 31 Aug 2023 13:16:44 -0400 Subject: [PATCH 30/46] clear error list on enable/disable --- .../dropdown-question/dropdown-question.vue | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/digital-components/dropdown-question/dropdown-question.vue b/src/digital-components/dropdown-question/dropdown-question.vue index 25a850d2..05f8b9a4 100644 --- a/src/digital-components/dropdown-question/dropdown-question.vue +++ b/src/digital-components/dropdown-question/dropdown-question.vue @@ -79,14 +79,19 @@ export default { initialValue }; - const { errorMessage, handleBlur, handleChange, meta, errors } = useField(props.inputId, props.validationRules, fieldOptions); + const { errorMessage, + handleBlur, + handleChange, + meta, errors, + setErrors } = useField(props.inputId, props.validationRules, fieldOptions); return { errorMessage, handleBlur, handleChange, meta, - errors + errors, + setErrors }; }, computed: { @@ -123,6 +128,11 @@ export default { } }, watch: { + isDisabled(newValue, oldValue) { + if (newValue !== oldValue) { + this.setErrors([]); + } + }, selectedOption(newValue) { this.handleChange(newValue); } From 7442e48ba52342dc422aced1ec95059abfe078c4 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 13:27:58 -0400 Subject: [PATCH 31/46] Setting values based on save session output --- src/store/index.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 2765a5f2..b2b9d9df 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -92,8 +92,6 @@ const getDefaultState = () => ({ coverageStatus: coverageStatuses.PENDING } }, - referralNumber: null, - referralDate: null, contactInfo: { firstName: null, lastName: null, @@ -108,7 +106,13 @@ const getDefaultState = () => ({ endTime: null, routeCode: null, jobMaxMinutes: null - } + }, + referralNumber: null, + referralDate: null, + referralCorrelationId: null, + referralSequenceNumber: null, + eon: null, + workOrderNumber: null }, applicationUser: { experiments: [], @@ -782,11 +786,24 @@ export const useMainStore = defineStore({ jobMaxMinutes: schedule.jobMaxMinutes }, referralDate: this.order.referralDate, - referralNumber: this.order.referralNumber?.toString() + referralNumber: this.order.referralNumber?.toString(), + referralCorrelationId: this.order.referralCorrelationId, + referralSequenceNumber: this.order.referralSequenceNumber, + eon: this.order.eon }, additionalSuccessEventDataHandler: (response) => `Email provided: ${customer.emailAddress ? 'true' : 'false'}` }).then((response) => { + if (referralNumber === null) { + this.order.referralNumber = response.referralNumber; + this.order.referralSequenceNumber = response.referralSequenceNumber; + this.order.referralDate = response.referralDate; + this.order.referralCorrelationId = response.referralCorrelationId; + this.order.eon = response.eon; + this.order.workOrderNumber = response.workOrderNumber; + this.applicationUser.savedSessionId = response.savedSessionId; + this.applicationUser.crmCustomerId = response.crmCustomerId; + } return resolve(response); }).catch((error) => { return reject(error); From 81ec8d4d1485d76d3b1f59ad980b91453c2dfb79 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 16:11:53 -0400 Subject: [PATCH 32/46] Committing to facilitate collab --- src/helpers/cookie-helper.js | 5 +- src/helpers/order-helper.js | 60 +++++++++ src/router/index.js | 13 +- src/store/index.js | 237 +++++++++++++++++------------------ 4 files changed, 190 insertions(+), 125 deletions(-) create mode 100644 src/helpers/order-helper.js diff --git a/src/helpers/cookie-helper.js b/src/helpers/cookie-helper.js index 2b93484b..bf88ace6 100644 --- a/src/helpers/cookie-helper.js +++ b/src/helpers/cookie-helper.js @@ -112,7 +112,9 @@ function setISSCookieProperties(properties) { Will update the cookie if present, or create a new one if not. */ export function updateOrCreateISSCookie() { + console.log('in cookie function'); const store = useMainStore(); + console.log(store); // Set up cookie with all the props. setISSCookieProperties({ @@ -122,7 +124,8 @@ export function updateOrCreateISSCookie() { ReferralNumber: store.order.referralNumber, ReferralDate: store.order.referralDate, ReferralCorrelationId: store.order.referralCorrelationId, - ReferralParentAccountNumber: store.order.accountNumber + ReferralParentAccountNumber: store.order.accountNumber, + SavedSessionId: store.applicationUser.savedSessionId }); } diff --git a/src/helpers/order-helper.js b/src/helpers/order-helper.js new file mode 100644 index 00000000..290b4c0e --- /dev/null +++ b/src/helpers/order-helper.js @@ -0,0 +1,60 @@ +import { useMainStore } from '@/store'; +import { updateOrCreateISSCookie } from '@/helpers/cookie-helper'; + +/* + Will call API to save existing order, or create new one depending where it's called from. + This will also set Referral information in the store after saving, and then + update the cookie. To force synchronous behavior pass in 'true' for shouldAwaitSaveSessionQueue +*/ +// encapsulate when you transition back into heritage +// we need eon from first call to get pricing +// eon is a number that some services require +// save session takes time +// not necessary for much throughout the flow +// we want each save session call to happen sequentially, but asynchronously +export async function saveSession({ shouldAwaitSaveSessionQueue = false }) { + const store = useMainStore(); + console.log('order helper'); + console.log(store); + var saveSessionPromise; + if (store.applicationUser.saveSessionPromise){ + console.log('if promise exists'); + console.log(store.applicationUser.saveSessionPromise); + + // .then returns another promise but waiting for another to finish + saveSessionPromise = store.applicationUser.saveSessionPromise + .then(() => { + console.log('then'); + return saveSessionHelper(store); + }) + .catch((error) => { + console.log("saveSessionPromise failed: " + error.message); + }); + } + else { + console.log('else'); + saveSessionPromise = saveSessionHelper(store); + } + // var saveSessionPromise = + // store.applicationUser.saveSessionPromise + // ? store.applicationUser.saveSessionPromise.then(() => { return saveSessionHelper(store); }) + // : saveSessionHelper(store); + console.log('promise exists'); + store.setSaveSessionPromise(saveSessionPromise); + console.log('set information'); + if (!store.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) { + console.log('pre await'); + await saveSessionPromise; + } + console.log('done'); +} + +/* + Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing +*/ +async function saveSessionHelper(store) { + console.log('helper helper called'); + const savedSessionInfo = await store.saveSession(); + store.setSaveSessionInfo(savedSessionInfo.data); + updateOrCreateISSCookie(); +} \ No newline at end of file diff --git a/src/router/index.js b/src/router/index.js index 6406096d..be341fbb 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -16,6 +16,7 @@ import applicationConfig from '@/constants/application-config'; import analyticsMixin from '@/mixins/analytics-mixin'; import navigationScenarios from './router-constants/navigation-scenarios'; +import { saveSession } from "@/helpers/order-helper.js"; const routes = [ { @@ -87,12 +88,18 @@ router.afterEach(async (to, from) => { const store = useMainStore(); // Update lastPageVisited in the store store.updateLastPageVisited(to.name); - await store.saveSession()?.catch(() => { - if(from.name === issPageValues.WELCOME_PAGE) { + console.log('after each'); + + await saveSession({shouldAwaitSaveSessionQueue: true}).then(() => { + console.log('then'); + }).catch((error) => { + console.log(error); + console.log("catch"); + if (from.name === issPageValues.WELCOME_PAGE) { router.navigate(navigationScenarios.SAVE_SESSION_FAILED, {query: {issPage: issPageValues.WELCOME_PAGE}}) } }); - + if (to.query.issPage !== issPageValues.ENTRY_PAGE) { // Push page view to GA analyticsMixin.methods.pushPageViewToGA(); diff --git a/src/store/index.js b/src/store/index.js index b2b9d9df..35a71604 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -109,7 +109,7 @@ const getDefaultState = () => ({ }, referralNumber: null, referralDate: null, - referralCorrelationId: null, + referralCorrelationId: '00000000-0000-0000-0000-000000000000', referralSequenceNumber: null, eon: null, workOrderNumber: null @@ -338,8 +338,6 @@ export const useMainStore = defineStore({ } }, getCoveragePolicyInfo({ accountNumber, policyNumber, dateOfLoss, zipCode }) { - // TODO: replace place holder correlationId with the real thing - const placeHolderCorrelationId = '00000000-0000-0000-0000-000000000000'; const { policy } = this.order; try { const response = globalMethods.callHttpClient({ @@ -350,7 +348,7 @@ export const useMainStore = defineStore({ policyNumber, dateOfLoss, zipCode, - correlationId: placeHolderCorrelationId + correlationId: this.order.referralCorrelationId } }).then((r) => { const responsePolicy = r.data.policies?.[0]; @@ -371,8 +369,6 @@ export const useMainStore = defineStore({ } }, registerClaim() { - // TODO: replace place holder correlationId with the real thing - const placeHolderCorrelationId = '00000000-0000-0000-0000-000000000000'; const nonNumberCharRegex = /[^0-9]/g; const { order } = this; return new Promise((resolve, reject) => { @@ -381,7 +377,7 @@ export const useMainStore = defineStore({ endpoint: endpoints.RegisterClaim.url, payload: { - correlationId: placeHolderCorrelationId, + correlationId: this.order.referralCorrelationId, accountNumber: this.issConfig.accountNumber?.toString() ?? '', insured: { firstName: this.order.customer.firstName, @@ -688,129 +684,128 @@ export const useMainStore = defineStore({ }); }, + setSaveSessionInfo(response){ + this.order.referralNumber = response.referralNumber; + this.order.referralSequenceNumber = response.referralSequenceNumber; + this.order.referralDate = response.referralDate; + this.order.referralCorrelationId = response.referralCorrelationId; + this.order.eon = response.eon; + this.order.workOrderNumber = response.workOrderNumber; + this.applicationUser.savedSessionId = response.savedSessionId; + this.applicationUser.crmCustomerId = response.crmCustomerId.toString(); + }, + saveSession() { const { vehicle, damage, policy, customer, contactInfo, payment, lineItems, serviceLocation, schedule } = this.order; const newGlassToReplace = convertGlassPieceNamingForApi(damage.glassToReplace); - return new Promise((resolve, reject) => { - globalMethods.callHttpClient({ - method: endpoints.SaveSession.method, - endpoint: endpoints.SaveSession.url, - payload: { - applicationUser: { - crmCustomerId: this.applicationUser.crmCustomerId, - experiments: this.applicationUser.experiments, - lastPage: this.applicationUser.lastPageVisited, - pageData: this.applicationUser.pageData, - savedSessionId: this.applicationUser.savedSessionId - }, - vehicle: { - year: vehicle.year, - make: vehicle.make, - model: vehicle.model, - style: vehicle.style, - vin: vehicle.vin, - carId: vehicle.carId, - licensePlateNumber: vehicle.registration?.licensePlate - }, - damage: { - numberOfChips: damage.numberOfChips, - glassToReplace: newGlassToReplace, - isRepair: damage.isRepair, - partQuestionAnswers: damage.partQuestionAnswers, - moldingQuestionAnswers: damage.moldingQuestionAnswers, - capabilityQuestionAnswers: damage.capabilityQuestionAnswers, - dateOfLoss: policy.dateOfLoss, - damageCause: policy.damageCause, - damageState: policy.damageState, - damageCity: policy.damageCity, - isDamageGlassOnly: policy.isDamageGlassOnly - }, - policy: { - policyHolder: { - policyFirstName: customer.firstName, - policyLastName: customer.lastName, - policyPhoneNumber: customer.phoneNumber, - policyEmail: customer.emailAddress - }, - policyNumber: policy.policyNumber, - policyZipCode: policy.policyZipCode, - noCoverage: policy.noCoverage, - policyLookupSuccessful: policy.policyLookupSuccessful, - originalDeductible: this.order.originalDeductible, - currentDeductible: this.order.currentDeductible - }, - customer: { - address: { - streetAddress: customer.address?.streetAddress, - streetAddress2: customer.address?.streetAddress2, - city: customer.address?.city, - state: customer.address?.state, - zipCode: customer.address?.zipCode - }, - emailAddress: contactInfo.emailAddress, - firstName: contactInfo.firstName, - lastName: contactInfo.lastName, - phoneNumber: contactInfo.phoneNumber, - optInSms: contactInfo.requestTextUpdates ?? false - }, - lineItems: { - glassParts: lineItems.glassParts, - supportingItems: lineItems.supportingItems, - vaps: lineItems.vaps - }, - payment: { - InsuranceCoverage: { - isVerified: payment.insuranceCoverage?.isVerified ?? false, - coverageStatus: payment.insuranceCoverage?.coverageStatus - }, - isInsurance: payment.isInsurance ?? true, - parentAccountNumber: this.issConfig.accountNumber - }, - serviceLocation: { - address: { - streetAddress: serviceLocation.address, - city: serviceLocation.city, - state: serviceLocation.state, - zipCode: serviceLocation.zipCode, - zipCodeCtu: serviceLocation.zipCodeCtu - }, - techNotes: contactInfo.notesForTechnician - }, - schedule: { - date: schedule.date, - startTime: schedule.startTime, - endTime: schedule.endTime, - routeCode: schedule.routeCode, - jobMaxMinutes: schedule.jobMaxMinutes - }, - referralDate: this.order.referralDate, - referralNumber: this.order.referralNumber?.toString(), - referralCorrelationId: this.order.referralCorrelationId, - referralSequenceNumber: this.order.referralSequenceNumber, - eon: this.order.eon + return globalMethods.callHttpClient({ + method: endpoints.SaveSession.method, + endpoint: endpoints.SaveSession.url, + payload: { + applicationUser: { + crmCustomerId: this.applicationUser.crmCustomerId, + experiments: this.applicationUser.experiments, + lastPage: this.applicationUser.lastPageVisited, + pageData: this.applicationUser.pageData, + savedSessionId: this.applicationUser.savedSessionId }, - additionalSuccessEventDataHandler: (response) => - `Email provided: ${customer.emailAddress ? 'true' : 'false'}` - }).then((response) => { - if (referralNumber === null) { - this.order.referralNumber = response.referralNumber; - this.order.referralSequenceNumber = response.referralSequenceNumber; - this.order.referralDate = response.referralDate; - this.order.referralCorrelationId = response.referralCorrelationId; - this.order.eon = response.eon; - this.order.workOrderNumber = response.workOrderNumber; - this.applicationUser.savedSessionId = response.savedSessionId; - this.applicationUser.crmCustomerId = response.crmCustomerId; - } - return resolve(response); - }).catch((error) => { - return reject(error); - }); + vehicle: { + year: vehicle.year, + make: vehicle.make, + model: vehicle.model, + style: vehicle.style, + vin: vehicle.vin, + carId: vehicle.carId, + licensePlateNumber: vehicle.registration?.licensePlate + }, + damage: { + numberOfChips: damage.numberOfChips, + glassToReplace: newGlassToReplace, + isRepair: damage.isRepair, + partQuestionAnswers: damage.partQuestionAnswers, + moldingQuestionAnswers: damage.moldingQuestionAnswers, + capabilityQuestionAnswers: damage.capabilityQuestionAnswers, + dateOfLoss: policy.dateOfLoss, + damageCause: policy.damageCause, + damageState: policy.damageState, + damageCity: policy.damageCity, + isDamageGlassOnly: policy.isDamageGlassOnly + }, + policy: { + policyHolder: { + policyFirstName: customer.firstName, + policyLastName: customer.lastName, + policyPhoneNumber: customer.phoneNumber, + policyEmail: customer.emailAddress + }, + policyNumber: policy.policyNumber, + policyZipCode: policy.policyZipCode, + noCoverage: policy.noCoverage, + policyLookupSuccessful: policy.policyLookupSuccessful, + originalDeductible: this.order.originalDeductible, + currentDeductible: this.order.currentDeductible + }, + customer: { + address: { + streetAddress: customer.address?.streetAddress, + streetAddress2: customer.address?.streetAddress2, + city: customer.address?.city, + state: customer.address?.state, + zipCode: customer.address?.zipCode + }, + emailAddress: contactInfo.emailAddress, + firstName: contactInfo.firstName, + lastName: contactInfo.lastName, + phoneNumber: contactInfo.phoneNumber, + optInSms: contactInfo.requestTextUpdates ?? false + }, + lineItems: { + glassParts: lineItems.glassParts, + supportingItems: lineItems.supportingItems, + vaps: lineItems.vaps + }, + payment: { + InsuranceCoverage: { + isVerified: payment.insuranceCoverage?.isVerified ?? false, + coverageStatus: payment.insuranceCoverage?.coverageStatus + }, + isInsurance: payment.isInsurance ?? true, + parentAccountNumber: this.issConfig.accountNumber + }, + serviceLocation: { + address: { + streetAddress: serviceLocation.address, + city: serviceLocation.city, + state: serviceLocation.state, + zipCode: serviceLocation.zipCode, + zipCodeCtu: serviceLocation.zipCodeCtu + }, + techNotes: contactInfo.notesForTechnician + }, + schedule: { + date: schedule.date, + startTime: schedule.startTime, + endTime: schedule.endTime, + routeCode: schedule.routeCode, + jobMaxMinutes: schedule.jobMaxMinutes + }, + referralDate: this.order.referralDate, + referralNumber: this.order.referralNumber?.toString(), + referralCorrelationId: this.order.referralCorrelationId, + referralSequenceNumber: this.order.referralSequenceNumber, + eon: this.order.eon + }, + additionalSuccessEventDataHandler: (response) => + `Email provided: ${customer.emailAddress ? 'true' : 'false'}` }); }, + setSaveSessionPromise(promise){ + this.applicationUser.saveSessionPromise = promise; + }, + saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); const isGlassToReplaceTheSame From 9118d598786975dd103eefd220dea2b9d8ca4c53 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 16:27:35 -0400 Subject: [PATCH 33/46] Addressing problems --- src/helpers/cookie-helper.js | 2 -- src/helpers/order-helper.js | 39 ++++-------------------------------- src/router/index.js | 11 +++++----- src/store/index.js | 4 ++++ 4 files changed, 13 insertions(+), 43 deletions(-) diff --git a/src/helpers/cookie-helper.js b/src/helpers/cookie-helper.js index bf88ace6..0fb14dd3 100644 --- a/src/helpers/cookie-helper.js +++ b/src/helpers/cookie-helper.js @@ -112,9 +112,7 @@ function setISSCookieProperties(properties) { Will update the cookie if present, or create a new one if not. */ export function updateOrCreateISSCookie() { - console.log('in cookie function'); const store = useMainStore(); - console.log(store); // Set up cookie with all the props. setISSCookieProperties({ diff --git a/src/helpers/order-helper.js b/src/helpers/order-helper.js index 290b4c0e..0b89d8e5 100644 --- a/src/helpers/order-helper.js +++ b/src/helpers/order-helper.js @@ -6,54 +6,23 @@ import { updateOrCreateISSCookie } from '@/helpers/cookie-helper'; This will also set Referral information in the store after saving, and then update the cookie. To force synchronous behavior pass in 'true' for shouldAwaitSaveSessionQueue */ -// encapsulate when you transition back into heritage -// we need eon from first call to get pricing -// eon is a number that some services require -// save session takes time -// not necessary for much throughout the flow -// we want each save session call to happen sequentially, but asynchronously export async function saveSession({ shouldAwaitSaveSessionQueue = false }) { const store = useMainStore(); - console.log('order helper'); - console.log(store); - var saveSessionPromise; - if (store.applicationUser.saveSessionPromise){ - console.log('if promise exists'); - console.log(store.applicationUser.saveSessionPromise); + var saveSessionPromise = store.applicationUser.saveSessionPromise + ? store.applicationUser.saveSessionPromise.then(() => { return saveSessionHelper(store); }) + : saveSessionHelper(store); - // .then returns another promise but waiting for another to finish - saveSessionPromise = store.applicationUser.saveSessionPromise - .then(() => { - console.log('then'); - return saveSessionHelper(store); - }) - .catch((error) => { - console.log("saveSessionPromise failed: " + error.message); - }); - } - else { - console.log('else'); - saveSessionPromise = saveSessionHelper(store); - } - // var saveSessionPromise = - // store.applicationUser.saveSessionPromise - // ? store.applicationUser.saveSessionPromise.then(() => { return saveSessionHelper(store); }) - // : saveSessionHelper(store); - console.log('promise exists'); store.setSaveSessionPromise(saveSessionPromise); - console.log('set information'); + if (!store.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) { - console.log('pre await'); await saveSessionPromise; } - console.log('done'); } /* Encapsulates asynchronous Save Session logic inside a promise to allow for Save Session queuing */ async function saveSessionHelper(store) { - console.log('helper helper called'); const savedSessionInfo = await store.saveSession(); store.setSaveSessionInfo(savedSessionInfo.data); updateOrCreateISSCookie(); diff --git a/src/router/index.js b/src/router/index.js index be341fbb..a2efe1a7 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -88,13 +88,12 @@ router.afterEach(async (to, from) => { const store = useMainStore(); // Update lastPageVisited in the store store.updateLastPageVisited(to.name); - console.log('after each'); + + if (from.redirectedFrom == undefined){ + store.clearSaveSessionPromise(); + } - await saveSession({shouldAwaitSaveSessionQueue: true}).then(() => { - console.log('then'); - }).catch((error) => { - console.log(error); - console.log("catch"); + await saveSession({shouldAwaitSaveSessionQueue: true}).catch((error) => { if (from.name === issPageValues.WELCOME_PAGE) { router.navigate(navigationScenarios.SAVE_SESSION_FAILED, {query: {issPage: issPageValues.WELCOME_PAGE}}) } diff --git a/src/store/index.js b/src/store/index.js index 35a71604..d5587220 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -806,6 +806,10 @@ export const useMainStore = defineStore({ this.applicationUser.saveSessionPromise = promise; }, + clearSaveSessionPromise(){ + this.applicationUser.saveSessionPromise = null; + }, + saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); const isGlassToReplaceTheSame From 8bbd7afb776dec8aabd012fd09485686d00ea2c1 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 16:53:53 -0400 Subject: [PATCH 34/46] Adding parameter to indicate whether save session should be synchronous --- src/router/index.js | 8 ++++++-- src/router/router-constants/router-params.js | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/router/index.js b/src/router/index.js index a2efe1a7..de100b55 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -17,6 +17,7 @@ import applicationConfig from '@/constants/application-config'; import analyticsMixin from '@/mixins/analytics-mixin'; import navigationScenarios from './router-constants/navigation-scenarios'; import { saveSession } from "@/helpers/order-helper.js"; +import routerParams from '@/router/router-constants/router-params'; const routes = [ { @@ -93,9 +94,12 @@ router.afterEach(async (to, from) => { store.clearSaveSessionPromise(); } - await saveSession({shouldAwaitSaveSessionQueue: true}).catch((error) => { + const saveSessionSynchronous = !!from.params[routerParams.SAVE_SESSION_SYNCHRONOUS]; + await saveSession({shouldAwaitSaveSessionQueue: saveSessionSynchronous}).catch((error) => { if (from.name === issPageValues.WELCOME_PAGE) { - router.navigate(navigationScenarios.SAVE_SESSION_FAILED, {query: {issPage: issPageValues.WELCOME_PAGE}}) + router.navigate( + navigationScenarios.SAVE_SESSION_FAILED, + {query: {issPage: issPageValues.WELCOME_PAGE}}); } }); diff --git a/src/router/router-constants/router-params.js b/src/router/router-constants/router-params.js index 37b1300d..2465f965 100644 --- a/src/router/router-constants/router-params.js +++ b/src/router/router-constants/router-params.js @@ -1,5 +1,6 @@ const routerParams = Object.freeze({ - DISPLAY_VEHICLE_CHANGE_ALERT: 'displayVehicleChangeAlert' + DISPLAY_VEHICLE_CHANGE_ALERT: 'displayVehicleChangeAlert', + SAVE_SESSION_SYNCHRONOUS: 'saveSessionSynchronous' }); export default routerParams; From 5db1b97e1b832eb5b644197c29038f1c394b38dc Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 31 Aug 2023 17:00:29 -0400 Subject: [PATCH 35/46] Reverting unnecessary changes --- src/router/router-constants/navigation-scenarios.js | 2 +- src/store/index.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index 6fb510d2..38b59ba9 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -64,7 +64,7 @@ const navigationScenarios = Object.freeze({ CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES: 'CLICKED_FORWARD_WITH_POLICY_AND_VEHICLES', // Bailout - CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT', + CLICKED_FORWARD_WITH_BAILOUT: 'CLICKED_FORWARD_WITH_BAILOUT' }); export default navigationScenarios; diff --git a/src/store/index.js b/src/store/index.js index d5587220..69dcfd3c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1303,14 +1303,14 @@ export const useMainStore = defineStore({ }, async validateZip({ zip }) { - return globalMethods.callHttpClient({ + return await globalMethods.callHttpClient({ methods: endpoints.ValidateZip.method, endpoint: `${endpoints.ValidateZip.url}/${zip}` }); }, async validateClientTag(clientTag) { - return globalMethods.callHttpClient({ + return await globalMethods.callHttpClient({ methods: endpoints.ValidateClientTag.method, endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}` }); From 40c381fdb87dffc24091faed2f57be3821ebc033 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 11:07:57 -0400 Subject: [PATCH 36/46] Fixing tests --- src/store/store.spec.js | 196 +++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 114 deletions(-) diff --git a/src/store/store.spec.js b/src/store/store.spec.js index 03427c95..d03784f5 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -560,16 +560,14 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - vehicle: expect.objectContaining({ - year: vehicle.year, - make: vehicle.make, - model: vehicle.model, - style: vehicle.style, - carId: vehicle.carId, - vin: vehicle.vin, - licensePlateNumber: vehicle.registration.licensePlate - }) + vehicle: expect.objectContaining({ + year: vehicle.year, + make: vehicle.make, + model: vehicle.model, + style: vehicle.style, + carId: vehicle.carId, + vin: vehicle.vin, + licensePlateNumber: vehicle.registration.licensePlate }) }) } @@ -603,19 +601,17 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - damage: expect.objectContaining({ - numberOfChips: damage.numberOfChips, - isRepair: damage.isRepair, - partQuestionAnswers: damage.partQuestionAnswers, - moldingQuestionAnswers: damage.moldingQuestionAnswers, - capabilityQuestionAnswers: damage.capabilityQuestionAnswers, - dateOfLoss: policy.dateOfLoss, - damageCause: policy.damageCause, - damageState: policy.damageState, - damageCity: policy.damageCity, - isDamageGlassOnly: policy.isDamageGlassOnly - }) + damage: expect.objectContaining({ + numberOfChips: damage.numberOfChips, + isRepair: damage.isRepair, + partQuestionAnswers: damage.partQuestionAnswers, + moldingQuestionAnswers: damage.moldingQuestionAnswers, + capabilityQuestionAnswers: damage.capabilityQuestionAnswers, + dateOfLoss: policy.dateOfLoss, + damageCause: policy.damageCause, + damageState: policy.damageState, + damageCity: policy.damageCity, + isDamageGlassOnly: policy.isDamageGlassOnly }) }) }) @@ -650,21 +646,19 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - policy: expect.objectContaining({ - policyHolder: expect.objectContaining({ - policyFirstName: customer.firstName, - policyLastName: customer.lastName, - policyPhoneNumber: customer.phoneNumber, - policyEmail: customer.emailAddress - }), - policyNumber: policy.policyNumber, - policyZipCode: policy.policyZipCode, - noCoverage: policy.noCoverage, - policyLookupSuccessful: policy.policyLookupSuccessful, - originalDeductible, - currentDeductible - }) + policy: expect.objectContaining({ + policyHolder: expect.objectContaining({ + policyFirstName: customer.firstName, + policyLastName: customer.lastName, + policyPhoneNumber: customer.phoneNumber, + policyEmail: customer.emailAddress + }), + policyNumber: policy.policyNumber, + policyZipCode: policy.policyZipCode, + noCoverage: policy.noCoverage, + policyLookupSuccessful: policy.policyLookupSuccessful, + originalDeductible, + currentDeductible }) }) }) @@ -699,21 +693,19 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - customer: expect.objectContaining({ - address: expect.objectContaining({ - streetAddress: customer.address.streetAddress, - streetAddress2: customer.address.streetAddress2, - city: customer.address.city, - state: customer.address.state, - zipCode: customer.address.zipCode - }), - emailAddress: contactInfo.emailAddress, - firstName: contactInfo.firstName, - lastName: contactInfo.lastName, - phoneNumber: contactInfo.phoneNumber, - optInSms: contactInfo.requestTextUpdates - }) + customer: expect.objectContaining({ + address: expect.objectContaining({ + streetAddress: customer.address.streetAddress, + streetAddress2: customer.address.streetAddress2, + city: customer.address.city, + state: customer.address.state, + zipCode: customer.address.zipCode + }), + emailAddress: contactInfo.emailAddress, + firstName: contactInfo.firstName, + lastName: contactInfo.lastName, + phoneNumber: contactInfo.phoneNumber, + optInSms: contactInfo.requestTextUpdates }) }) }) @@ -736,12 +728,10 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - lineItems: expect.objectContaining({ - glassParts: lineItems.glassParts, - supportingItems: lineItems.supportingItems, - vaps: lineItems.vaps - }) + lineItems: expect.objectContaining({ + glassParts: lineItems.glassParts, + supportingItems: lineItems.supportingItems, + vaps: lineItems.vaps }) }) }) @@ -772,15 +762,13 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - payment: expect.objectContaining({ - InsuranceCoverage: expect.objectContaining({ - isVerified: payment.insuranceCoverage.isVerified, - coverageStatus: coverageStatus - }), - isInsurance: payment.isInsurance, - parentAccountNumber: accountNumber - }) + payment: expect.objectContaining({ + InsuranceCoverage: expect.objectContaining({ + isVerified: payment.insuranceCoverage.isVerified, + coverageStatus: coverageStatus + }), + isInsurance: payment.isInsurance, + parentAccountNumber: accountNumber }) }) }) @@ -807,17 +795,15 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - serviceLocation: expect.objectContaining({ - address: expect.objectContaining({ - streetAddress: serviceLocation.address, - city: serviceLocation.city, - state: serviceLocation.state, - zipCode: serviceLocation.zipCode, - zipCodeCtu: serviceLocation.zipCodeCtu - }), - techNotes: notesForTechnician - }) + serviceLocation: expect.objectContaining({ + address: expect.objectContaining({ + streetAddress: serviceLocation.address, + city: serviceLocation.city, + state: serviceLocation.state, + zipCode: serviceLocation.zipCode, + zipCodeCtu: serviceLocation.zipCodeCtu + }), + techNotes: notesForTechnician }) }) }) @@ -842,14 +828,12 @@ describe('Store', () => { expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { payload: expect.objectContaining({ - order: expect.objectContaining({ - schedule: expect.objectContaining({ - date: schedule.date, - startTime: schedule.startTime, - endTime: schedule.endTime, - routeCode: schedule.routeCode, - jobMaxMinutes: schedule.jobMaxMinutes - }) + schedule: expect.objectContaining({ + date: schedule.date, + startTime: schedule.startTime, + endTime: schedule.endTime, + routeCode: schedule.routeCode, + jobMaxMinutes: schedule.jobMaxMinutes }) }) }) @@ -867,9 +851,7 @@ describe('Store', () => { // Assert expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { - payload: expect.objectContaining({ - order: expect.objectContaining({ referralDate: referralDate }) - }) + payload: expect.objectContaining({ referralDate: referralDate }) }) ); }); @@ -885,9 +867,7 @@ describe('Store', () => { // Assert expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { - payload: expect.objectContaining({ - order: expect.objectContaining({ referralNumber: referralNumber }) - }) + payload: expect.objectContaining({ referralNumber: referralNumber }) } )); }); @@ -902,13 +882,9 @@ describe('Store', () => { // Asserts expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { - method: endpoints.SaveSession.method, - endpoint: endpoints.SaveSession.url, payload: expect.objectContaining({ - order: expect.objectContaining({ - damage: expect.objectContaining({ - glassToReplace: [] - }) + damage: expect.objectContaining({ + glassToReplace: [] }) }) }) @@ -924,13 +900,9 @@ describe('Store', () => { // Asserts expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { - method: endpoints.SaveSession.method, - endpoint: endpoints.SaveSession.url, payload: expect.objectContaining({ - order: expect.objectContaining({ - damage: expect.objectContaining({ - glassToReplace: [] - }) + damage: expect.objectContaining({ + glassToReplace: [] }) }) }) @@ -953,16 +925,12 @@ describe('Store', () => { // Asserts expect(globalMethods.callHttpClient).toHaveBeenCalledWith(expect.objectContaining( { - method: endpoints.SaveSession.method, - endpoint: endpoints.SaveSession.url, payload: expect.objectContaining({ - order: expect.objectContaining({ - damage: expect.objectContaining({ - glassToReplace: expect.arrayContaining([ - {location: location1, name: name1}, - {location: location2, name: name2} - ]) - }) + damage: expect.objectContaining({ + glassToReplace: expect.arrayContaining([ + {location: location1, name: name1}, + {location: location2, name: name2} + ]) }) }) }) From b0353cf7f7df10dae7a46f0810f0daaca778c1f8 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 11:15:38 -0400 Subject: [PATCH 37/46] Setting current and original deductible --- src/store/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/store/index.js b/src/store/index.js index fa0e4c0d..c582e318 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -113,7 +113,9 @@ const getDefaultState = () => ({ referralCorrelationId: '00000000-0000-0000-0000-000000000000', referralSequenceNumber: null, eon: null, - workOrderNumber: null + workOrderNumber: null, + originalDeductible: null, + currentDeductible: null }, applicationUser: { experiments: [], @@ -898,6 +900,10 @@ export const useMainStore = defineStore({ this.order.policy.deductible.replace = vehicle.deductible; this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible; + // TODO logic should be more complicated later on + this.order.originalDeductible = vehicle.deductible; + this.order.currentDeductible = vehicle.deductible; + this.resetSupportingItemsState(); this.resetVapsState(); }, From 412b2bebb6e651c09874cd972b36e0bb34213e2e Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 12:06:20 -0400 Subject: [PATCH 38/46] Swapping store call --- src/layouts/address-lookup/address-lookup.vue | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index 5f913011..9f86be4e 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -92,7 +92,7 @@ import routerParams from '@/router/router-constants/router-params'; import { getDamageString, isGlassAvailableForCarId } from '@/helpers/damage-helper'; import vinPagesMixin from '@/mixins/vin-pages-mixin'; -import { useMainStore } from '@/store'; +import { useMainStore } from '@/store/index.js'; export default { name: 'address-lookup', @@ -152,7 +152,7 @@ export default { // eslint-disable-next-line max-len `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; const vinYmmExpected = - `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`; + `${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model}`; return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText') .replaceAll('{custom:damage}', getDamageString()) @@ -171,7 +171,7 @@ export default { `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`; const vinYmmsExpected = // eslint-disable-next-line max-len - `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`; + `${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model} ${useMainStore().order.vehicle.style}`; return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText') .replaceAll('{custom:damage}', getDamageString()) @@ -183,7 +183,7 @@ export default { // eslint-disable-next-line max-len `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; const vinYmmExpected = - `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`; + `${useMainStore().order.vehicle.year} ${useMainStore().order.vehicle.make} ${useMainStore().order.vehicle.model}`; return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase()); } }, @@ -203,7 +203,7 @@ export default { }, methods: { arePagePrerequisitesValid() { - return this.mainStore.order.vehicle.carId !== null; + return useMainStore().order.vehicle.carId !== null; }, backButtonAction() { @@ -283,7 +283,7 @@ export default { vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin }); } else if (carsFound.length > 1) { // If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info - const matchingCars = carsFound.filter((vin) => vin.vehicle.carId === this.mainStore.order.vehicle.carId); + const matchingCars = carsFound.filter((vin) => vin.vehicle.carId === useMainStore().order.vehicle.carId); if (matchingCars.length === 1) { vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, { From a511a550bf296d4ed98884231f3ccf0dcb51af01 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 12:18:57 -0400 Subject: [PATCH 39/46] Fixing store reference in remaining prerequisites --- src/layouts/address-vehicles/address-vehicles.vue | 2 +- src/layouts/license-plate-lookup/license-plate-lookup.vue | 2 +- src/layouts/vehicle-parts/vehicle-parts.vue | 7 ++++--- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/layouts/address-vehicles/address-vehicles.vue b/src/layouts/address-vehicles/address-vehicles.vue index 63cb3572..4494d938 100644 --- a/src/layouts/address-vehicles/address-vehicles.vue +++ b/src/layouts/address-vehicles/address-vehicles.vue @@ -226,7 +226,7 @@ export default { getRouterLinkRouteFromCopy, getRouterLinkDisplayTextFromCopy, arePagePrerequisitesValid() { - if (this.mainStore.order.vehicle.carId) { + if (useMainStore().order.vehicle.carId) { return true; } return false; diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index 91d70b2b..a1b46623 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -218,7 +218,7 @@ export default { }, methods: { arePagePrerequisitesValid() { - return this.mainStore.order.vehicle.carId !== null; + return useMainStore().order.vehicle.carId !== null; }, loadDefaultsFromStore() { this.customerQuestions = this.mainStore.customerData.addressQuestions.state; diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue index 7848c4e3..52b33ed8 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.vue +++ b/src/layouts/vehicle-parts/vehicle-parts.vue @@ -77,6 +77,7 @@ import issPageValues from '@/router/router-constants/issPage-values'; import { Form } from 'vee-validate'; import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin'; import BaseFormMixin from '@/mixins/base-form-mixin.js'; +import { useMainStore } from '@/store'; export default { name: 'vehicle-parts', @@ -178,9 +179,9 @@ export default { arePagePrerequisitesValid() { // Check if isRepair is populated and if the pageData we need is here (Parts data) return ( - this.mainStore.damage.isRepair != null - && this.mainStore.pageData(issPageValues.VEHICLE_PARTS) - && Object.keys(this.mainStore.pageData(issPageValues.VEHICLE_PARTS)).length !== 0 + useMainStore().damage.isRepair != null + && useMainStore().pageData(issPageValues.VEHICLE_PARTS) + && Object.keys(useMainStore().pageData(issPageValues.VEHICLE_PARTS)).length !== 0 ); }, async forwardButtonAction() { From 6043b0ce8f03037270c3e1b6b5b54b98d3e80dc9 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 12:42:05 -0400 Subject: [PATCH 40/46] Swapping loose equality for strict --- src/router/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/router/index.js b/src/router/index.js index e5eeee1e..30539023 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -124,7 +124,7 @@ router.afterEach(async (to, from) => { // Update lastPageVisited in the store store.updateLastPageVisited(to.name); - if (from.redirectedFrom == undefined){ + if (from.redirectedFrom === undefined){ store.clearSaveSessionPromise(); } From 083cef3b85afd3e49c3b94a2d089a17891a99417 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 12:51:56 -0400 Subject: [PATCH 41/46] save session synchronous after welcome page and coverage statement page --- .../coverage-statement/coverage-statement.vue | 20 ++++++++++++++----- src/layouts/welcome-page/welcome-page.vue | 10 +++++++--- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index f27b2208..6dce9a1b 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -337,29 +337,39 @@ export default { if (this.unverified || this.verifiedDeductible) { this.$router.navigate( navigationScenarios.CLICKED_FORWARD, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } else if (this.verifiedITAC || this.verifiedNoComp) { if (this.selectedProvider === 'Safelite') { this.$router.navigate( navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } else if (useMainStore().issConfig.enableTPAFlow) { this.$router.navigate( navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } else { this.$router.navigate( navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } } else { this.$router.navigate( navigationScenarios.CLICKED_FORWARD_WITH_INVALID_STATE, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } }, diff --git a/src/layouts/welcome-page/welcome-page.vue b/src/layouts/welcome-page/welcome-page.vue index e9943ba6..45666547 100644 --- a/src/layouts/welcome-page/welcome-page.vue +++ b/src/layouts/welcome-page/welcome-page.vue @@ -351,7 +351,7 @@ export default { this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES, this.$route, {}, - {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }, this.vehiclesFound ); } else { @@ -359,14 +359,18 @@ export default { // navigate to vehicle-selection page (manual entry) this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } } else { // if policy lookup is unsuccessful, navigate to policy-holder-details page this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED, - this.$route + this.$route, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); } }, From da44fe9e1caec3b76371e2480370b63e17f1c685 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 12:53:04 -0400 Subject: [PATCH 42/46] Adding routerParams reference --- src/layouts/coverage-statement/coverage-statement.vue | 1 + src/layouts/welcome-page/welcome-page.vue | 1 + 2 files changed, 2 insertions(+) diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index 6dce9a1b..ccd03999 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -120,6 +120,7 @@ import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin.js'; import globalRules from '@/constants/global-rules.js'; import baseFormMixin from '@/mixins/base-form-mixin.js'; import navigationScenarios from '@/router/router-constants/navigation-scenarios.js'; +import routerParams from '@/router/router-constants/router-params'; export default { name: 'coverage-statement', diff --git a/src/layouts/welcome-page/welcome-page.vue b/src/layouts/welcome-page/welcome-page.vue index 45666547..c1964c7f 100644 --- a/src/layouts/welcome-page/welcome-page.vue +++ b/src/layouts/welcome-page/welcome-page.vue @@ -184,6 +184,7 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js'; import { useMainStore } from '@/store'; import states from '@/constants/states'; import globalRules from '@/constants/global-rules'; +import routerParams from '@/router/router-constants/router-params'; // define validation rules defineRule('loss-date-required', required(errorMessages.LOSS_DATE_REQUIRED)); From a91d4ad43176048a65dc18ee2dd6987b07537d9a Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 13:01:35 -0400 Subject: [PATCH 43/46] Fixing parsing bug --- src/store/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index c582e318..a2bfbcd7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -901,8 +901,8 @@ export const useMainStore = defineStore({ this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible; // TODO logic should be more complicated later on - this.order.originalDeductible = vehicle.deductible; - this.order.currentDeductible = vehicle.deductible; + this.order.originalDeductible = parseFloat(vehicle.deductible); + this.order.currentDeductible = parseFloat(vehicle.deductible); this.resetSupportingItemsState(); this.resetVapsState(); From 50313df9fcda1e9e14e9c74001aa51eeda648f11 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 13:13:20 -0400 Subject: [PATCH 44/46] fixing tests --- .../coverage-statement.spec.js | 37 ++++++++++++++++--- src/layouts/welcome-page/welcome-page.spec.js | 11 ++++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/layouts/coverage-statement/coverage-statement.spec.js b/src/layouts/coverage-statement/coverage-statement.spec.js index 389444f5..857d1dcb 100644 --- a/src/layouts/coverage-statement/coverage-statement.spec.js +++ b/src/layouts/coverage-statement/coverage-statement.spec.js @@ -9,6 +9,7 @@ import navigationScenarios from '@/router/router-constants/navigation-scenarios. import { getRandomString, getRandomInt } from '@/helpers/data-generation.js'; import settleAllPromises from '@/helpers/layout-helper.js'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; +import routerParams from '@/router/router-constants/router-params'; jest.mock('@/helpers/layout-helper.js', () => jest.fn()); @@ -457,7 +458,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); test('If Verified Deductible, navigate forward with CLICKED_FORWARD scenario', () => { // Arrange @@ -493,7 +498,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); test('If Verified ITAC and selected Safelite, navigate forward with CLICKED_FORWARD_WITH_SAFELITE scenario', () => { // Arrange @@ -530,7 +539,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); test('If Verified ITAC, selected other shop, and TPA enabled, navigate forward w/ CLICKED_FORWARD_WITH_TPA_ENABLED', () => { // Arrange @@ -570,7 +583,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_TPA_ENABLED, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); test('If Verified ITAC, selected other shop, and TPA disabled, navigate forward w/ CLICKED_FORWARD_WITH_TPA_DISABLED', () => { // Arrange @@ -610,7 +627,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_TPA_DISABLED, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); test('If No Comp and selected Safelite, navigate forward with CLICKED_FORWARD scenario', () => { // Arrange @@ -636,7 +657,11 @@ describe('coverageStatement.vue', () => { // Assert expect(wrapper.vm.$router.navigate) - .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, undefined); + .toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }); }); }); describe('ADAS', () => { diff --git a/src/layouts/welcome-page/welcome-page.spec.js b/src/layouts/welcome-page/welcome-page.spec.js index ac4e132e..697451c8 100644 --- a/src/layouts/welcome-page/welcome-page.spec.js +++ b/src/layouts/welcome-page/welcome-page.spec.js @@ -10,6 +10,7 @@ import { getMountOptions } from '@/helpers/unit-test-helper.js'; import applicationConfig from '@/constants/application-config'; import { useMainStore } from '@/store'; import navigationScenarios from '@/router/router-constants/navigation-scenarios'; +import routerParams from '@/router/router-constants/router-params'; // Mock our module for promises. jest.mock('@/helpers/layout-helper.js', () => jest.fn()); @@ -182,7 +183,7 @@ describe('navigation', () => { navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES, undefined, {}, - {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true }, mockvehicles ); }); @@ -208,7 +209,9 @@ describe('navigation', () => { // Assert expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES, - undefined + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); }); test('if policy is not found, navigate to policy-holder-details page', async () => { @@ -228,7 +231,9 @@ describe('navigation', () => { // Assert expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED, - undefined + undefined, + {}, + { [routerParams.SAVE_SESSION_SYNCHRONOUS]: true } ); }); }); From 647eb4c9198d24e131d329cb6f7a93f5c6d71d56 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 6 Sep 2023 17:21:58 -0400 Subject: [PATCH 45/46] Remove bailout when no vehicle found --- src/layouts/vin-lookup/vin-lookup.vue | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index bb91d977..67bd391f 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -112,8 +112,7 @@ export default { vehicleFromLookup: null, vin: this.getVinFromStore(), forwardButtonCarStyle: '', - vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0, - bailout: false + vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0 }; }, computed: { @@ -179,15 +178,8 @@ export default { // because the form itself actually passes its client-side validation. // SSR-189 Scenario #4. this.$refs.siteFooter.enableForwardAction(); - this.bailout = true; } - if (this.bailout) { - return this.$router.navigate( - this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, - this.$route - ); - } // Add vin bcs the response from the service doesn't contain vin this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { vin: this.vin }); } From b95124b428508013c9cf5438c02d0fbb6d24bbbf Mon Sep 17 00:00:00 2001 From: brydon1 Date: Thu, 7 Sep 2023 11:05:48 -0400 Subject: [PATCH 46/46] Removing bailout navigation test --- src/layouts/vin-lookup/vin-lookup.spec.js | 28 ----------------------- 1 file changed, 28 deletions(-) diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js index 2e59dd23..d38cd24c 100644 --- a/src/layouts/vin-lookup/vin-lookup.spec.js +++ b/src/layouts/vin-lookup/vin-lookup.spec.js @@ -476,34 +476,6 @@ describe('vin-lookup.vue', () => { ); }); }); - - test('Selected vehicle VIN do not match vehicles (CarIDs) in our system then navigate forward to bailout page.', async () => { - // Arrange - const user = userEvent.setup(); - lookupVehicleByVin.mockResponse.data.error = true; - - jest.spyOn(VinLookupComponent.methods, lookupVehicleByVin.methodName) - .mockResolvedValue(lookupVehicleByVinError.mockResponse); - - mountOptions.data = () => ({ - needToLookupVehicle: true, - bailout: true, - vin: mockValidVin - }); - - const { container } = render(VinLookupComponent, mountOptions); - const continueButton = container.querySelector(continueButtonQuerySelector); - await user.click(continueButton); - - await flushPromises(); - await waitFor(() => { - expect(mockRouter.navigate).toHaveBeenCalledTimes(1); - expect(mockRouter.navigate).toHaveBeenCalledWith( - navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, - mockRoute - ); - }); - }); }); }); });