diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 847b14477..2cfd08a8e 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -91,6 +91,9 @@ const storeActions = { SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes", SAVE_CCTOKEN: "saveCCToken", SAVE_PAYPAL_TOKEN: "savePaypalToken", + + CREATE_SUBMITTED_ORDER: "createSubmittedOrder", + RESET_SUBMITTED_ORDER: "resetSubmittedOrder", }; export { storeActions }; diff --git a/src/layouts/confirmation/confirmation.spec.js b/src/layouts/confirmation/confirmation.spec.js index 4bef5f8a3..e0e970abd 100644 --- a/src/layouts/confirmation/confirmation.spec.js +++ b/src/layouts/confirmation/confirmation.spec.js @@ -19,6 +19,53 @@ beforeEach(() => { jest.restoreAllMocks(); jest.clearAllMocks(); store.getters = { + submittedOrder: { + schedule: { + date: "2023-01-01", + startTime: "09:00", + endTime: "10:00", + routeCode: "000", + }, + 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, + }, + referralNumber: "1234567", + vehicle: { + year: "2004", + make: "Ford", + model: "F Series F250", + }, + customer: { + emailAddress: "test@test.com", + }, + }, order: { schedule: { date: "2023-01-01", @@ -127,9 +174,10 @@ describe("computed properties...", () => { }); test("ScheduleTimeFormatted should return mobile time in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE; - store.getters.order.schedule.startTime = "09:00"; - store.getters.order.schedule.endTime = "11:00"; + store.getters.submittedOrder.serviceLocation.appointmentType = + AppointmentTypeStrings.MOBILE; + store.getters.submittedOrder.schedule.startTime = "09:00"; + store.getters.submittedOrder.schedule.endTime = "11:00"; const { wrapper } = setupMocks({}); // Act @@ -140,9 +188,10 @@ describe("computed properties...", () => { }); test("ScheduleTimeFormatted should return DROP_OFF time in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF; - store.getters.order.schedule.startTime = "09:00"; - store.getters.order.schedule.endTime = "11:00"; + 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({}); // Act @@ -153,9 +202,10 @@ describe("computed properties...", () => { }); test("ScheduleTimeFormatted should return Inshop time in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP; - store.getters.order.schedule.startTime = "09:00"; - store.getters.order.schedule.endTime = "11:00"; + 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({}); // Act @@ -166,7 +216,8 @@ describe("computed properties...", () => { }); test("AppointmentWordingText should return mobile text in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE; + store.getters.submittedOrder.serviceLocation.appointmentType = + AppointmentTypeStrings.MOBILE; const { wrapper } = setupMocks({}); // Act @@ -177,7 +228,8 @@ describe("computed properties...", () => { }); test("AppointmentWordingText should return DROP_OFF text in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF; + store.getters.submittedOrder.serviceLocation.appointmentType = + AppointmentTypeStrings.DROP_OFF; const { wrapper } = setupMocks({}); @@ -189,7 +241,8 @@ describe("computed properties...", () => { }); test("AppointmentWordingText should return IN_SHOP text in expected format.", () => { //Arrange - store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP; + store.getters.submittedOrder.serviceLocation.appointmentType = + AppointmentTypeStrings.IN_SHOP; const { wrapper } = setupMocks({}); diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue index 505f41bf0..51c109677 100644 --- a/src/layouts/confirmation/confirmation.vue +++ b/src/layouts/confirmation/confirmation.vue @@ -57,6 +57,8 @@ import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner"; import navbar from "@/fmg-components/nav-bar/nav-bar"; import addToCalendar from "@/layouts/confirmation/add-to-calendar/add-to-calendar"; //Supporting files +import baseMixin from "@/mixins/base-mixin.js"; +import { storeActions } from "@/constants/store-actions"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { AppointmentTypeStrings } from "@/constants/schedule-constants"; import { settleAllPromises } from "@/helpers/layout-helper"; @@ -70,6 +72,8 @@ import { get12HourTimeFormat, get12HourTimeMobileFormat } from "@/helpers/date-h export default { name: "confirmation", async beforeRouteEnter(to, from, next) { + await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_ORDER); + // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); @@ -95,7 +99,7 @@ export default { return this.getCmsContent("ScheduleConfirmationWidget", "Image"); }, CustomerPortalLoginToken() { - return store.getters.order.customerPortalLoginToken; + return store.getters.submittedOrder.customerPortalLoginToken; }, ConfirmationEmailText() { return this.getCmsContent("ConfirmationEmailWidget", "BodyText") @@ -105,16 +109,16 @@ export default { ?.replaceAll(">", ">"); }, ScheduleDate() { - return store.getters.order.schedule.date; + return store.getters.submittedOrder.schedule.date; }, AppointmentType() { - return store.getters.order.serviceLocation.appointmentType; + return store.getters.submittedOrder.serviceLocation.appointmentType; }, ScheduleStartTime() { - return store.getters.order.schedule.startTime; + return store.getters.submittedOrder.schedule.startTime; }, ScheduleEndTime() { - return store.getters.order.schedule.endTime; + return store.getters.submittedOrder.schedule.endTime; }, InShopWordingText() { return this.getCmsContent("InShopWordingWidget", "BodyText"); @@ -126,31 +130,31 @@ export default { return this.getCmsContent("DropOffWordingWidget", "BodyText"); }, ServiceLocationAddress() { - return store.getters.order.serviceLocation.address; + return store.getters.submittedOrder.serviceLocation.address; }, ServiceLocationAddress2() { - return store.getters.order.serviceLocation.address2; + return store.getters.submittedOrder.serviceLocation.address2; }, ServiceLocationCity() { - return store.getters.order.serviceLocation.city; + return store.getters.submittedOrder.serviceLocation.city; }, ServiceLocationState() { - return store.getters.order.serviceLocation.state; + return store.getters.submittedOrder.serviceLocation.state; }, ServiceLocationZipCode() { - return store.getters.order.serviceLocation.zipCode; + return store.getters.submittedOrder.serviceLocation.zipCode; }, ProviderAddress() { - return store.getters.order.serviceLocation.provider.address.streetAddress; + return store.getters.submittedOrder.serviceLocation.provider.address.streetAddress; }, ProviderCity() { - return store.getters.order.serviceLocation.provider.address.city; + return store.getters.submittedOrder.serviceLocation.provider.address.city; }, ProviderState() { - return store.getters.order.serviceLocation.provider.address.state; + return store.getters.submittedOrder.serviceLocation.provider.address.state; }, ProviderZipCode() { - return store.getters.order.serviceLocation.provider.address.zipCode; + return store.getters.submittedOrder.serviceLocation.provider.address.zipCode; }, AppointmentWordingText() { if (this.AppointmentType == AppointmentTypeStrings.MOBILE) { @@ -204,6 +208,10 @@ export default { }, methods: { arePagePrerequisitesValid() { + if (store.getters.hasSubmittedOrder) { + return true; + } + // Service Location const serviceLocation = store.getters.order.serviceLocation; const mobileReqs = !!( diff --git a/src/layouts/payment/payment-switch/payment-switch-button/payment-switch-button.vue b/src/layouts/payment/payment-switch/payment-switch-button/payment-switch-button.vue new file mode 100644 index 000000000..7199e27e7 --- /dev/null +++ b/src/layouts/payment/payment-switch/payment-switch-button/payment-switch-button.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/layouts/payment/payment-switch/payment-switch.vue b/src/layouts/payment/payment-switch/payment-switch.vue new file mode 100644 index 000000000..5b72ffc39 --- /dev/null +++ b/src/layouts/payment/payment-switch/payment-switch.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/layouts/payment/payment.vue b/src/layouts/payment/payment.vue index fc43af443..a8780cbc5 100644 --- a/src/layouts/payment/payment.vue +++ b/src/layouts/payment/payment.vue @@ -21,39 +21,10 @@ scrolling="no"> -
{{ switchPaymentText }}
-
- -
-
or
-
- -
-
or
-
- -
+ diff --git a/src/layouts/vehicle/vehicle.vue b/src/layouts/vehicle/vehicle.vue index 1754a3a91..200ade920 100644 --- a/src/layouts/vehicle/vehicle.vue +++ b/src/layouts/vehicle/vehicle.vue @@ -334,6 +334,7 @@ export default { }, async forwardButtonAction() { + await this.dispatchStoreAction(storeActions.RESET_SUBMITTED_ORDER); this.dispatchStoreAction( storeActions.SAVE_VEHICLE, { diff --git a/src/router/index.js b/src/router/index.js index 0a1bef3a3..cec3ff193 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -55,8 +55,17 @@ const routes = [ await GoToFunnelStartOn404(next); } + // Intercept all navigation if a submitted order exists in storage + if (store.getters.hasSubmittedOrder) { + if (to.query.fmgPage !== "vehicle") { + to.query.fmgPage = "confirmation"; + } + } // On entering the funnel "fresh", read cookie information, decide what to do next. payment pages used to return from safelitehop so exclude here - if (from.redirectedFrom === undefined && !to.query.fmgPage.startsWith("payment")) { + else if ( + from.redirectedFrom === undefined && + !to.query.fmgPage.startsWith("payment") + ) { // clear the saveSessionPromise - if it exists in the vuex store but a new instance was created // the saveSessionPromise will no longer point to a valid promise baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); diff --git a/src/store/index.js b/src/store/index.js index 175b78ce7..c096fa8fd 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -691,6 +691,8 @@ export const getters = { .filter((x) => !!x.isActive) .map((x) => x.settings) .reduce((r, c) => Object.assign(r, c), {}) ?? {}, + submittedOrder: (state) => JSON.parse(window.sessionStorage.getItem("submittedOrder")), + hasSubmittedOrder: (state) => window.sessionStorage.getItem("submittedOrder") !== null, }; function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) { @@ -2441,6 +2443,26 @@ export const actions = { return false; }, + + createSubmittedOrder(context) { + if (context.getters.hasSubmittedOrder) { + return; + } + + // create a submitted order object from vuex. + const submittedOrder = context.state.order; + + // set to local storage + window.sessionStorage.setItem("submittedOrder", JSON.stringify(submittedOrder)); + + // clear vuex + context.commit(storeMutations.RESET_STATE); + }, + + resetSubmittedOrder(context) { + // clear from local storage + window.sessionStorage.removeItem("submittedOrder"); + }, }; export default createStore({