diff --git a/src/assets/img/icons/alert-circle-yellow.svg b/src/assets/img/icons/alert-circle-yellow.svg deleted file mode 100644 index 904aefb98..000000000 --- a/src/assets/img/icons/alert-circle-yellow.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/src/constants/analytics.js b/src/constants/analytics.js index e156de11b..51b0c24b6 100644 --- a/src/constants/analytics.js +++ b/src/constants/analytics.js @@ -15,6 +15,8 @@ const GaCategories = { APPOINTMENT: "Appointment", SERVICE_LOCATION: "service-location", CONFIRMATION_CLICKED: "confirmation clicked", + INSHOP_CONFIRMATION_CLICKED: "inshop confirmation clicked", + MOBILE_CONFIRMATION_CLICKED: "mobile confirmation clicked", RECAL_DISCLAIMER: "Recalibration disclaimer", }; diff --git a/src/constants/experiments.js b/src/constants/experiments.js index c76b1ea1c..f8691fc46 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -5,6 +5,7 @@ const experimentUniverses = { IGQ_SkipQuote: "NextGen_IGQSkipToInsurance", AFTERPAY_BREAKOUT_DISPLAY: "AfterpayBreakoutDisplay", MOBILE_FIRST_APPOINTMENT: "MobileFirstAppointment", + MULTI_LOCATION_POPUP: "MultiLocationPopup", }; const experimentSettings = { @@ -40,6 +41,10 @@ const experimentSettings = { SHOW_MOBILE_FIRST_POPUP_REPLACE_WITHOUT_MSR: "Show_Mobile_First_Popup_Replace_Without_MSR", SHOW_MOBILE_FIRST_POPUP_REPLACE_WITH_MSR: "Show_Mobile_First_Popup_Replace_With_MSR", OFFER_OEM: "OfferOem", + SHOW_MULTI_LOCATION_APPT: "ShowMultiLocationAppt", + SHOW_NO_AVAILABILE_DAYS_MULTI_LOCATION: "Show_NoAvailableDaysMultiLocation", + SHOW_NO_PM_DAYS_MULTI_LOCATION: "Show_NoPMDaysMultiLocation", + SHOW_PM_DAYS_MULTI_LOCATION: "Show_PMDaysMultiLocation", USE_ADYEN_PAYMENT: "UseAdyenPayment", SHOW_UNVERIFIED_DEDUCT_ENTRY: "ShowUnverifiedDeducEntry", SERVICE_PACKAGE_ORDER: "ServicePackageOrder", diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue index 9862633ad..417c88809 100644 --- a/src/digital-components/button-question/button-question.vue +++ b/src/digital-components/button-question/button-question.vue @@ -226,6 +226,7 @@ export default { let classes; switch (this.buttonTypeString) { case "timeSlotModalListButton": + case "multiLocationRadioButton": case "listButton": classes = "w-100"; break; @@ -265,6 +266,8 @@ export default { classes += " radio-button-container"; } else if (this.buttonTypeString == "servicePackageRadio") { classes = "package-wrapper col"; + } else if (this.buttonTypeString == "multiLocationRadioButton") { + classes = "multi-location-wrapper col"; } if (this.buttonTypeString == "listCard" && this.buttonsInfo.length > 2) { diff --git a/src/fmg-components/promo-modal-question/promo-modal-question.vue b/src/fmg-components/promo-modal-question/promo-modal-question.vue index 1e87d5bb5..bb3b390a8 100644 --- a/src/fmg-components/promo-modal-question/promo-modal-question.vue +++ b/src/fmg-components/promo-modal-question/promo-modal-question.vue @@ -317,6 +317,10 @@ export default { serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, pricedLineItems: pricedLineItemsToTax, + serviceLocationAddressLine1: + store.getters.order.serviceLocation?.address, + serviceLocationAddressLine2: + store.getters.order.serviceLocation?.address2, }, "payment-method", false diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index 450875d0f..727add296 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -343,14 +343,3 @@ export function splitCMSCopyOnParagraphTag(copy) { export function splitCMSCopyOnBR(copy) { return copy.split("
"); } - -// This function takes in a number and returns it formatted as USD currency, with or without cents depending on if the number is an integer or not. -export function formatToUSDollar(amount) { - const isInteger = amount % 1 === 0; - return new Intl.NumberFormat("en-US", { - style: "currency", - currency: "USD", - minimumFractionDigits: isInteger ? 0 : 2, - maximumFractionDigits: 2, - }).format(amount); -} diff --git a/src/helpers/vehicle-helper.js b/src/helpers/vehicle-helper.js new file mode 100644 index 000000000..cd94d7bd5 --- /dev/null +++ b/src/helpers/vehicle-helper.js @@ -0,0 +1,11 @@ +import store from "@/store"; + +export function hasVehicleInfo() { + return ( + store.getters.order?.vehicle.year && + store.getters.order?.vehicle?.make && + store.getters.order?.vehicle?.model && + store.getters.order?.vehicle?.style && + store.getters.order?.vehicle?.carId + ); +} diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 4d80f84c0..d333b4bbf 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -322,6 +322,8 @@ export default { serviceLocationState: store.getters.order.serviceLocation.state, serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, pricedLineItems: lineItemsForCart, + serviceLocationAddressLine1: store.getters.order.serviceLocation?.address, + serviceLocationAddressLine2: store.getters.order.serviceLocation?.address2, }, "payment-method", false @@ -526,6 +528,10 @@ export default { serviceLocationState: this.$store.getters.order.serviceLocation.state, serviceLocationZipCode: this.$store.getters.order.serviceLocation.zipCode, pricedLineItems: this.lineItems, + serviceLocationAddressLine1: + this.$store.getters.order.serviceLocation?.address, + serviceLocationAddressLine2: + this.$store.getters.order.serviceLocation?.address2, }, "payment-method", false @@ -650,6 +656,8 @@ export default { serviceLocationState: store.getters.order.serviceLocation.state, serviceLocationZipCode: store.getters.order.serviceLocation.zipCode, pricedLineItems: this.lineItems, + serviceLocationAddressLine1: store.getters.order.serviceLocation?.address, + serviceLocationAddressLine2: store.getters.order.serviceLocation?.address2, }, "payment-method", false diff --git a/src/layouts/schedule/multi-location-modal/multi-location-modal.vue b/src/layouts/schedule/multi-location-modal/multi-location-modal.vue new file mode 100644 index 000000000..effa3c91b --- /dev/null +++ b/src/layouts/schedule/multi-location-modal/multi-location-modal.vue @@ -0,0 +1,345 @@ + + + + diff --git a/src/layouts/schedule/multi-location-modal/multi-location-radio/multi-location-radio.spec.js b/src/layouts/schedule/multi-location-modal/multi-location-radio/multi-location-radio.spec.js new file mode 100644 index 000000000..f305d4e2e --- /dev/null +++ b/src/layouts/schedule/multi-location-modal/multi-location-radio/multi-location-radio.spec.js @@ -0,0 +1,121 @@ +import { mount } from "@vue/test-utils"; +import multiLocationRadio from "./multi-location-radio"; +import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin"; + +describe("multi-location-radio.vue", () => { + it("Should include buttonLabel in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabel"])); + }); + + it("Should include buttonLabelSubCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelSubCopy"])); + }); + it("Should include buttonFooterCopy in html", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + + // Act + const outputHtml = wrapper.html(); + + // Assert + expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonFooterCopy"])); + }); + it("Should get 5 strings from getArrayOfListItemsFromRawCmsCopy when provided with a buttonBodyCopy", async () => { + // Arrange + let { wrapper } = setupMocks({ + mountOptionsMockData: { + propsData: mockProps, + }, + }); + // Act + const results = wrapper.vm.getArrayOfListItemsFromRawCmsCopy(wrapper.vm.buttonBodyCopy); + + // Assert + expect(results.length).toBe(5); + }); + it("Should get strings from getArrayOfListItemsFromRawCmsCopy without