Merge pull request #1963 from Safelite/feature/CSR-2193

Feature/csr 2193
This commit is contained in:
CarlNation 2024-09-09 06:13:15 -04:00 committed by GitHub
commit f50d62e366
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 323 additions and 159 deletions

View file

@ -36,6 +36,7 @@ const queryStrings = {
VIN_SELECTION: "vinselection", VIN_SELECTION: "vinselection",
SERVICE_PACKAGE: "servicepackage", SERVICE_PACKAGE: "servicepackage",
NUMBER_OF_CHIPS: "numberofchips", NUMBER_OF_CHIPS: "numberofchips",
LOG: "log",
UTM_SOURCE: "_source", UTM_SOURCE: "_source",
UTM_MEDIUM: "_medium", UTM_MEDIUM: "_medium",
UTM_CAMPAIGN: "_campaign", UTM_CAMPAIGN: "_campaign",

View file

@ -8,6 +8,10 @@ export function getDateDifferenceInDays(startDate, endDate) {
return Math.round(difference / (1000 * 3600 * 24)); return Math.round(difference / (1000 * 3600 * 24));
} }
export function get12HourTimeFormat(time) { export function get12HourTimeFormat(time) {
if (!time) {
return null;
}
// Check correct time format and split into components // Check correct time format and split into components
time = time.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)?$/) || [time]; time = time.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)?$/) || [time];
@ -20,8 +24,12 @@ export function get12HourTimeFormat(time) {
return time.join(""); // return adjusted time or original string return time.join(""); // return adjusted time or original string
} }
export function get12HourTimeMobileFormat(time) { export function get12HourTimeMobileFormat(time) {
if (!time) {
return null;
}
// Check correct time format and split into components // Check correct time format and split into components
time = time.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)?$/) || [time]; time = time?.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)?$/) || [time];
if (time.length > 1) { if (time.length > 1) {
// If time format correct // If time format correct

View file

@ -107,8 +107,12 @@ export async function getImplicitNavigation(toRoute) {
*/ */
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) { export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog }) {
console.log(new Date() + " navigateToHeritageFunnel: " + JSON.stringify(applicationConfig)); const log = getQuerystringParameter(queryStrings.LOG);
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL); if (eval(log)) {
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
}
// Create the order (or save existing order) when navigating to Heritage Funnel. // Create the order (or save existing order) when navigating to Heritage Funnel.
if (shouldSaveSession) { if (shouldSaveSession) {
await saveSession({ pageNameToLog: pageNameToLog, shouldAwaitSaveSessionQueue: true }); await saveSession({ pageNameToLog: pageNameToLog, shouldAwaitSaveSessionQueue: true });

View file

@ -34,6 +34,8 @@ import {
import store from "@/store"; import store from "@/store";
import { serviceType } from "@/constants/service-type"; import { serviceType } from "@/constants/service-type";
import { applicationConfig } from "@/constants/application-config.js"; import { applicationConfig } from "@/constants/application-config.js";
import baseMixin from "@/mixins/base-mixin.js";
export default { export default {
name: "add-to-calendar", name: "add-to-calendar",
components: { components: {
@ -110,10 +112,10 @@ export default {
return this.getCmsContent(this.sameDayDropOffWidgetName, "BodyText"); return this.getCmsContent(this.sameDayDropOffWidgetName, "BodyText");
}, },
UniqueId() { UniqueId() {
return store.getters.submittedOrder.referralNumber?.toString(); return this.getSubmittedOrder()?.referralNumber?.toString();
}, },
ServiceType() { ServiceType() {
const isRepair = store.getters.submittedOrder.damage.isRepair; const isRepair = this.getSubmittedOrder()?.damage.isRepair;
const funnelHasRecalibrationPart = store.getters.isRecalibrationOnSubmittedOrder; const funnelHasRecalibrationPart = store.getters.isRecalibrationOnSubmittedOrder;
if (!isRepair) { if (!isRepair) {
if (funnelHasRecalibrationPart) { if (funnelHasRecalibrationPart) {
@ -125,7 +127,7 @@ export default {
return serviceType.REPAIR; return serviceType.REPAIR;
}, },
RouteCode() { RouteCode() {
return store.getters.submittedOrder.schedule.routeCode; return this.getSubmittedOrder()?.schedule.routeCode;
}, },
Appointment() { Appointment() {
var subject = ""; var subject = "";
@ -206,6 +208,9 @@ export default {
}, },
methods: { methods: {
getSubmittedOrder() {
return baseMixin.methods.getSubmittedOrder();
},
setCalendarAppointment(calendarOption) { setCalendarAppointment(calendarOption) {
if ( if (
calendarOption.name == calendarOptions.ICAL || calendarOption.name == calendarOptions.ICAL ||

View file

@ -19,67 +19,6 @@ beforeEach(() => {
jest.restoreAllMocks(); jest.restoreAllMocks();
jest.clearAllMocks(); jest.clearAllMocks();
store.getters = { store.getters = {
submittedOrder: {
schedule: {
date: "2023-01-01",
startTime: "09:00",
endTime: "10:00",
routeCode: "000",
jobMaxMinutes: "120",
jobMinMinutes: "60",
},
lineItems: {
glassParts: [
{
partNumber: "ABC123",
},
],
supportingItems: [],
},
serviceLocation: {
address: "test",
address2: "123",
city: "test",
state: "AZ",
appointmentType: "Inshop",
zipCode: "12345",
zipCodeCtu: "01234",
provider: {
providerNumber: "123",
address: {
streetAddress: "test1",
city: "test",
state: "AZ",
zipCode: "12345",
zipCodeCtu: "01234",
},
},
},
damage: {
isRepair: false,
},
payment: {
isPia: true,
isInsurance: false,
insuranceCoverage: {
coverageStatus: "test",
},
},
policy: {
isNoComp: false,
currentDeductible: 1,
insuranceCompanyName: "test name",
},
referralNumber: "1234567",
vehicle: {
year: "2004",
make: "Ford",
model: "F Series F250",
},
customer: {
emailAddress: "test@test.com",
},
},
order: { order: {
schedule: { schedule: {
date: "2023-01-01", date: "2023-01-01",
@ -96,6 +35,7 @@ beforeEach(() => {
supportingItems: [], supportingItems: [],
}, },
serviceLocation: { serviceLocation: {
appointmentType: AppointmentTypeStrings.IN_SHOP,
address: "test", address: "test",
address2: "123", address2: "123",
city: "test", city: "test",
@ -180,6 +120,20 @@ describe("computed properties...", () => {
test("ScheduleDateFormatted should return date in expected format.", () => { test("ScheduleDateFormatted should return date in expected format.", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
startTime: "09:00",
endTime: "11:00",
date: "2023-01-01",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ScheduleDateFormatted; const testValue = wrapper.vm.ScheduleDateFormatted;
@ -189,11 +143,22 @@ describe("computed properties...", () => {
}); });
test("ScheduleTimeFormatted should return mobile time in expected format.", () => { test("ScheduleTimeFormatted should return mobile time in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.MOBILE;
store.getters.submittedOrder.schedule.startTime = "09:00";
store.getters.submittedOrder.schedule.endTime = "11:00";
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
startTime: "09:00",
endTime: "11:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
wrapper.vm.submittedOrder.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;
// Act // Act
const testValue = wrapper.vm.ScheduleTimeFormatted; const testValue = wrapper.vm.ScheduleTimeFormatted;
@ -203,11 +168,22 @@ describe("computed properties...", () => {
}); });
test("ScheduleTimeFormatted should return DROP_OFF time in expected format.", () => { test("ScheduleTimeFormatted should return DROP_OFF time in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.DROP_OFF;
store.getters.submittedOrder.schedule.startTime = "09:00";
store.getters.submittedOrder.schedule.endTime = "11:00";
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
startTime: "09:00",
endTime: "11:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
wrapper.vm.submittedOrder.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF;
// Act // Act
const testValue = wrapper.vm.ScheduleTimeFormatted; const testValue = wrapper.vm.ScheduleTimeFormatted;
@ -217,11 +193,22 @@ describe("computed properties...", () => {
}); });
test("ScheduleTimeFormatted should return Inshop time in expected format.", () => { test("ScheduleTimeFormatted should return Inshop time in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.IN_SHOP;
store.getters.submittedOrder.schedule.startTime = "09:00";
store.getters.submittedOrder.schedule.endTime = "11:00";
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
startTime: "09:00",
endTime: "11:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
wrapper.vm.submittedOrder.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP;
// Act // Act
const testValue = wrapper.vm.ScheduleTimeFormatted; const testValue = wrapper.vm.ScheduleTimeFormatted;
@ -231,10 +218,21 @@ describe("computed properties...", () => {
}); });
test("AppointmentWordingText should return mobile text in expected format.", () => { test("AppointmentWordingText should return mobile text in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.MOBILE;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
endTime: "10:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
wrapper.vm.submittedOrder.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;
// Act // Act
const testValue = wrapper.vm.AppointmentWordingText; const testValue = wrapper.vm.AppointmentWordingText;
@ -243,10 +241,21 @@ describe("computed properties...", () => {
}); });
test("AppointmentWordingText should return DROP_OFF text in expected format.", () => { test("AppointmentWordingText should return DROP_OFF text in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.DROP_OFF;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
endTime: "10:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
wrapper.vm.submittedOrder.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF;
// Act // Act
const testValue = wrapper.vm.AppointmentWordingText; const testValue = wrapper.vm.AppointmentWordingText;
@ -256,10 +265,20 @@ describe("computed properties...", () => {
}); });
test("AppointmentWordingText should return IN_SHOP text in expected format.", () => { test("AppointmentWordingText should return IN_SHOP text in expected format.", () => {
//Arrange //Arrange
store.getters.submittedOrder.serviceLocation.appointmentType =
AppointmentTypeStrings.IN_SHOP;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
endTime: "10:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.AppointmentWordingText; const testValue = wrapper.vm.AppointmentWordingText;
@ -280,6 +299,19 @@ describe("computed properties...", () => {
test("ScheduleDate should return date in expected format.", () => { test("ScheduleDate should return date in expected format.", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2023-01-01",
endTime: "10:00",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ScheduleDate; const testValue = wrapper.vm.ScheduleDate;
@ -290,6 +322,19 @@ describe("computed properties...", () => {
test("ScheduleStartTime should return time in expected format.", () => { test("ScheduleStartTime should return time in expected format.", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
startTime: "09:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ScheduleStartTime; const testValue = wrapper.vm.ScheduleStartTime;
@ -300,6 +345,19 @@ describe("computed properties...", () => {
test("ScheduleEndTime should return time in expected format.", () => { test("ScheduleEndTime should return time in expected format.", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
endTime: "10:00",
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ScheduleEndTime; const testValue = wrapper.vm.ScheduleEndTime;
@ -344,6 +402,18 @@ describe("computed properties...", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ServiceLocationFullAddress; const testValue = wrapper.vm.ServiceLocationFullAddress;
@ -355,6 +425,18 @@ describe("computed properties...", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
},
serviceLocation: store.getters.order.serviceLocation
};
// Act // Act
const testValue = wrapper.vm.ProviderFullAddress; const testValue = wrapper.vm.ProviderFullAddress;
@ -366,6 +448,17 @@ describe("computed properties...", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
}
};
// Act // Act
const testValue = wrapper.vm.AppointmentDuration; const testValue = wrapper.vm.AppointmentDuration;
@ -375,9 +468,18 @@ describe("computed properties...", () => {
}); });
test("Appointment Duration should return with correct duration values in expected format for hours.", () => { test("Appointment Duration should return with correct duration values in expected format for hours.", () => {
//Arrange //Arrange
store.getters.submittedOrder.schedule.jobMaxMinutes = 120;
store.getters.submittedOrder.schedule.jobMinMinutes = 60;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 120,
jobMinMinutes: 60,
routeCode: ""
}
};
// Act // Act
const testValue = wrapper.vm.AppointmentDuration; const testValue = wrapper.vm.AppointmentDuration;
@ -387,9 +489,18 @@ describe("computed properties...", () => {
}); });
test("Appointment Duration should return with correct duration values in expected format for minutes.", () => { test("Appointment Duration should return with correct duration values in expected format for minutes.", () => {
//Arrange //Arrange
store.getters.submittedOrder.schedule.jobMaxMinutes = 45;
store.getters.submittedOrder.schedule.jobMinMinutes = 30;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 45,
jobMinMinutes: 30,
routeCode: ""
}
};
// Act // Act
const testValue = wrapper.vm.AppointmentDuration; const testValue = wrapper.vm.AppointmentDuration;
@ -400,10 +511,18 @@ describe("computed properties...", () => {
test("Appointment Duration should return with All Day.", () => { test("Appointment Duration should return with All Day.", () => {
//Arrange //Arrange
store.getters.submittedOrder.schedule.jobMaxMinutes = 45;
store.getters.submittedOrder.schedule.jobMinMinutes = 30;
store.getters.submittedOrder.schedule.routeCode = RouteCodeFlags.ALL_DAY_DROP_OFF;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 45,
jobMinMinutes: 30,
routeCode: RouteCodeFlags.ALL_DAY_DROP_OFF
}
};
// Act // Act
const testValue = wrapper.vm.AppointmentDuration; const testValue = wrapper.vm.AppointmentDuration;
@ -414,10 +533,18 @@ describe("computed properties...", () => {
test("Appointment Duration should return with Overnight.", () => { test("Appointment Duration should return with Overnight.", () => {
//Arrange //Arrange
store.getters.submittedOrder.schedule.jobMaxMinutes = 45;
store.getters.submittedOrder.schedule.jobMinMinutes = 30;
store.getters.submittedOrder.schedule.routeCode = RouteCodeFlags.OVERNIGHT_DROP_OFF;
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.submittedOrder = {
vehicle: {
imageUrl: ""
},
schedule: {
date: "2024-09-28",
jobMaxMinutes: 45,
jobMinMinutes: 30,
routeCode: RouteCodeFlags.OVERNIGHT_DROP_OFF
}
};
// Act // Act
const testValue = wrapper.vm.AppointmentDuration; const testValue = wrapper.vm.AppointmentDuration;
@ -443,4 +570,4 @@ function setupMocks({ customMountOptions }) {
]; ];
const wrapper = shallowMount(confirmation, mountOptions); const wrapper = shallowMount(confirmation, mountOptions);
return { wrapper }; return { wrapper };
} }

View file

@ -109,16 +109,19 @@ import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helpe
export default { export default {
name: "confirmation", name: "confirmation",
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
console.log("beforeRoute..");
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER); await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER);
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging( const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_WIPERS, storeActions.GET_WIPERS,
{ {
serviceZipCode: store.getters.submittedOrder.serviceLocation.zipCode, serviceZipCode: submittedOrder.serviceLocation.zipCode,
carId: store.getters.submittedOrder.vehicle.carId, carId: submittedOrder.vehicle.carId,
}, },
"confirmation" "confirmation"
); );
@ -147,24 +150,26 @@ export default {
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const availableVaps = [resultMap.rainDefense, ...resultMap.wipers]; const availableVaps = [resultMap.rainDefense, ...resultMap.wipers];
const lineItemsFromSubmittedOrder = deepClone(store.getters.submittedOrder.lineItems); const lineItemsFromSubmittedOrder = deepClone(submittedOrder.lineItems);
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.lineItems = lineItemsFromSubmittedOrder; vm.lineItems = lineItemsFromSubmittedOrder;
vm.vaps = availableVaps; vm.vaps = availableVaps;
vm.submittedOrder = submittedOrder;
}); });
}, },
data() { data() {
return { return {
lineItems: [], lineItems: [],
vaps: [], vaps: [],
submittedOrder: null,
}; };
}, },
computed: { computed: {
ShowCart() { ShowCart() {
if (this.isPia && store.getters.submittedOrder.settledTenderAmount == 0) { if (this.isPia && this.submittedOrder?.settledTenderAmount == 0) {
// settleTenderAmount always shows 0 via localhost or dev. // settleTenderAmount always shows 0 via localhost or dev.
// Temporarily set return true to see cart in localhost or dev environment // Temporarily set return true to see cart in localhost or dev environment
return false; return false;
@ -179,7 +184,7 @@ export default {
return this.getCmsContent("ScheduleConfirmationWidget", "Image"); return this.getCmsContent("ScheduleConfirmationWidget", "Image");
}, },
CustomerPortalLoginToken() { CustomerPortalLoginToken() {
return store.getters.submittedOrder.customerPortalLoginToken; return this.submittedOrder?.customerPortalLoginToken;
}, },
ConfirmationEmailText() { ConfirmationEmailText() {
return this.getCmsContent("ConfirmationEmailWidget", "BodyText") return this.getCmsContent("ConfirmationEmailWidget", "BodyText")
@ -189,16 +194,16 @@ export default {
?.replaceAll(">", ">"); ?.replaceAll(">", ">");
}, },
ScheduleDate() { ScheduleDate() {
return store.getters.submittedOrder.schedule.date; return this.submittedOrder?.schedule?.date;
}, },
AppointmentType() { AppointmentType() {
return store.getters.submittedOrder.serviceLocation.appointmentType; return this.submittedOrder?.serviceLocation?.appointmentType;
}, },
ScheduleStartTime() { ScheduleStartTime() {
return store.getters.submittedOrder.schedule.startTime; return this.submittedOrder?.schedule?.startTime;
}, },
ScheduleEndTime() { ScheduleEndTime() {
return store.getters.submittedOrder.schedule.endTime; return this.submittedOrder?.schedule?.endTime;
}, },
InShopWordingText() { InShopWordingText() {
return this.getCmsContent("InShopWordingWidget", "BodyText"); return this.getCmsContent("InShopWordingWidget", "BodyText");
@ -210,31 +215,31 @@ export default {
return this.getCmsContent("DropOffWordingWidget", "BodyText"); return this.getCmsContent("DropOffWordingWidget", "BodyText");
}, },
ServiceLocationAddress() { ServiceLocationAddress() {
return store.getters.submittedOrder.serviceLocation.address; return this.submittedOrder?.serviceLocation?.address;
}, },
ServiceLocationAddress2() { ServiceLocationAddress2() {
return store.getters.submittedOrder.serviceLocation.address2; return this.submittedOrder?.serviceLocation?.address2;
}, },
ServiceLocationCity() { ServiceLocationCity() {
return store.getters.submittedOrder.serviceLocation.city; return this.submittedOrder?.serviceLocation?.city;
}, },
ServiceLocationState() { ServiceLocationState() {
return store.getters.submittedOrder.serviceLocation.state; return this.submittedOrder?.serviceLocation?.state;
}, },
ServiceLocationZipCode() { ServiceLocationZipCode() {
return store.getters.submittedOrder.serviceLocation.zipCode; return this.submittedOrder?.serviceLocation?.zipCode;
}, },
ProviderAddress() { ProviderAddress() {
return store.getters.submittedOrder.serviceLocation.provider.address.streetAddress; return this.submittedOrder?.serviceLocation?.provider?.address?.streetAddress;
}, },
ProviderCity() { ProviderCity() {
return store.getters.submittedOrder.serviceLocation.provider.address.city; return this.submittedOrder?.serviceLocation?.provider?.address?.city;
}, },
ProviderState() { ProviderState() {
return store.getters.submittedOrder.serviceLocation.provider.address.state; return this.submittedOrder?.serviceLocation?.provider?.address?.state;
}, },
ProviderZipCode() { ProviderZipCode() {
return store.getters.submittedOrder.serviceLocation.provider.address.zipCode; return this.submittedOrder?.serviceLocation?.provider?.address?.zipCode;
}, },
AppointmentWordingText() { AppointmentWordingText() {
if (this.AppointmentType == AppointmentTypeStrings.MOBILE) { if (this.AppointmentType == AppointmentTypeStrings.MOBILE) {
@ -268,7 +273,7 @@ export default {
// This conversion ensures we don't get get GMT induced date changes // This conversion ensures we don't get get GMT induced date changes
const dateObject = convertDateStringToDate(this.ScheduleDate); const dateObject = convertDateStringToDate(this.ScheduleDate);
// Ex: Tuesday, April 22 // Ex: Tuesday, April 22
return dateObject.toLocaleDateString("en-us", { return dateObject?.toLocaleDateString("en-us", {
weekday: "long", weekday: "long",
month: "long", month: "long",
day: "numeric", day: "numeric",
@ -286,19 +291,19 @@ export default {
} }
}, },
vehicleBannerImageUrl() { vehicleBannerImageUrl() {
return store.getters.submittedOrder?.vehicle.imageUrl; return this.submittedOrder?.vehicle.imageUrl;
}, },
damageInfo() { damageInfo() {
return store.getters.submittedOrder.damage; return this.submittedOrder?.damage;
}, },
isInsurance() { isInsurance() {
return store.getters.submittedOrder.payment.isInsurance; return this.submittedOrder?.payment?.isInsurance;
}, },
isNoComp() { isNoComp() {
return store.getters.submittedOrder.policy.isNoComp; return this.submittedOrder?.policy?.isNoComp;
}, },
isItac() { isItac() {
return store.getters.submittedOrder.policy.isItac; return this.submittedOrder?.policy?.isItac;
}, },
hasVapsInCart() { hasVapsInCart() {
if (this.lineItems?.vaps?.length > 0) { if (this.lineItems?.vaps?.length > 0) {
@ -311,32 +316,28 @@ export default {
if (this.isNoComp || this.isItac) { if (this.isNoComp || this.isItac) {
return coverageStatus.NOCOMP; return coverageStatus.NOCOMP;
} else { } else {
return store.getters.submittedOrder.payment.insuranceCoverage.coverageStatus; return this.submittedOrder?.payment?.insuranceCoverage?.coverageStatus;
} }
}, },
currentDeductible() { currentDeductible() {
return store.getters.submittedOrder.policy.currentDeductible; return this.submittedOrder?.policy?.currentDeductible;
}, },
insuranceCompanyName() { insuranceCompanyName() {
return store.getters.submittedOrder.policy.insuranceCompanyName; return this.submittedOrder?.policy?.insuranceCompanyName;
}, },
isPia() { isPia() {
return store.getters.submittedOrder?.payment.isPia; return this.submittedOrder?.payment?.isPia;
}, },
AppointmentDuration() { AppointmentDuration() {
const durationMaximum = store.getters.submittedOrder?.schedule?.jobMaxMinutes; const durationMaximum = this.submittedOrder?.schedule?.jobMaxMinutes;
const durationMinimum = store.getters.submittedOrder?.schedule?.jobMinMinutes; const durationMinimum = this.submittedOrder?.schedule?.jobMinMinutes;
const durationLengthString = "Duration: "; const durationLengthString = "Duration: ";
if ( if (
store.getters.submittedOrder?.schedule?.routeCode.includes( this.submittedOrder?.schedule?.routeCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)
RouteCodeFlags.ALL_DAY_DROP_OFF
)
) { ) {
return durationLengthString.concat("All Day"); return durationLengthString.concat("All Day");
} else if ( } else if (
store.getters.submittedOrder?.schedule?.routeCode.includes( this.submittedOrder?.schedule?.routeCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)
RouteCodeFlags.OVERNIGHT_DROP_OFF
)
) { ) {
return durationLengthString.concat("Overnight"); return durationLengthString.concat("Overnight");
} else { } else {
@ -348,7 +349,7 @@ export default {
}, },
methods: { methods: {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
if (store.getters.hasSubmittedOrder) { if (baseMixin.methods.hasSubmittedOrder()) {
return true; return true;
} }

View file

@ -572,7 +572,10 @@ export default {
); );
}, },
hasSubmittedOrder() { hasSubmittedOrder() {
return this.$store.getters.hasSubmittedOrder; return baseMixin.methods.hasSubmittedOrder();
},
getSubmittedOrder() {
return baseMixin.methods.getSubmittedOrder();
}, },
openModal(modalName) { openModal(modalName) {
this.$refs[modalName].openModal(); this.$refs[modalName].openModal();
@ -597,17 +600,17 @@ export default {
}, },
isInsurance() { isInsurance() {
return this.hasSubmittedOrder() return this.hasSubmittedOrder()
? this.$store.getters.submittedOrder.payment.isInsurance ? this.getSubmittedOrder()?.payment.isInsurance
: this.$store.getters.payment.isInsurance; : this.$store.getters.payment.isInsurance;
}, },
isNoComp() { isNoComp() {
return this.hasSubmittedOrder() return this.hasSubmittedOrder()
? this.$store.getters.submittedOrder.policy.isNoComp ? this.getSubmittedOrder()?.policy.isNoComp
: this.$store.getters.policy.isNoComp; : this.$store.getters.policy.isNoComp;
}, },
isItac() { isItac() {
return this.hasSubmittedOrder() return this.hasSubmittedOrder()
? this.$store.getters.submittedOrder.policy.isItac ? this.getSubmittedOrder()?.policy.isItac
: this.$store.getters.policy.isItac; : this.$store.getters.policy.isItac;
}, },
hasVapsInCart() { hasVapsInCart() {
@ -622,13 +625,13 @@ export default {
return coverageStatus.NOCOMP; return coverageStatus.NOCOMP;
} else { } else {
return this.hasSubmittedOrder() return this.hasSubmittedOrder()
? this.$store.getters.submittedOrder.payment.insuranceCoverage.coverageStatus ? this.getSubmittedOrder()?.payment.insuranceCoverage.coverageStatus
: this.$store.getters.payment.insuranceCoverage.coverageStatus; : this.$store.getters.payment.insuranceCoverage.coverageStatus;
} }
}, },
currentDeductible() { currentDeductible() {
return this.hasSubmittedOrder() return this.hasSubmittedOrder()
? this.$store.getters.submittedOrder.policy.currentDeductible ? this.getSubmittedOrder()?.policy.currentDeductible
: this.$store.getters.policy.currentDeductible; : this.$store.getters.policy.currentDeductible;
}, },
insuranceCompanyName() { insuranceCompanyName() {

View file

@ -37,9 +37,11 @@ export default {
const currentPageName = getPageNameByQueryString(); const currentPageName = getPageNameByQueryString();
await this.validateSession(); await this.validateSession();
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const refSequenceNum = const refSequenceNum =
store.getters.order.referralSequenceNumber || store.getters.order.referralSequenceNumber ||
store.getters.submittedOrder?.referralSequenceNumber; submittedOrder?.referralSequenceNumber;
var payload = { var payload = {
userId: getUserIdValue(), userId: getUserIdValue(),
@ -125,8 +127,9 @@ export default {
const isDefined = (x) => x !== null && x !== undefined; const isDefined = (x) => x !== null && x !== undefined;
// Get correct order object // Get correct order object
const hasSubmittedOrder = store.getters.hasSubmittedOrder; const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
const order = hasSubmittedOrder ? store.getters.submittedOrder : store.getters.order; const submittedOrder = baseMixin.methods.getSubmittedOrder();
const order = hasSubmittedOrder ? submittedOrder : store.getters.order;
// Begin assembling payload for data layer // Begin assembling payload for data layer
const payload = {}; const payload = {};

View file

@ -21,6 +21,7 @@ import {
getSessionKeyValue, getSessionKeyValue,
getUserIdValue, getUserIdValue,
} from "@/helpers/heritage-integration/cookie-helper"; } from "@/helpers/heritage-integration/cookie-helper";
import baseMixin from "./base-mixin";
const parts = { const parts = {
windshield: { windshield: {
@ -470,8 +471,9 @@ describe("analyticsMixin.js", () => {
test("Pushes correct data when submitted order is present", () => { test("Pushes correct data when submitted order is present", () => {
// Arrange // Arrange
window.dataLayer = []; window.dataLayer = [];
store.getters.hasSubmittedOrder = true; baseMixin.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
store.getters.submittedOrder = store.getters.order; baseMixin.methods.getSubmittedOrder = jest.fn().mockReturnValue(store.getters.order);
store.getters.order = { store.getters.order = {
vehicle: { vehicle: {
year: null, year: null,

View file

@ -166,9 +166,7 @@ export default {
); );
} }
const order = store.getters.hasSubmittedOrder const order = this.hasSubmittedOrder() ? this.getSubmittedOrder() : store.getters.order;
? store.getters.submittedOrder
: store.getters.order;
if ( if (
order.payment.insuranceCoverage.isVerified && order.payment.insuranceCoverage.isVerified &&
@ -224,6 +222,12 @@ export default {
return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)]; return [parseInt(v[1], 10), parseInt(v[2], 10), parseInt(v[3] || 0, 10)];
} }
}, },
getSubmittedOrder() {
return JSON.parse(window.sessionStorage.getItem("submittedOrder"));
},
hasSubmittedOrder() {
return window.sessionStorage.getItem("submittedOrder") !== null;
},
}, },
computed: { computed: {
storeActions() { storeActions() {

View file

@ -226,15 +226,16 @@ describe("baseMixin.js", () => {
const payment = { insuranceCoverage: { isVerified: true } }; const payment = { insuranceCoverage: { isVerified: true } };
const policy = { isNoComp: false, isItac: false, currentDeductible: 250 }; const policy = { isNoComp: false, isItac: false, currentDeductible: 250 };
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(true);
mixIn.methods.getSubmittedOrder = jest.fn().mockReturnValue({
payment: payment,
policy: policy,
});
store.getters = { store.getters = {
payment: {}, payment: {},
policy: {}, policy: {},
order: {}, order: {},
submittedOrder: {
payment: payment,
policy: policy,
},
hasSubmittedOrder: true,
}; };
var amtDue = mixIn.methods.getAmountDue(lineItems); var amtDue = mixIn.methods.getAmountDue(lineItems);
@ -301,6 +302,8 @@ describe("baseMixin.js", () => {
const payment = { isInsurance: null, insuranceCoverage: { isVerified: null } }; const payment = { isInsurance: null, insuranceCoverage: { isVerified: null } };
const policy = { isNoComp: false, isItac: false, currentDeductible: 0 }; const policy = { isNoComp: false, isItac: false, currentDeductible: 0 };
mixIn.methods.hasSubmittedOrder = jest.fn().mockReturnValue(false);
store.getters = { store.getters = {
payment: payment, payment: payment,
policy: policy, policy: policy,

View file

@ -64,7 +64,7 @@ const routes = [
} }
// Intercept all navigation if a submitted order exists in storage // Intercept all navigation if a submitted order exists in storage
if (store.getters.hasSubmittedOrder) { if (window.sessionStorage.getItem("submittedOrder") !== null) {
if (to.query.fmgPage !== funnelStartPageName) { if (to.query.fmgPage !== funnelStartPageName) {
to.query.fmgPage = fmgPageValues.CONFIRMATION; to.query.fmgPage = fmgPageValues.CONFIRMATION;
} }
@ -409,6 +409,7 @@ async function navigate(
const zip = getQuerystringParameter(queryStrings.ZIP_CODE); const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
const promo = getQuerystringParameter(queryStrings.PROMO); const promo = getQuerystringParameter(queryStrings.PROMO);
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR); const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
const log = getQuerystringParameter(queryStrings.LOG);
if ( if (
hasZip && hasZip &&
@ -428,6 +429,10 @@ async function navigate(
queryStringsObject[queryStrings.PAGE_ERROR] = pageError; queryStringsObject[queryStrings.PAGE_ERROR] = pageError;
} }
if (log) {
queryStringsObject[queryStrings.LOG] = log;
}
router.push({ router.push({
name: "root", name: "root",
query: Object.assign(optionalQuery, queryStringsObject), query: Object.assign(optionalQuery, queryStringsObject),

View file

@ -883,8 +883,6 @@ export const getters = {
.filter((x) => !!x.isActive) .filter((x) => !!x.isActive)
.map((x) => x.settings) .map((x) => x.settings)
.reduce((r, c) => Object.assign(r, c), {}) ?? {}, .reduce((r, c) => Object.assign(r, c), {}) ?? {},
submittedOrder: (state) => JSON.parse(window.sessionStorage.getItem("submittedOrder")),
hasSubmittedOrder: (state) => window.sessionStorage.getItem("submittedOrder") !== null,
isVerifiedAndDeductibleZeroConfirmed: (state) => { isVerifiedAndDeductibleZeroConfirmed: (state) => {
// used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages // used as a CMS variable on /payment-method, needed for FunnelSubHeaderWidget on cart pages
if ( if (
@ -2798,7 +2796,7 @@ export const actions = {
}, },
createSubmittedOrder(context) { createSubmittedOrder(context) {
if (context.getters.hasSubmittedOrder) { if (window.sessionStorage.getItem("submittedOrder") !== null) {
return; return;
} }