DigitalConsumer.ISS/src/store/index.js

1405 lines
57 KiB
JavaScript

/* eslint-disable max-len */
import { defineStore } from 'pinia';
import { endpoints } from '@/constants/endpoints';
// eslint-disable-next-line import/no-cycle
import { getDateForSavedSessionTimeout } from '@/helpers/session-helper';
// 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';
const storeId = 'main';
const getDefaultState = () => ({
order: {
vehicle: {
year: null,
make: null,
model: null,
style: null,
carId: null,
category: null,
vin: null,
imageUrl: null,
imageVifNumber: null,
imageColor: null,
registration: {
licensePlate: null,
address: null,
city: null,
state: null,
zipCode: null,
firstName: null,
lastName: null
}
},
damage: {
isRepair: null,
numberOfChips: null,
glassToReplace: null,
partQuestionAnswers: null,
moldingQuestionAnswers: null,
capabilityQuestionAnswers: null
},
policy: {
policyNumber: null,
policyZipCode: null,
dateOfLoss: null,
damageCause: null,
damageState: null,
damageCity: null,
isDamageGlassOnly: null,
policyLookupSuccessful: null,
noCoverage: null,
deductible: {
repair: null, // numerical value; how much customer owes on deductible in repair case
replace: null // numerical value; how much customer owes on deductible in replace case,
}
},
customer: {
address: {
streetAddress: null,
streetAddress2: null,
city: null,
state: null,
zipCode: null
},
firstName: null,
lastName: null,
emailAddress: null,
phoneNumber: null
},
serviceLocation: {
address: null,
city: null,
state: null,
zipCode: null,
zipCodeCtu: null
},
lineItems: {
glassParts: null,
otherParts: null,
supportingItems: null,
vaps: null
},
payment: {
isInsurance: true,
insuranceCoverage: {
isVerified: false,
coverageStatus: coverageStatuses.PENDING
}
},
referralNumber: null,
referralDate: null,
contactInfo: {
firstName: null,
lastName: null,
emailAddress: null,
phoneNumber: null,
requestTextUpdates: false,
notesForTechnician: ''
}
},
applicationUser: {
experiments: [],
eventBus: [],
pageData: {},
savedSessionTimeout: getDateForSavedSessionTimeout(),
saveSessionPromise: null,
savedSessionId: null,
crmCustomerId: null,
lastPageVisited: null,
triggeredSiteEntry: false
},
issConfig: {
clientName: 'Generic Insurance', // this is the default and will be overriden by the client's name
clientDisplayName: 'Generic Insurance', // this is the default and will be overridden by the client's name or client display name.
styleSheet: '', // Stylesheet used by the client.
accountNumber: 0, // Account number used by the client.
isCoverageEnabled: false, // Indicates if we should be calling coverage on this flow.
isClaimRegistrationRequired: false, // Indicates if the claim registration call needs to be made for a client to complete coverage verification.
isAuthenticated: false, // Indicates if user is authenticated or not.
enableTPAFlow: false, // Indicates if the TPA flow is supported for this client.
successReturnURL: null, // Client URL to return the user to upon a successfull flow completetion (order submission).
failureReturnURL: null, // Client URL to return the user to when they encounter an error or bailout and are unable to complete the flow.
disabledFields: { // Fields that are disabled and read only if sent over from a client.
policyNumber: null,
policyZipCode: null
}
}
});
export const state = getDefaultState();
export const useMainStore = defineStore({
id: storeId,
state: () => state,
getters: {
hasRecalibrationPart: (state) => getHasRecalibrationPart(state),
vehicle: (state) => state.order.vehicle,
damage: (state) => state.order.damage,
lineItems: (state) => state.order.lineItems,
payment: (state) => state.order.payment,
policy: (state) => state.order.policy,
hasAnyNonWindshieldGlassParts: (state) => !state.order.policy.isDamageGlassOnly,
isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired,
eventBusItem: (state) => (eventCategory, eventSubCategory) => {
const matchedEvent = state.applicationUser.eventBus.find(({ category, subCategory }) => category === eventCategory && subCategory === eventSubCategory);
return matchedEvent?.eventValue;
},
eventBus: (state) => state.applicationUser.eventBus,
applicationUserObj: (state) => state.applicationUser,
pageData: (state) => (page) => state.applicationUser.pageData[page],
customerData: (state) => {
if (state.order.vehicle.registration.address) {
const { registration } = state.order.vehicle;
return {
addressQuestions: {
streetAddress: registration.address,
city: registration.city,
state: registration.state,
zipCode: registration.zipCode
},
firstName: registration.firstName,
lastName: registration.lastName
};
}
const { address } = state.order.customer;
return {
addressQuestions: {
streetAddress: address.streetAddress,
city: address.city,
state: address.state,
zipCode: address.zipCode
},
firstName: state.order.customer.firstName,
lastName: state.order.customer.lastName
};
},
contactInfo: (s) => ({
firstName: s.order.contactInfo.firstName ?? s.order.customer.firstName,
lastName: s.order.contactInfo.lastName ?? s.order.customer.lastName,
emailAddress: s.order.contactInfo.emailAddress ?? s.order.customer.emailAddress,
phoneNumber: s.order.contactInfo.phoneNumber ?? s.order.customer.phoneNumber,
requestTextUpdates: s.order.contactInfo.requestTextUpdates ?? false,
notesForTechnician: s.order.contactInfo.notesForTechnician
}),
experimentOrder: (state) => ({
issVehicleYear: state.order.vehicle.year,
issVehicleMake: state.order.vehicle.make,
issVehicleModel: state.order.vehicle.model,
issVehicleStyle: state.order.vehicle.style,
issIsRepair: state.order.damage.isRepair,
issNumberOfChips: state.order.damage.numberOfChips,
issCarId: state.order.vehicle.carId,
issServiceCity: state.order.serviceLocation.city,
issServiceState: state.order.serviceLocation.state,
issServiceZipCode: state.order.serviceLocation.zipCode,
issParentAccountNumber: state.order.accountNumber,
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),
issOrderPartNumbers: [
...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')
]
}),
experimentSettings: (state) => state.applicationUser.experiments
.map((x) => x.settings)
.reduce((r, c) => Object.assign(r, c), {}) ?? {}
},
actions:
{
// Content API Actions
lookupVinByAddress({ licenseLastName, licenseStreetAddress, licenseZip, licenseState }) {
return globalMethods.callHttpClient({
method: endpoints.LookupVinByAddress.method,
endpoint: endpoints.LookupVinByAddress.url,
payload: {
licenseLastName,
licenseStreetAddress,
licenseZip,
licenseState
}
});
},
getRouteInfo(pageName) {
return globalMethods.callHttpClient({
method: endpoints.GetRouteInfo.method,
endpoint: endpoints.GetRouteInfo.url(applicationConfig.APPLICATION_ABBREVIATION),
payload: {
pageName
}
});
},
getHomepageName() {
return globalMethods.callHttpClient({
method: endpoints.GetHomepageInfo.method,
endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION)
});
},
getPageData(pageName) {
return globalMethods.callHttpClient({
method: endpoints.GetPageData.method,
endpoint: endpoints.GetPageData.url(applicationConfig.APPLICATION_ABBREVIATION, pageName),
payload: {}
});
},
// Vehicle API Actions
getVehicleYears() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleYears.method,
endpoint: endpoints.GetVehicleYears.url,
payload: {}
});
},
getVehicleMakes() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleMakes.method,
endpoint: endpoints.GetVehicleMakes.url + this.order.vehicle.year,
payload: {}
});
},
getVehicleModels() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleModels.method,
endpoint: `${endpoints.GetVehicleModels.url}/${this.order.vehicle.year}/${this.order.vehicle.make}`,
payload: {}
});
},
getVehicleStyles() {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleStyles.method,
endpoint: `${endpoints.GetVehicleStyles.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}`,
payload: {}
});
},
getDamageOptions(carId) {
return globalMethods.callHttpClient({
methods: endpoints.GetDamageOptions.method,
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
payload: {}
});
},
getIsVinbyAddressPermissible() {
try {
const response = globalMethods.callHttpClient({
method: endpoints.IsVinbyAddressPermissible.method,
endpoint: `${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
payload: {}
});
return response;
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
}
},
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({
method: endpoints.CoveragePolicyInfo.method,
endpoint: endpoints.CoveragePolicyInfo.url,
payload: {
accountNumber,
policyNumber,
dateOfLoss,
zipCode,
correlationId: placeHolderCorrelationId
}
}).then((r) => {
const responsePolicy = r.data.policies?.[0];
policy.policyLookupSuccessful = !!responsePolicy;
return r;
}, (r) => {
policy.policyLookupSuccessful = false;
return r;
});
return response;
} catch (responseError) {
policy.policyLookupSuccessful = false;
return {
error: {
status: responseError.status
}
};
}
},
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) => {
globalMethods.callHttpClient({
method: endpoints.RegisterClaim.method,
endpoint: endpoints.RegisterClaim.url,
payload:
{
correlationId: placeHolderCorrelationId,
accountNumber: this.issConfig.accountNumber?.toString() ?? '',
insured: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName,
address: {
addressLine1: this.order.customer.address.streetAddress,
addressLine2: this.order.customer.address.streetAddress2,
city: this.order.customer.address.city,
state: this.order.customer.address.state,
zipCode: this.order.customer.address.zipCode,
country: 'US' // TODO set from store
},
homePhone: {
number: this.order.customer.phoneNumber?.replaceAll(nonNumberCharRegex, '') ?? ''
}
},
driver: {
firstName: this.order.customer.firstName,
lastName: this.order.customer.lastName
},
caller: {
homePhone: {}
},
policyInfo: {
policyNumber: this.order.policy.policyNumber,
safelitePolicy: {
policies: []
}
},
lossInfo: {
dateOfLoss: this.order.policy.dateOfLoss,
location: {
city: this.order.policy.damageCity,
state: this.order.policy.damageState,
country: 'US' // TODO set from store
},
vehicle: {
year: this.order.vehicle.year?.toString() ?? '',
make: this.order.vehicle.make,
model: this.order.vehicle.model,
vin: this.order.vehicle.vin
},
damageDescription: this.order.policy.damageCause
}
}
}).then((response) => {
const registerClaimFailed = response.data.isError;
order.payment.insuranceCoverage.isVerified = !registerClaimFailed;
if (registerClaimFailed) {
this.order.payment.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
} else if (this.policy.noCoverage) {
this.order.payment.insuranceCoverage.coverageStatus = coverageStatuses.NO_COMP;
} else {
this.order.payment.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED;
}
return resolve(response);
}, (error) => {
this.order.payment.insuranceCoverage.isVerified = false;
this.order.payment.insuranceCoverage.coverageStatus = coverageStatuses.PENDING;
return reject(error);
});
});
},
async lookupVinByPlate(licensePlate, licenseState) {
try {
const response = await globalMethods.callHttpClient({
method: endpoints.LookupVinByPlate.method,
endpoint: endpoints.LookupVinByPlate.url,
payload: {
licensePlate,
licenseState
}
});
return response;
} catch (responseError) {
return {
error: {
status: responseError.status
}
};
}
},
// PartsOrQuestions API Actions
async getPartsOrQuestions() {
this.resetPartsAndDependencies();
const { vehicle } = this;
const { damage } = this;
const { order } = this;
const { carId } = vehicle;
const glassArray = damage.glassToReplace;
const zipCode = vehicle.registration.zipCode ? vehicle.registration.zipCode : order.customer.address.zipCode;
const { vin } = vehicle;
// create a new array to avoid mutating state
const glassArrayForPayload = convertGlassPieceNamingForApi(glassArray);
const response = await globalMethods.callHttpClient({
method: endpoints.GetPartsOrQuestions.method,
endpoint: endpoints.GetPartsOrQuestions.url,
payload: {
carId,
glassPieces: glassArrayForPayload,
zip: zipCode,
vin
}
});
// Flatten location and name properties
response.data.partsOrQuestions = convertGlassPieceNamingFromApi(response.data.partsOrQuestions);
return response;
},
async getParts() {
const { vehicle } = this.order;
const { damage } = this.order;
const { order } = this;
const { carId } = vehicle;
const glassArray = damage.glassToReplace;
const resultsArray = damage.partQuestionAnswers;
const zipCode = vehicle.registration.zipCode ? vehicle.registration.zipCode : order.customer.address.zipCode;
const { vin } = vehicle;
// create a new array to avoid mutating state
const glassArrayForPayload = convertGlassPieceNamingForApi(glassArray);
const resultsArrayForPayload = convertResultsForApi(resultsArray);
const response = await globalMethods.callHttpClient({
method: endpoints.GetParts.method,
endpoint: endpoints.GetParts.url,
payload: {
carId,
glassPieces: glassArrayForPayload,
answerResults: resultsArrayForPayload,
zip: zipCode,
vin
}
});
// Flatten location and name properties
response.data.glassPieceParts = convertGlassPieceNamingFromApi(response.data.glassPieceParts);
return response;
},
getCapabilityQuestions(carId, partNumber) {
return globalMethods.callHttpClient({
method: endpoints.GetCapabilityQuestions.method,
endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`
});
},
getPartFromCapabilityQuestionAnswer(glassLocation) {
const pageData = this.pageData(issPageValues.CAPABILITY_QUESTIONS);
const part = pageData.partsOrQuestions.find((x) => x.glassLocation === glassLocation)
.parts[0];
const { capabilityQuestionAnswers } = this.order.damage;
const capabilityQuestionAnswersForPart = capabilityQuestionAnswers.find((x) => x.glassLocation === glassLocation);
return globalMethods.callHttpClient({
method: endpoints.GetPartFromCapabilityAnswer.method,
endpoint: endpoints.GetPartFromCapabilityAnswer.url,
payload: {
part,
capabilityAnswerResults: capabilityQuestionAnswersForPart
}
});
},
async getWipers() {
const { carId } = this.order.vehicle;
// WARNING
// TODO: this is temp test code until serviceLocation is complete.
// const serviceZipCode = this.order.serviceLocation.zipCode;
const serviceZipCode = '44902';
return globalMethods
.callHttpClient({
method: endpoints.GetWipers.method,
endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`
})
.catch((error) => {
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
console.error(error);
return [];
});
},
async getRainDefense() {
return globalMethods
.callHttpClient({
method: endpoints.GetRainDefense.method,
endpoint: `${endpoints.GetRainDefense.url}`
})
.catch((error) => {
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
console.error(error);
return [];
});
},
async getSupportingItems() {
const glassPartsArray = this.order.lineItems.glassParts ?? [];
const { carId } = this.order.vehicle;
const { isRepair } = this.order.damage;
const { numberOfChips } = this.order.damage;
return globalMethods
.callHttpClient({
method: endpoints.GetSupportingItems.method,
endpoint: endpoints.GetSupportingItems.url,
payload: {
carId,
damageType: isRepair ? 'Repair' : 'Replace',
parentAccountNumber: applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
parts: glassPartsArray,
numberOfRepairChips: isRepair ? numberOfChips : 0
}
});
},
async getPriceOrderItems(availableLineItems) {
let zipCodeToUse = this.order.serviceLocation.zipCode;
let ctuToUse = this.order.serviceLocation.zipCodeCtu;
const availableLineItemsFormattedForRequest
= getLineItemQueryStringForPricing(availableLineItems);
const { vehicle } = this.order;
// WARNING
// TODO: this is temp test code until serviceLocation is complete.
// and ctu is available. Also, EON may need to be implemented.
zipCodeToUse = '44902';
ctuToUse = '01820';
const queryString
= `ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}`
+ `&CTU=${ctuToUse}`
+ `&CarId=${vehicle.carId}`
+ `&Make=${vehicle.make}`
+ `&Model=${vehicle.model}`
+ `&Year=${vehicle.year}`
+ '&EON=0'
+ `&ZipCode=${zipCodeToUse}`
+ `${availableLineItemsFormattedForRequest}`;
const response = await globalMethods
.callHttpClient({
method: endpoints.GetPriceOrderItems.method,
endpoint: `${endpoints.GetPriceOrderItems.url}?${queryString}`
}).catch((error) => {
console.error(error);
return [];
});
availableLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems);
return availableLineItems;
},
getServiceabilityDetails({ serviceZipCode }) {
const lineItemsWithOnlyPartNumbers = this.order.lineItems.glassParts.map((glassPart) => ({
partNumber: glassPart.partNumber
}));
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');
return globalMethods.callHttpClient({
method: endpoints.GetServiceabilityDetails.method,
endpoint: `${endpoints.GetServiceabilityDetails.url}?zip=${serviceZipCode}&carId=${carId}&${lineItems}&${glassPieces}`
});
},
lookupVehicleByVin(vin) {
return globalMethods.callHttpClient({
method: endpoints.LookupVehicleByVin.method,
endpoint: endpoints.LookupVehicleByVin.url,
payload: {
vin
}
});
},
setVehicle() {
return globalMethods
.callHttpClient({
methods: endpoints.GetVehicle.method,
endpoint: `${endpoints.GetVehicle.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}/${this.order.vehicle.style}`,
payload: {}
})
.then((response) => {
this.updateVehicle(response.data);
return response;
});
},
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
&& 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);
if (isDamageChanging) {
// Reset dependent state when changing
// Was resetGlassPartsState, added dependencies for SSR-290
this.resetPartsAndDependencies();
// Save new values
this.updateIsRepair(isWindshieldRepair);
this.updateNumberOfChips(isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null);
this.updateGlassToReplace(selectedGlassToReplace);
}
},
updateRegistration(registrationInfo) {
this.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
this.order.vehicle.registration.address = registrationInfo?.address;
this.order.vehicle.registration.city = registrationInfo?.city;
this.order.vehicle.registration.state = registrationInfo?.state;
this.order.vehicle.registration.zipCode = registrationInfo?.zipCode;
this.order.vehicle.registration.firstName = registrationInfo?.firstName;
this.order.vehicle.registration.lastName = registrationInfo?.lastName;
},
updateServiceLocation(serviceLocationInfo) {
this.order.serviceLocation.address = serviceLocationInfo.address;
this.order.serviceLocation.city = serviceLocationInfo.city;
this.order.serviceLocation.state = serviceLocationInfo.state;
this.order.serviceLocation.zipCode = serviceLocationInfo.zipCode;
this.order.serviceLocation.zipCodeCtu = serviceLocationInfo.zipCodeCtu;
},
resetRegistrationState() {
this.order.vehicle.registration.licensePlate = null;
this.order.vehicle.registration.address = null;
this.order.vehicle.registration.city = null;
this.order.vehicle.registration.state = null;
this.order.vehicle.registration.zipCode = null;
this.order.vehicle.registration.firstName = null;
this.order.vehicle.registration.lastName = null;
},
updateSupportingItems(partsData) {
this.order.lineItems.supportingItems = partsData;
},
updateVaps(partsData) {
this.order.lineItems.vaps = partsData;
},
updateVehicle(vehicle) {
// Assuming that the method caller pass all the properties.
// otherwise need to check for undefined for every property.
this.vehicle.carId = vehicle.carId;
this.order.vehicle.category = vehicle.category;
this.order.vehicle.year = vehicle.year;
this.order.vehicle.make = vehicle.make;
this.order.vehicle.model = vehicle.model;
this.order.vehicle.style = vehicle.style;
this.order.vehicle.vin = vehicle.vin;
this.order.vehicle.imageUrl = vehicle.imageUrl;
this.order.vehicle.imageVifNumber = vehicle.imageVifNumber;
this.order.vehicle.imageColor = vehicle.imageVifColor;
// These could be undefined
this.order.policy.noCoverage = vehicle.noCoverage;
this.order.policy.deductible.replace = vehicle.deductible;
this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible;
this.resetSupportingItemsState();
this.resetVapsState();
},
updateVehicleVin(vin) {
this.order.vehicle.vin = vin;
},
resetVehicleState() {
this.order.vehicle.year = null;
this.order.vehicle.make = null;
this.order.vehicle.model = null;
this.order.vehicle.style = null;
this.order.vehicle.carId = null;
this.order.vehicle.category = null;
this.order.vehicle.vin = null;
this.order.vehicle.imageUrl = null;
this.order.vehicle.imageVifNumber = null;
this.order.vehicle.imageColor = null;
},
resetGlassPartsState() {
this.order.lineItems.glassParts = null;
this.order.damage.partQuestionAnswers = null;
this.order.damage.moldingQuestionAnswers = null;
this.order.damage.capabilityQuestionAnswers = null;
this.applicationUser.pageData[issPageValues.PART_QUESTIONS] = null;
this.applicationUser.pageData[issPageValues.VEHICLE_PARTS] = null;
this.applicationUser.pageData[issPageValues.MOLDING_QUESTIONS] = null;
this.applicationUser.pageData[issPageValues.CAPABILITY_QUESTIONS] = null;
},
resetSupportingItemsState() {
this.order.lineItems.supportingItems = null;
},
resetVapsState() {
this.order.lineItems.vaps = null;
},
resetDamageState() {
this.order.damage.isRepair = null;
this.order.damage.numberOfChips = null;
this.order.damage.glassToReplace = null;
},
resetISSConfigState() {
this.issConfig.clientName = 'Generic Insurance';
this.issConfig.clientDisplayName = 'Generic Insurance';
this.issConfig.accountNumber = 0;
this.issConfig.styleSheet = '';
this.issConfig.isCoverageEnabled = false;
this.issConfig.isAuthenticated = false;
this.issConfig.enableTPAFlow = false;
this.issConfig.isClaimRegistrationRequired = false;
this.issConfig.successReturnURL = null;
this.issConfig.failureReturnURL = null;
this.issConfig.disabledFields.policyNumber = false;
this.issConfig.disabledFields.policyZipCode = false;
},
updateVehicleYear(year) {
if (this.order.vehicle.year !== year) {
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
}
},
updateVehicleMake(make) {
if (this.order.vehicle.make !== make) {
const { year } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
}
},
updateVehicleModel(model) {
if (this.order.vehicle.model !== model) {
const { year } = this.order.vehicle;
const { make } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
this.order.vehicle.model = model;
}
},
updateVehicleStyle(style) {
if (this.order.vehicle.style !== style) {
const { year } = this.order.vehicle;
const { make } = this.order.vehicle;
const { model } = this.order.vehicle;
this.resetVehicleState();
this.resetDamageAndDependencies();
this.order.vehicle.year = year;
this.order.vehicle.make = make;
this.order.vehicle.model = model;
this.order.vehicle.style = style;
}
},
updateIsRepair(isRepair) {
this.order.damage.isRepair = isRepair;
},
updateNumberOfChips(numberOfChips) {
this.order.damage.numberOfChips = numberOfChips;
},
updateGlassToReplace(glassToReplace) {
this.order.damage.glassToReplace = glassToReplace;
},
updateGlassParts(partsData) {
this.order.lineItems.glassParts = partsData;
},
updateMoldingQuestionAnswers(answersArray) {
this.order.damage.moldingQuestionAnswers = answersArray;
},
updateCapabilityQuestionAnswers(answersArray) {
this.order.damage.capabilityQuestionAnswers = answersArray;
},
updatePartQuestionAnswers(answersArray) {
this.order.damage.partQuestionAnswers = answersArray;
},
updatePageData(pageData) {
this.applicationUser.pageData[pageData.page] = pageData.data;
},
updatePolicyData(welcomePageModel) {
this.order.policy.policyNumber = welcomePageModel?.policyNumber;
this.order.policy.policyZipCode = welcomePageModel?.policyZipCode;
this.order.policy.dateOfLoss = welcomePageModel?.dateOfLoss;
this.order.policy.damageCause = welcomePageModel?.damageCause;
this.order.policy.damageState = welcomePageModel?.damageState;
this.order.policy.damageCity = welcomePageModel?.damageCity;
this.order.policy.isDamageGlassOnly = welcomePageModel?.isDamageGlassOnly;
this.order.customer.phoneNumber = welcomePageModel?.phoneNumber;
this.order.customer.emailAddress = welcomePageModel?.email;
},
updatePolicyHolderDetails(customerQuestions) {
this.order.customer.address.streetAddress = customerQuestions.addressQuestions.streetAddress;
this.order.customer.address.streetAddress2 = customerQuestions.addressQuestions.streetAddress2;
this.order.customer.address.city = customerQuestions.addressQuestions.city;
this.order.customer.address.state = customerQuestions.addressQuestions.state;
this.order.customer.address.zipCode = customerQuestions.addressQuestions.zipCode;
this.order.customer.firstName = customerQuestions.firstName;
this.order.customer.lastName = customerQuestions.lastName;
},
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);
if (havePartQuestionAnswersChanged) {
this.updateGlassParts(null);
this.updateMoldingQuestionAnswers(null);
this.updateCapabilityQuestionAnswers(null);
this.resetSupportingItemsState();
this.resetVapsState();
this.updatePageData({ page: issPageValues.VEHICLE_PARTS, data: null });
this.updatePageData({ page: issPageValues.MOLDING_QUESTIONS, data: null });
this.updatePageData({ page: issPageValues.CAPABILITY_QUESTIONS, data: null });
}
// Save new values
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);
if (haveMoldingQuestionAnswersChanged) {
this.updateGlassParts(null);
this.updateSupportingItems(null);
this.updateCapabilityQuestionAnswers(null);
this.updatePageData({ page: issPageValues.CAPABILITY_QUESTIONS, data: null });
}
// Save new values
this.updateMoldingQuestionAnswers(moldingQuestionAnswersArray);
},
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);
if (haveCapabilityQuestionAnswersChanged) {
this.updateGlassParts(null);
this.updateSupportingItems(null);
}
// Save new values
this.updateCapabilityQuestionAnswers(capabilityQuestionAnswersArray);
},
saveGlassParts(glassParts) {
this.order.lineItems.glassParts = glassParts;
},
saveSupportingItems(supportingItems) {
this.order.lineItems.supportingItems = supportingItems;
},
saveVaps(vaps) {
this.order.lineItems.vaps = vaps;
},
saveProviderPreferenceData(data) {
this.updatePageData({ page: issPageValues.PROVIDER_PREFERENCE, data });
},
addEventToBus(event) {
this.applicationUser.eventBus.push(event);
},
removeEventFromBus(eventData) {
const matchedEvent = this.applicationUser.eventBus.find(({ category, subCategory }) => category === eventData.category && subCategory === eventData.subCategory);
const itemIndex = this.applicationUser.eventBus.indexOf(matchedEvent);
// If the item exists, remove it.
if (itemIndex > -1) {
this.applicationUser.eventBus.splice(itemIndex, 1);
}
},
// populate initial state
populateInitialState() {
if (!localStorage.getItem(storeId)) {
this.$state = state;
}
},
// Analytics Actions
logExperimentExposure({ userId, sessionKey, pageName, experiment }) {
return globalMethods.callHttpClient({
method: endpoints.LogExperimentExposureIfAssigned.method,
endpoint: endpoints.LogExperimentExposureIfAssigned.url,
payload: {
experimentForLogging: {
userId,
experimentUniverseId: experiment.universeId,
experimentUniverseName: experiment.universeName,
experimentTestId: experiment.testId,
experimentTestName: experiment.testName,
experimentVariationId: experiment.variationId,
experimentVariationName: experiment.variationName,
enabled: experiment.isActive,
isExposed: experiment.isExposed,
userPartitionNumber: experiment.userPartitionNumber,
assignmentId: experiment.assignmentId,
sessionKey,
pageName
}
}
});
},
logPageView({ userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId, experimentsForUser }) {
const payload = {
userId,
sessionKey,
sessionId,
pageName,
applicationName: applicationConfig.APPLICATION_NAME,
action,
event,
shouldUseSessionId,
experimentsForUser
};
return globalMethods.callHttpClient({
method: endpoints.LogPageView.method,
endpoint: endpoints.LogPageView.url,
payload,
logApiCall: false
}).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'; }
const payload = {
userId,
sessionKey,
sessionId,
pageName,
applicationName: applicationConfig.APPLICATION_NAME,
category,
action,
label,
value,
shouldUseSessionId,
experimentsForUser
};
return globalMethods.callHttpClient({
method: endpoints.LogCustomEvent.method,
endpoint: endpoints.LogCustomEvent.url,
payload,
logApiCall: false
}).then((response) => response,
(error) => {
console.log(`Analytics Service Error: ${error.data}`);
});
},
initializeSession({ userId, sessionId, userAgent, referrer }) {
const payload = {
applicationName: applicationConfig.APPLICATION_NAME,
userId,
deviceId: userId,
sessionId,
userAgent,
operatorId: 'WEB',
userName: 'SafeliteISS',
referrer
};
return globalMethods.callHttpClient({
method: endpoints.InitializeSession.method,
endpoint: endpoints.InitializeSession.url,
payload,
logApiCall: false
}).then((response) => response,
(error) => {
console.log(`Analytics Service Error: ${error.data}`);
});
},
updateLastPageVisited(lastPageVisited) {
this.applicationUser.lastPageVisited = lastPageVisited;
},
updateExperiments(experiments) {
this.applicationUser.experiments = experiments;
},
updateTriggeredSiteEntry(wasSiteEntryTriggered) {
this.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered;
},
updateContactInfo(contactInfo) {
this.order.contactInfo.firstName = contactInfo?.firstName ?? '';
this.order.contactInfo.lastName = contactInfo?.lastName ?? '';
this.order.contactInfo.emailAddress = contactInfo?.emailAddress ?? '';
this.order.contactInfo.phoneNumber = contactInfo?.phoneNumber ?? '';
this.order.contactInfo.requestTextUpdates = contactInfo?.requestTextUpdates ?? false;
this.order.contactInfo.notesForTechnician = contactInfo?.notesForTechnician ?? '';
},
GetExperimentsByUser(userId) {
return globalMethods.callHttpClient({
method: endpoints.GetExperimentsByUser.method,
endpoint: `${endpoints.GetExperimentsByUser.url}/${userId}`,
payload: {}
});
},
async runExperimentsForTrigger({ userId, triggerEvent, triggerValue }) {
if (triggerEvent === experimentTriggers.SITE_ENTRY) {
this.updateTriggeredSiteEntry(true);
}
const payload = {
applicationName: applicationConfig.APPLICATION_NAME,
userId,
triggerEvent,
triggerValue,
experimentOrder: this.experimentOrder
};
const response = await globalMethods.callHttpClient({
method: endpoints.RunExperimentsForTrigger.method,
endpoint: endpoints.RunExperimentsForTrigger.url,
payload
});
this.updateExperiments(response.data.experiments);
},
async validateZip({ zip }) {
return await globalMethods.callHttpClient({
methods: endpoints.ValidateZip.method,
endpoint: `${endpoints.ValidateZip.url}/${zip}`
});
},
async validateClientTag(clientTag) {
return await globalMethods.callHttpClient({
methods: endpoints.ValidateClientTag.method,
endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`
});
},
saveServiceLocation(serviceLocationInfo) {
this.updateServiceLocation(serviceLocationInfo);
},
saveRegistrationAddressLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
// Reset dependent state when changing
if
(
registrationInfo?.address !== this.order.vehicle.registration?.address
|| registrationInfo?.city !== this.order.vehicle.registration?.city
|| registrationInfo?.state !== this.order.vehicle.registration?.state
|| registrationInfo?.zipCode !== this.order.vehicle.registration?.zipCode
|| registrationInfo?.firstName !== this.order.vehicle.registration?.firstName
|| registrationInfo?.lastName !== this.order.vehicle.registration?.lastName
) {
if (!isSelectedGlassAvailableForVehicle) {
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateRegistration(registrationInfo);
}
if (vehicleInfo) {
this.updateVehicle(vehicleInfo);
}
},
saveVin({ isSelectedGlassAvailableForVehicle, vehicleInfo }) {
// Reset dependent state when changing
if (vehicleInfo.vin !== this.order.vehicle.vin) {
this.resetRegistrationAndDependencies();
if (!isSelectedGlassAvailableForVehicle) {
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateVehicle(vehicleInfo);
}
},
saveRegistrationLicensePlateLookup({ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
// Reset dependent state when changing
if (registrationInfo?.licensePlate !== this.order.vehicle.registration?.licensePlate
|| registrationInfo?.state !== this.order.vehicle.registration?.state) {
this.resetRegistrationAndDependencies();
if (!isSelectedGlassAvailableForVehicle) {
// Dependencies already cleared in above statement
this.resetDamageState();
this.resetGlassPartsState();
}
// Save new values
this.updateVehicle(vehicleInfo);
}
this.updateRegistration(registrationInfo);
},
resetRegistrationAndDependencies() {
this.resetRegistrationState();
this.resetGlassPartsState();
this.resetSupportingItemsState();
this.resetVapsState();
},
resetDamageAndDependencies() {
this.resetDamageState();
this.resetGlassPartsState();
this.resetSupportingItemsState();
this.resetVapsState();
},
resetPartsAndDependencies() {
this.resetGlassPartsState();
this.resetSupportingItemsState();
this.resetVapsState();
},
resetPageFields() {
this.order.policy.policyNumber = null;
this.order.policy.dateOfLoss = null;
this.order.policy.damageCause = null;
this.order.policy.damageCity = null;
this.order.policy.damageState = null;
this.order.customer.phoneNumber = null;
this.order.customer.emailAddress = null;
this.order.customer.firstName = null;
this.order.customer.lastName = null;
this.order.customer.address.city = null;
this.order.customer.address.state = null;
this.order.customer.address.zipCode = null;
this.order.customer.address.streetAddress = null;
this.order.customer.address.streetAddress2 = null;
this.resetVehicleState();
this.resetDamageState();
}
},
persist: true
});
// 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;
if (hasRequiresRecalibration) {
if (hasRecalibrationType) {
// Has both 'requiresRecalibration' and 'recalibrationType' and 'recalibrationType'
return (
getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts,
'recalibrationType')[0].toLowerCase() !== 'unknown'
);
}
// Has 'requiresRecalibration' but no 'recalibrationType' at all
return true;
}
// Does not have 'requiresRecalibration'
return false;
}
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
}
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
if (!arrayOfObjects) return null;
return arrayOfObjects.sort((a, b) => {
if (a[propertyName] < b[propertyName]) return -1;
if (a[propertyName] > b[propertyName]) return 1;
return 0;
});
}
function convertGlassPieceNamingForApi(glassArray) {
if (!glassArray || glassArray.length === 0) return [];
// check if array already converted. (likely when a session has been saved previously and then reloaded)
if (glassArray[0].location !== undefined) {
return glassArray;
}
const converted = [];
glassArray.forEach((glass) => {
converted.push({
location: glass.glassLocation,
name: glass.glassName
});
});
return converted;
}
function convertResultsForApi(resultsArray) {
if (!resultsArray) return [];
const converted = [];
resultsArray.forEach((answer) => {
converted.push({
location: answer.glassLocation,
name: answer.glassName,
result: answer.result
});
});
return converted;
}
function convertGlassPieceNamingFromApi(glassArray) {
glassArray.forEach((glass) => {
glass.glassLocation = glass.glassPiece.location;
glass.glassName = glass.glassPiece.name;
delete glass.glassPiece;
return glass;
});
return glassArray;
}
function addPricesToLineItems(lineItems, pricingLineItems) {
lineItems.forEach((lineItem) => {
if (lineItem.childParts) {
addPricesToLineItems(lineItem.childParts, pricingLineItems);
}
const lineItemIndex = pricingLineItems.findIndex((pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber);
if (lineItemIndex > -1) {
const pricedLineItem = pricingLineItems[lineItemIndex];
lineItem.laborAmount = pricedLineItem.laborAmount;
lineItem.sellingPrice = pricedLineItem.sellingPrice;
lineItem.kitPrice = pricedLineItem.kitPrice;
}
});
return lineItems;
}
function getLineItemQueryStringForPricing(lineItems) {
return lineItems.map((lineItem, index) => {
let queryStringSnippet = `&LineItems[${index}].partNumber=${lineItem.partNumber}`;
if (lineItem.childParts) {
queryStringSnippet += getLineItemQueryStringForPricing(lineItem.childParts);
}
return queryStringSnippet;
}).join('');
}
function buildQueryStringParameterFromArrayOfComplexObjects(arrayOfObjects, parameterName) {
let queryStringParameter = '';
for (let i = 0; i < arrayOfObjects.length; i++) {
for (const [key, value] of Object.entries(arrayOfObjects[i])) {
queryStringParameter += `${parameterName}[${i}].${key}=${value}&`;
}
}
// Remove trailing &
return queryStringParameter.slice(0, -1);
}