diff --git a/src/assets/img/icons/Google.svg b/src/assets/img/icons/Google.svg
new file mode 100644
index 000000000..606351ec9
--- /dev/null
+++ b/src/assets/img/icons/Google.svg
@@ -0,0 +1,14 @@
+
diff --git a/src/assets/img/icons/Outlook.com.svg b/src/assets/img/icons/Outlook.com.svg
new file mode 100644
index 000000000..467b585ac
--- /dev/null
+++ b/src/assets/img/icons/Outlook.com.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/assets/img/icons/Outlook.svg b/src/assets/img/icons/Outlook.svg
new file mode 100644
index 000000000..f974fb13a
--- /dev/null
+++ b/src/assets/img/icons/Outlook.svg
@@ -0,0 +1,16 @@
+
diff --git a/src/assets/img/icons/Yahoo.svg b/src/assets/img/icons/Yahoo.svg
new file mode 100644
index 000000000..0206eccbb
--- /dev/null
+++ b/src/assets/img/icons/Yahoo.svg
@@ -0,0 +1,13 @@
+
diff --git a/src/assets/img/icons/iCal.svg b/src/assets/img/icons/iCal.svg
new file mode 100644
index 000000000..399bcdea0
--- /dev/null
+++ b/src/assets/img/icons/iCal.svg
@@ -0,0 +1,11 @@
+
diff --git a/src/constants/calendar-options.js b/src/constants/calendar-options.js
new file mode 100644
index 000000000..c87a85b18
--- /dev/null
+++ b/src/constants/calendar-options.js
@@ -0,0 +1,8 @@
+const calendarOptions = {
+ ICAL: "iCal",
+ GOOGLE: "Google",
+ OUTLOOK: "Outlook",
+ OUTLOOKCOM: "Outlook.com",
+ YAHOO: "Yahoo",
+};
+export { calendarOptions };
diff --git a/src/constants/calendar-status.js b/src/constants/calendar-status.js
new file mode 100644
index 000000000..38cf23467
--- /dev/null
+++ b/src/constants/calendar-status.js
@@ -0,0 +1,7 @@
+const calendarStatus = {
+ FREE: "Free",
+ BUSY: "Busy",
+ TENTATIVE: "Tentative",
+ OUT_OF_THE_OFFICE: "OutOfTheOffice",
+};
+export { calendarStatus };
diff --git a/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue b/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue
index 0a6faa72f..d894f2ee8 100644
--- a/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue
+++ b/src/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons.vue
@@ -21,9 +21,8 @@ export default {
name: "add-vaps-modal-buttons",
props: {
cartItems: Object,
- rainDefenseItem: Object,
- wiperItems: Object,
vapsTilesCmsName: String,
+ availableLineItems: Object,
},
data() {
return {
@@ -55,13 +54,19 @@ export default {
});
},
rainDefensePrice() {
- const lineItem = this.rainDefenseItem;
+ // const lineItem = this.rainDefenseItem;
+ const lineItem = this.availableLineItems.find((item) => {
+ return item.partType === "RAIN DEFENSE";
+ });
+
const price = lineItem.laborAmount + lineItem.sellingPrice + lineItem.kitPrice;
return parseFloat(price).toFixed(2);
},
wipersPrice() {
let price = 0;
- const lineItems = this.wiperItems;
+ const lineItems = this.availableLineItems.filter((item) => {
+ return item.partType.includes(" WIPER");
+ });
lineItems?.forEach((item) => {
price += item.laborAmount + item.sellingPrice + item.kitPrice;
});
diff --git a/src/fmg-components/cart/cart.vue b/src/fmg-components/cart/cart.vue
index 67558c323..7107e64e8 100644
--- a/src/fmg-components/cart/cart.vue
+++ b/src/fmg-components/cart/cart.vue
@@ -54,36 +54,28 @@
+
diff --git a/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-list-button/calendar-modal-list-button.vue b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-list-button/calendar-modal-list-button.vue
new file mode 100644
index 000000000..7f4fe2801
--- /dev/null
+++ b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-list-button/calendar-modal-list-button.vue
@@ -0,0 +1,79 @@
+
+
+
+
+
+ {{ value }}
+
+
+
+
+
+
diff --git a/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js
new file mode 100644
index 000000000..d28c2442f
--- /dev/null
+++ b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.spec.js
@@ -0,0 +1,53 @@
+import { shallowMount } from "@vue/test-utils";
+import { getMountOptions } from "@/helpers/unit-test-helper.js";
+import calendarModalQuestion from "@/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.vue";
+
+describe("calendar-modal-question.vue", () => {
+ test("When selected calendar option is changed, a correctly selectedCalendarOption should be emitted", async () => {
+ //Arrange
+ const url = "iCal url";
+ const name = "iCal";
+ const icon = "iCal.svg";
+ const expectedEmit = [
+ [
+ {
+ url: url,
+ name: name,
+ icon: icon,
+ },
+ ],
+ ];
+
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ propsData: {
+ calendarOptionsData: [
+ {
+ url: url,
+ name: name,
+ icon: icon,
+ },
+ ],
+ },
+ },
+ });
+
+ wrapper.vm.$refs.calendarOptions.closeModal = jest.fn();
+ wrapper.vm.selectedCalendarOption = name;
+
+ //Act
+ wrapper.vm.setSelectedCalendarOption();
+
+ //Assert
+ expect(wrapper.emitted()["update:modelValue"]).toEqual(expectedEmit);
+ });
+});
+
+function setupMocks({ customMountOptions }) {
+ const mountOptions = getMountOptions({
+ ...customMountOptions,
+ });
+
+ const wrapper = shallowMount(calendarModalQuestion, mountOptions);
+ return { wrapper };
+}
diff --git a/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.vue b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.vue
new file mode 100644
index 000000000..dacda07f2
--- /dev/null
+++ b/src/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.vue
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/layouts/confirmation/confirmation.spec.js b/src/layouts/confirmation/confirmation.spec.js
index c60b19c26..4bef5f8a3 100644
--- a/src/layouts/confirmation/confirmation.spec.js
+++ b/src/layouts/confirmation/confirmation.spec.js
@@ -1,5 +1,7 @@
// Components
import confirmation from "@/layouts/confirmation/confirmation.vue";
+import { AppointmentTypeStrings } from "@/constants/schedule-constants";
+import { applicationConfig } from "@/constants/application-config.js";
// Supporting Files
import { shallowMount } from "@vue/test-utils";
@@ -12,14 +14,14 @@ import router from "@/router";
jest.mock("@/helpers/layout-helper.js", () => ({
settleAllPromises: jest.fn(),
}));
-
+var wordingText = "wording Text {custom:ADDRESS}";
beforeEach(() => {
jest.restoreAllMocks();
jest.clearAllMocks();
store.getters = {
order: {
schedule: {
- date: "2019-01-01",
+ date: "2023-01-01",
startTime: "09:00",
endTime: "10:00",
routeCode: "000",
@@ -33,9 +35,9 @@ beforeEach(() => {
supportingItems: [],
},
serviceLocation: {
- address: "",
- address2: null,
- city: "",
+ address: "test",
+ address2: "123",
+ city: "test",
state: "AZ",
appointmentType: "Inshop",
zipCode: "12345",
@@ -112,8 +114,188 @@ describe("confirmation.vue", () => {
expect(window.location.assign).toHaveBeenCalled();
});
});
+describe("computed properties...", () => {
+ test("ScheduleDateFormatted should return date in expected format.", () => {
+ //Arrange
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleDateFormatted;
+
+ // Assert
+ expect(testValue).toEqual("Sunday, January 1");
+ });
+ 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";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleTimeFormatted;
+
+ // Assert
+ expect(testValue).toEqual("Between 9 AM - 11 AM");
+ });
+ 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";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleTimeFormatted;
+
+ // Assert
+ expect(testValue).toEqual("Drop off before 9:30 AM");
+ });
+ 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";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleTimeFormatted;
+
+ // Assert
+ expect(testValue).toEqual("at 9:00 AM");
+ });
+ test("AppointmentWordingText should return mobile text in expected format.", () => {
+ //Arrange
+ store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;
+
+ const { wrapper } = setupMocks({});
+ // Act
+ const testValue = wrapper.vm.AppointmentWordingText;
+
+ // Assert
+ expect(testValue).toEqual("wording Text 123, test,
test, AZ 12345");
+ });
+ test("AppointmentWordingText should return DROP_OFF text in expected format.", () => {
+ //Arrange
+ store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.AppointmentWordingText;
+
+ // Assert
+ expect(testValue).toEqual("wording Text test1,
test, AZ 12345");
+ });
+ test("AppointmentWordingText should return IN_SHOP text in expected format.", () => {
+ //Arrange
+ store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP;
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.AppointmentWordingText;
+
+ // Assert
+ expect(testValue).toEqual("wording Text test1,
test, AZ 12345");
+ });
+ test("ConfirmationEmailText should return text in expected format.", () => {
+ //Arrange
+ wordingText = "{custom:MY_ACCOUNT_URL}";
+ const { wrapper } = setupMocks({});
+ // Act
+ const testValue = wrapper.vm.ConfirmationEmailText;
+
+ // Assert
+ expect(testValue).toEqual(applicationConfig.MY_ACCOUNT);
+ });
+ test("ScheduleDate should return date in expected format.", () => {
+ //Arrange
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleDate;
+
+ // Assert
+ expect(testValue).toEqual("2023-01-01");
+ });
+ test("ScheduleStartTime should return time in expected format.", () => {
+ //Arrange
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleStartTime;
+
+ // Assert
+ expect(testValue).toEqual("09:00");
+ });
+ test("ScheduleEndTime should return time in expected format.", () => {
+ //Arrange
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ScheduleEndTime;
+
+ // Assert
+ expect(testValue).toEqual("10:00");
+ });
+ test("InShopWordingText should return text in expected format.", () => {
+ //Arrange
+ wordingText = "InShopWordingText format";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.InShopWordingText;
+
+ // Assert
+ expect(testValue).toEqual(wordingText);
+ });
+ test("MobileWordingText should return text in expected format.", () => {
+ //Arrange
+ wordingText = "MobileWordingText format";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.MobileWordingText;
+
+ // Assert
+ expect(testValue).toEqual(wordingText);
+ });
+ test("DropOffWordingText should return text in expected format.", () => {
+ //Arrange
+ wordingText = "DropOffWordingText format";
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.DropOffWordingText;
+
+ // Assert
+ expect(testValue).toEqual(wordingText);
+ });
+ test("ServiceLocationFullAddress should return text in expected format.", () => {
+ //Arrange
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ServiceLocationFullAddress;
+
+ // Assert
+ expect(testValue).toEqual("123, test,
test, AZ 12345");
+ });
+ test("ProviderFullAddress should return text in expected format.", () => {
+ //Arrange
+
+ const { wrapper } = setupMocks({});
+
+ // Act
+ const testValue = wrapper.vm.ProviderFullAddress;
+
+ // Assert
+ expect(testValue).toEqual("test1,
test, AZ 12345");
+ });
+});
-const wordingText = "wording Text";
function setupMocks({ customMountOptions }) {
const mountOptions = getMountOptions({
...customMountOptions,
diff --git a/src/layouts/confirmation/confirmation.vue b/src/layouts/confirmation/confirmation.vue
index 3691cf496..cb7ca43c1 100644
--- a/src/layouts/confirmation/confirmation.vue
+++ b/src/layouts/confirmation/confirmation.vue
@@ -10,6 +10,10 @@
+
+
{{ this.ScheduleDateFormatted }}
{{ this.ScheduleTimeFormatted }}
+
-
-
-
-
-
@@ -58,6 +49,7 @@
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import navbar from "@/fmg-components/nav-bar/nav-bar";
+import addToCalendar from "@/layouts/add-to-calendar/add-to-calendar";
//Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
@@ -243,6 +235,7 @@ export default {
Form,
navbar,
vehicleBanner,
+ addToCalendar,
},
};
diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index eac00fe15..ecd310c5c 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -17,8 +17,8 @@
@@ -34,10 +34,50 @@
+ :availableLineItems="availableLineItems"
+ vapsTilesCmsName="VapsProductTiles"
+ v-on="{ 'buttonEvent.openModal': openModal }" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -64,6 +104,7 @@ import paymentMethodQuestion from "@/layouts/payment-method/payment-method-quest
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import cart from "@/fmg-components/cart/cart";
import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons";
+import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
import alert from "@/ux-components/alert/alert";
@@ -88,11 +129,14 @@ export default {
null,
"payment-method"
);
+
const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_RAIN_DEFENSE,
null,
"payment-method"
);
+ console.log("rainDefensePromise: ", rainDefensePromise);
+
const supportingItemsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_SUPPORTING_ITEMS,
null,
@@ -119,16 +163,17 @@ export default {
];
const resultMap = await settleAllPromises(promiseResultMap);
- const clonedGlassParts = store.getters.order.lineItems.glassParts
- ? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts))
- : [];
+
+ const glassParts = (await store.getters.order.lineItems.glassParts) ?? [];
+
const availableLineItems = [
resultMap.rainDefense,
...resultMap.supportingItems,
...resultMap.wipers,
- ...clonedGlassParts,
+ ...glassParts,
];
- const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
+
+ const pricedAvailableLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
{
availableLineItems: availableLineItems,
@@ -136,30 +181,25 @@ export default {
"payment-method",
false
);
- const storeLineItems = store.getters.lineItems;
- const cartItems = [
- ...clonedGlassParts,
- ...storeLineItems.supportingItems,
- ...storeLineItems.vaps,
- ];
+ const lineItems = store.getters.lineItems;
+
+ const cartItems = [...glassParts, ...lineItems.supportingItems, ...lineItems.vaps]; // TOBEREMOVED BY AJC IN CSR-1384
// Call the "next" function to complete the transition to this page.
next((vm) => {
+ vm.cartItems = cartItems; // TOBEREMOVED BY AJC IN CSR-1384
+
vm.setCmsContent(resultMap.cmsContent);
- vm.availableLineItems = pricingResults;
- vm.availableWipers = resultMap.wipers;
- vm.availableRainDefense = resultMap.rainDefense;
- vm.cartItems = cartItems;
+ vm.availableLineItems = pricedAvailableLineItems;
+ vm.lineItems = lineItems;
});
},
data() {
return {
- cartItems: [],
- availableWipers: null,
- availableRainDefense: null,
- availableLineItems: null,
- supportingItems: null,
- pricedGlassParts: null,
+ cartItems: [], // TOBEREMOVED BY AJC IN CSR-1384
+
+ lineItems: [],
+ availableLineItems: [],
displayPaypalAlert: this.getPaypalAlert(),
paymentMethodInternalModel: null,
};
@@ -217,6 +257,9 @@ export default {
packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs
);
},
+ openModal(modalName) {
+ this.$refs[modalName].openModal();
+ },
getPaypalAlert() {
return store.getters.order.payment.piaErrorCode ? true : false;
},
@@ -231,7 +274,7 @@ export default {
const matchedIndices = [];
this.cartItems.forEach((cartItem, i) => {
if (cartItem.partType === item.partType) {
- console.log("adding this to matchedIndices: ", i);
+ // console.log("adding this to matchedIndices: ", i);
matchedIndices.push(i);
}
});
@@ -284,12 +327,9 @@ export default {
},
computed: {
damageInfo() {
+ // console.log("this.$store.getters.damage ", this.$store.getters.damage)
return this.$store.getters.damage;
},
- storeLineItems() {
- // console.log("storeLineItems, aka lineItems from store: ", this.$store.getters.lineItems)
- return this.$store.getters.lineItems;
- },
customCtaCopy() {
switch (this.paymentMethod) {
case paymentMethods.CREDIT_CARD:
@@ -332,6 +372,7 @@ export default {
cart,
alert,
addVapsModalButtons,
+ contentGroupModal,
paymentMethodQuestion,
},
};
diff --git a/src/layouts/schedule/schedule.spec.js1 b/src/layouts/schedule/schedule.spec.js1
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/store/index.js b/src/store/index.js
index 2c2eb8492..bcafa6509 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -14,6 +14,7 @@ import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper
import { deepEqual } from "@/helpers/object-helper";
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
+import { deepClone } from "@/helpers/object-helper";
import { queryStrings } from "@/constants/query-strings";
import { partTypeStrings } from "@/constants/part-type-strings";
import {
@@ -2067,9 +2068,9 @@ export const actions = {
context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData);
- availableLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems);
+ const pricedLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems);
- return availableLineItems;
+ return pricedLineItems;
},
// Misc order actions
@@ -2277,7 +2278,8 @@ function convertGlassPieceNamingFromApi(glassArray) {
}
function addPricesToLineItems(lineItems, pricingLineItems) {
- lineItems.forEach((lineItem) => {
+ const pricedLineItems = deepClone(lineItems);
+ pricedLineItems.forEach((lineItem) => {
let lineItemIndex = pricingLineItems.findIndex(
(pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber
);
@@ -2289,7 +2291,7 @@ function addPricesToLineItems(lineItems, pricingLineItems) {
lineItem.sellingPrice = pricedLineItem.sellingPrice;
lineItem.kitPrice = pricedLineItem.kitPrice;
});
- return lineItems;
+ return pricedLineItems;
}
function getFlattenedArrayOfLineItemsWithChildParts(lineItems) {