diff --git a/src/layouts/vehicle-parts/vehicle-parts.spec.js b/src/layouts/vehicle-parts/vehicle-parts.spec.js
index 23ce3b88a..4d4287430 100644
--- a/src/layouts/vehicle-parts/vehicle-parts.spec.js
+++ b/src/layouts/vehicle-parts/vehicle-parts.spec.js
@@ -481,7 +481,7 @@ describe("vehicle-parts.vue", () => {
},
});
- wrapper.vm.$store.commit = jest.fn();
+ wrapper.vm.dispatchStoreAction = jest.fn();
wrapper.setData({
selectedGlassParts: { "Rear-Stationary": { partNumber: "DB12209GTYN" } },
@@ -498,7 +498,7 @@ describe("vehicle-parts.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
- expect(wrapper.vm.$store.commit).toHaveBeenCalled();
+ expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
// TODO KO UNCOMMENT FOR QUOTE PAGES RELEASE
// expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue
index 3291bdd79..95aa2891d 100644
--- a/src/layouts/vin-lookup/vin-lookup.vue
+++ b/src/layouts/vin-lookup/vin-lookup.vue
@@ -323,7 +323,7 @@ export default {
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
await this.dispatchStoreAction(
- storeActions.SAVE_SERVICE_LOCATION,
+ storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
zipCode: this.serviceZipCode,
state: resultMap.zipCodeData.state,
@@ -360,7 +360,7 @@ export default {
);
} else {
await this.dispatchStoreAction(
- storeActions.SAVE_SERVICE_LOCATION,
+ storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
zipCode: this.serviceZipCode,
state: zipCodeData.state,
diff --git a/src/mixins/vehicle-questions-mixin.js b/src/mixins/vehicle-questions-mixin.js
index 718f8fc50..4b05067ea 100644
--- a/src/mixins/vehicle-questions-mixin.js
+++ b/src/mixins/vehicle-questions-mixin.js
@@ -442,7 +442,7 @@ export default {
const collectedGlassParts = this.reducedGlassPartsArray(partsOrQuestions);
// save to store lineItems.glassParts
- self.$store.commit(storeMutations.UPDATE_GLASS_PARTS, collectedGlassParts);
+ self.dispatchStoreAction(storeActions.SAVE_GLASS_PARTS, collectedGlassParts, false);
const payment = store.getters.payment;
diff --git a/src/mixins/vehicle-questions-mixin.spec.js b/src/mixins/vehicle-questions-mixin.spec.js
index a9bf6f313..f87d7efdc 100644
--- a/src/mixins/vehicle-questions-mixin.spec.js
+++ b/src/mixins/vehicle-questions-mixin.spec.js
@@ -2240,15 +2240,17 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$store.commit).toHaveBeenCalledTimes(1);
- expect(wrapper.vm.$store.commit).toHaveBeenCalledWith(
- storeMutations.UPDATE_GLASS_PARTS,
+ expect(wrapper.vm.$store.dispatch).toHaveBeenCalledWith(
+ storeActions.SAVE_GLASS_PARTS,
collectedGlassParts
);
+
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
{ query: { fmgPage: "vin-lookup" } }
);
+
expect(wrapper.vm.$router.navigateWithoutSaving).not.toHaveBeenCalled();
});
});
diff --git a/src/router/index.js b/src/router/index.js
index 86c402187..27222ab08 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -28,22 +28,8 @@ import analyticsMixin from "@/mixins/analytics-mixin";
import { experimentTriggers } from "../constants/experiments";
import { applicationConfig } from "../constants/application-config";
-// Components
-import datePicker from "@/digital-components/date-picker/date-picker.vue";
-import demoDatePicker from "@/layouts/demo-date-picker/demo-date-picker.vue";
import review from "@/layouts/review/review";
-
const routes = [
- {
- path: "/demo-date-picker", // This is a temporary route for testing.
- name: "demo-date-picker",
- component: demoDatePicker,
- },
- {
- path: "/date-picker", // This is a temporary route for testing.
- name: "date-picker",
- component: datePicker,
- },
{
path: "/review", // This is a temporary route for testing.
name: "review",
diff --git a/src/store/index.js b/src/store/index.js
index 9d06df11a..eac829543 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,4 +1,4 @@
-import { createStore, Store } from "vuex";
+import { createStore } from "vuex";
import { endpoints } from "@/constants/endpoints.js";
import { storeMutations } from "@/constants/store-mutations";
import { getDateForSavedSessionTimeout } from "@/helpers/heritage-integration/session-helper";
@@ -9,8 +9,9 @@ import { applicationConfig } from "@/constants/application-config";
import { experimentTriggers } from "@/constants/experiments";
import { damageLocationsSelected } from "@/constants/damage-locations-selected";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
-import router from "@/router";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
+import { deepEqual } from "@/helpers/object-helper";
+import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
// Export State
const getDefaultState = () => {
@@ -39,11 +40,13 @@ const getDefaultState = () => {
},
serviceLocation: {
address: null,
+ address2: null,
city: null,
state: null,
zipCode: null,
zipCodeCtu: null,
appointmentType: null,
+ isVehicleProtected: null,
provider: {
providerNumber: null,
address: {
@@ -84,6 +87,7 @@ const getDefaultState = () => {
startTime: null,
endTime: null,
routeCode: null,
+ jobMaxMinutes: null,
},
referralNumber: null,
referralDate: null,
@@ -250,16 +254,7 @@ export const mutations = {
state.order.serviceLocation.isVehicleProtected = serviceLocationInfo.isVehicleProtected;
if (serviceLocationInfo.provider) {
- state.order.serviceLocation.provider.providerNumber =
- serviceLocationInfo.provider?.providerNumber;
- state.order.serviceLocation.provider.address.streetAddress =
- serviceLocationInfo.provider?.address?.streetAddress;
- state.order.serviceLocation.provider.address.city =
- serviceLocationInfo.provider?.address?.city;
- state.order.serviceLocation.provider.address.state =
- serviceLocationInfo.provider?.address?.state;
- state.order.serviceLocation.provider.address.zip =
- serviceLocationInfo.provider?.address?.zip;
+ state.order.serviceLocation.provider = serviceLocationInfo.provider;
}
},
updateSchedule(state, scheduleInfo) {
@@ -268,6 +263,7 @@ export const mutations = {
state.order.schedule.startTime = scheduleInfo.startTime;
state.order.schedule.endTime = scheduleInfo.endTime;
state.order.schedule.routeCode = scheduleInfo.routeCode;
+ state.order.schedule.jobMaxMinutes = scheduleInfo.jobMaxMinutes;
}
},
@@ -338,12 +334,44 @@ export const mutations = {
state.applicationUser.pageData[fmgPageValues.MOLDING_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.CAPABILITY_QUESTIONS] = null;
},
+ resetSchedule(state) {
+ state.order.schedule.date = null;
+ state.order.schedule.startTime = null;
+ state.order.schedule.endTime = null;
+ state.order.schedule.routeCode = null;
+ state.order.schedule.jobMaxMinutes = null;
+
+ //early bird fee used on schedule page also needs reset when schedule is reset
+ const supportingItems = state.order.lineItems.supportingItems;
+ const removeEarlyBirdIndex = supportingItems?.findIndex(
+ (item) => item.partType == PREMIUM_FEE_PART_TYPE
+ );
+
+ if (removeEarlyBirdIndex >= 0) {
+ supportingItems.splice(removeEarlyBirdIndex, 1);
+ state.order.lineItems.supportingItems = supportingItems;
+ }
+ },
resetState(state) {
Object.assign(state, getDefaultState());
},
resetSaveSessionPromise(state) {
state.applicationUser.saveSessionPromise = null;
},
+ resetServiceLocationAppointmentType(state) {
+ state.order.serviceLocation.appointmentType = null;
+ },
+ resetServiceLocationProvider(state) {
+ state.order.serviceLocation.provider = null;
+ },
+ resetServiceLocationMobileAddress(state) {
+ state.order.serviceLocation.address = null;
+ state.order.serviceLocation.address2 = null;
+ state.order.serviceLocation.city = null;
+ state.order.serviceLocation.state = null;
+ state.order.serviceLocation.zipCode = null;
+ state.order.serviceLocation.isVehicleProtected = null;
+ },
// Misc Mutations
updateStateWithOrderInformation(state, sessionInformation) {
state.order.referralNumber = sessionInformation.order.referralNumber;
@@ -395,18 +423,20 @@ export const mutations = {
state.order.lineItems.supportingItems = sessionInformation.order.lineItems.supportingItems;
state.order.lineItems.vaps = sessionInformation.order.lineItems.vaps;
state.order.lineItems.serverData = sessionInformation.order.lineItems.serverData;
+
state.order.payment.parentAccountNumber =
sessionInformation.order.payment.parentAccountNumber;
- (state.order.serviceLocation.address =
- sessionInformation.order.serviceLocation.streetAddress),
- (state.order.serviceLocation.address2 =
- sessionInformation.order.serviceLocation.address2),
- (state.order.serviceLocation.city = sessionInformation.order.serviceLocation.city),
- (state.order.serviceLocation.state = sessionInformation.order.serviceLocation.state),
- (state.order.serviceLocation.zipCode =
- sessionInformation.order.serviceLocation.zipCode),
- (state.order.serviceLocation.zipCodeCtu =
- sessionInformation.order.serviceLocation.zipCodeCtu);
+
+ state.order.serviceLocation.address =
+ sessionInformation.order.serviceLocation.streetAddress;
+ state.order.serviceLocation.address2 =
+ sessionInformation.order.serviceLocation.streetAddress2;
+ state.order.serviceLocation.city = sessionInformation.order.serviceLocation.city;
+ state.order.serviceLocation.state = sessionInformation.order.serviceLocation.state;
+ state.order.serviceLocation.zipCode = sessionInformation.order.serviceLocation.zipCode;
+ state.order.serviceLocation.zipCodeCtu =
+ sessionInformation.order.serviceLocation.zipCodeCtu;
+
state.order.serviceLocation.appointmentType =
sessionInformation.order.serviceLocation.appointmentType;
state.order.serviceLocation.isVehicleProtected =
@@ -440,6 +470,7 @@ export const mutations = {
state.order.schedule.startTime = sessionInformation.order.schedule?.startTime;
state.order.schedule.endTime = sessionInformation.order.schedule?.endTime;
state.order.schedule.routeCode = sessionInformation.order.schedule?.routeCode;
+ state.order.schedule.jobMaxMinutes = sessionInformation.order.schedule?.jobMaxMinutes;
},
updateExperiments(state, experiments) {
state.applicationUser.experiments = experiments;
@@ -551,6 +582,7 @@ export const actions = {
payload: {},
});
},
+
lookupVehicleByYmms(context, { year, make, model, style }) {
return globalMethods.callHttpClient({
method: endpoints.LookupVehicleByYmms.method,
@@ -558,6 +590,7 @@ export const actions = {
payload: {},
});
},
+
lookupVehicleByVin(context, { vin }) {
return globalMethods.callHttpClient({
method: endpoints.LookupVehicleByVin.method,
@@ -567,6 +600,7 @@ export const actions = {
},
});
},
+
lookupVinByPlate(context, { licensePlate, licenseState }) {
return globalMethods.callHttpClient({
method: endpoints.LookupVinByPlate.method,
@@ -577,6 +611,7 @@ export const actions = {
},
});
},
+
lookupVinByAddress(
context,
{ licenseLastName, licenseStreetAddress, licenseZip, licenseState }
@@ -592,6 +627,7 @@ export const actions = {
},
});
},
+
lookupVinByImage(context, image) {
const data = new FormData();
data.append("vinImage", image);
@@ -602,6 +638,7 @@ export const actions = {
isFormData: true,
});
},
+
isVinByAddressPermissible(context, zip) {
return globalMethods.callHttpClient({
method: endpoints.IsVinByAddressPermissible.method,
@@ -609,6 +646,7 @@ export const actions = {
payload: {},
});
},
+
getVehicleMakes(context, { year }) {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleMakes.method,
@@ -616,6 +654,7 @@ export const actions = {
payload: {},
});
},
+
getVehicleModels(context, { year, make }) {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleModels.method,
@@ -623,6 +662,7 @@ export const actions = {
payload: {},
});
},
+
getVehicleStyles(context, { year, make, model }) {
return globalMethods.callHttpClient({
method: endpoints.GetVehicleStyles.method,
@@ -630,6 +670,7 @@ export const actions = {
payload: {},
});
},
+
setVehicle(context, { year, make, model, style }) {
return globalMethods
.callHttpClient({
@@ -652,6 +693,7 @@ export const actions = {
return response;
});
},
+
getDamageOptions(context, { carId }) {
return globalMethods.callHttpClient({
methods: endpoints.GetDamageOptions.method,
@@ -659,6 +701,7 @@ export const actions = {
payload: {},
});
},
+
validateZip(context, { zip }) {
return globalMethods.callHttpClient({
methods: endpoints.ValidateZip.method,
@@ -673,18 +716,22 @@ export const actions = {
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, null);
context.commit(storeMutations.UPDATE_VAPS, null);
},
+
resetRegistrationAndDependencies(context) {
context.commit(storeMutations.RESET_REGISTRATION_STATE);
context.commit(storeMutations.RESET_GLASS_PARTS_STATE);
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, null);
},
+
resetPartsAndDependencies(context) {
context.commit(storeMutations.RESET_GLASS_PARTS_STATE);
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, null);
},
+
resetState(context) {
context.commit(storeMutations.RESET_STATE);
},
+
resetSaveSessionPromise(context) {
context.commit(storeMutations.RESET_SAVE_SESSION_PROMISE);
},
@@ -699,12 +746,14 @@ export const actions = {
},
});
},
+
getHomepageName(context) {
return globalMethods.callHttpClient({
method: endpoints.GetHomepageInfo.method,
endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION),
});
},
+
getPageData(context, { pageName }) {
return globalMethods.callHttpClient({
method: endpoints.GetPageData.method,
@@ -771,6 +820,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_SAVED_SESSION_ID, savedSessionId);
context.commit(storeMutations.UPDATE_CRM_CUSTOMER_ID, crmCustomerId);
},
+
logPageView(
context,
{
@@ -812,6 +862,7 @@ export const actions = {
}
);
},
+
logCustomEvent(
context,
{
@@ -1116,52 +1167,121 @@ export const actions = {
});
},
- getShopTimeSlots(
- context,
- { startDate = "2023-01-01", endDate = "2023-05-01", shopAppointmentType = "" }
- ) {
+ getShopTimeSlots(context, { startDate, endDate, shopAppointmentType, providerNumber }) {
const order = context.state.order;
- const mockArray = [];
+ const vehicle = context.state.order.vehicle;
+ let partNumbers = [
+ ...(order.lineItems.supportingItems ?? []),
+ ...(order.lineItems.vaps ?? []),
+ ...getFlattenedArrayOfLineItemsWithChildParts(order.lineItems.glassParts),
+ ];
+ partNumbers = partNumbers.map((lineItem) => {
+ return lineItem.partNumber;
+ });
+ const glassPieces = order.damage.glassToReplace
+ ? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
+ : [];
var payload = {
- providerNumber: order.providerNumber,
+ providerNumber: providerNumber,
startDate: startDate,
endDate: endDate,
shopAppointmentType: shopAppointmentType,
applicationName: applicationConfig.APPLICATION_NAME,
parentAccountNumber: context.getters.payment.parentAccountNumber,
- carId: context.getters.vehicle.carId,
- partNumbers: mockArray, // TODO: WHERE DO I GET THIS?
+ carId: vehicle.carId,
+ partNumbers: partNumbers,
+ glassPieces: glassPieces,
eon: order.eon,
- provisionalReasons: mockArray, // TODO: WHERE DO I GET THIS?
+ coverage: {
+ status: "",
+ deductible: 0,
+ additionalAuthFlag: "",
+ },
+ partSelection: {
+ // TODO: Provisional booking will utilize these fields
+ hasAnsweredPartQuestions: false,
+ hasAnsweredMoldingQuestions: false,
+ hasAnsweredCapabilityQuestions: false,
+ hasManuallySelectedParts: false,
+ },
+ vehicle: {
+ year: vehicle.year,
+ make: vehicle.make,
+ model: vehicle.model,
+ style: vehicle.style,
+ vin: vehicle.vin ?? "",
+ },
};
- // TODO: REMOVE MOCK CALL & USE REAL CALL BELOW
- return globalMethods.callMockHttpClient({
+ return globalMethods.callHttpClient({
method: endpoints.GetShopTimeSlots.method,
- endpoint: endpoints.GetShopTimeSlots.mockUrl,
+ endpoint: endpoints.GetShopTimeSlots.url,
payload: payload,
});
- // TODO: RESTORE THIS
- // return globalMethods.callHttpClient({
- // method: endpoints.GetShopTimeSlots.method,
- // endpoint: endpoints.GetShopTimeSlots.url,
- // payload: payload,
- // logApiCall: false,
- // });
},
- getMobileEarlyBirdFee(context) {
+
+ getMobileTimeSlots(context, { startDate, endDate }) {
+ const order = context.state.order;
+ const vehicle = context.state.order.vehicle;
+ let partNumbers = [
+ ...(order.lineItems.supportingItems ?? []),
+ ...(order.lineItems.vaps ?? []),
+ ...getFlattenedArrayOfLineItemsWithChildParts(order.lineItems.glassParts),
+ ];
+ partNumbers = partNumbers.map((lineItem) => {
+ return lineItem.partNumber;
+ });
+ const glassPieces = order.damage.glassToReplace
+ ? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
+ : [];
+ var payload = {
+ startDate: startDate,
+ endDate: endDate,
+ applicationName: applicationConfig.APPLICATION_NAME,
+ parentAccountNumber: context.getters.payment.parentAccountNumber,
+ carId: vehicle.carId,
+ partNumbers: partNumbers,
+ glassPieces: glassPieces,
+ eon: order.eon,
+ coverage: {
+ status: "",
+ deductible: 0,
+ additionalAuthFlag: "",
+ },
+ partSelection: {
+ // TODO: Provisional booking will utilize these fields
+ hasAnsweredPartQuestions: false,
+ hasAnsweredMoldingQuestions: false,
+ hasAnsweredCapabilityQuestions: false,
+ hasManuallySelectedParts: false,
+ },
+ vehicle: {
+ year: vehicle.year,
+ make: vehicle.make,
+ model: vehicle.model,
+ style: vehicle.style,
+ vin: vehicle.vin ?? "",
+ },
+ zipCode: order.serviceLocation.zipCode,
+ };
+ return globalMethods.callHttpClient({
+ method: endpoints.GetMobileTimeSlots.method,
+ endpoint: endpoints.GetMobileTimeSlots.url,
+ payload: payload,
+ });
+ },
+
+ getMobilePremiumFee(context) {
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
const paymentType = context.getters.order.payment.isInsurance ? "Insurance" : "Cash";
- return globalMethods.callMockHttpClient({
- method: endpoints.GetMobileEarlyBirdFee.method,
- endpoint: `${endpoints.GetMobileEarlyBirdFee.mockUrl}/Cash/Replace`,
+
+ return globalMethods.callHttpClient({
+ method: endpoints.GetMobilePremiumFee.method,
+ endpoint: `${endpoints.GetMobilePremiumFee.url}/${paymentType}/${damageType}`,
});
- // return globalMethods.callHttpClient({
- // method: endpoints.GetMobileEarlyBirdFee.method,
- // endpoint: `${endpoints.GetMobileEarlyBirdFee.url}/${paymentType}/${damageType}`,
- // });
},
+
// Session API Actions
saveSession(context) {
const vehicle = context.getters.vehicle;
@@ -1243,6 +1363,7 @@ export const actions = {
city: order.serviceLocation.provider?.address?.city,
state: order.serviceLocation.provider?.address?.state,
zip: order.serviceLocation.provider?.address?.zip,
+ zipCtu: order.serviceLocation.provider?.address?.zipCtu,
},
},
},
@@ -1251,6 +1372,7 @@ export const actions = {
startTime: order.schedule?.startTime,
endTime: order.schedule?.endTime,
routeCode: order.schedule?.routeCode,
+ jobMaxMinutes: order.schedule?.jobMaxMinutes,
},
existingPromoCode: null,
referralCorrelationId: order.referralCorrelationId,
@@ -1262,6 +1384,7 @@ export const actions = {
},
});
},
+
loadSession(
context,
{
@@ -1288,7 +1411,7 @@ export const actions = {
},
})
.then(
- (response) => {
+ async (response) => {
// Flatten location and name properties
response.data.order.damage?.glassToReplace?.map((glass) => {
glass.glassLocation = glass.location;
@@ -1302,10 +1425,13 @@ export const actions = {
if (context.state.order.eon && context.state.order.eon != response.data.eon) {
context.commit(storeMutations.RESET_STATE);
}
+
context.commit(
storeMutations.UPDATE_STATE_WITH_ORDER_INFORMATION,
response.data
);
+
+ await resetScheduleIfUnavailable(context, response.data.order);
return response;
},
(error) => {
@@ -1339,6 +1465,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_YEAR, year);
}
},
+
saveVehicleMake(context, make) {
//Reset dependent state when changing
if (context.state.order.vehicle.make !== make) {
@@ -1359,6 +1486,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_MAKE, make);
}
},
+
saveVehicleModel(context, model) {
//Reset dependent state when changing
if (context.state.order.vehicle.model !== model) {
@@ -1378,6 +1506,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_MODEL, model);
}
},
+
saveVehicleStyle(context, style) {
//Reset dependent state when changing
if (context.state.order.vehicle.style !== style) {
@@ -1396,6 +1525,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_STYLE, style);
}
},
+
saveVehicleDamage(
context,
{ isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }
@@ -1453,6 +1583,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
}
},
+
saveRegistrationLicensePlateLookup(
context,
{ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
@@ -1474,6 +1605,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
}
},
+
saveRegistrationAddressLookup(
context,
{ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
@@ -1499,6 +1631,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
}
},
+
savePartQuestionAnswers(context, partQuestionAnswersArray) {
// if part question answers have changed, reset subsequent question answers
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
@@ -1537,6 +1670,7 @@ export const actions = {
//Save new values
context.commit(storeMutations.UPDATE_PART_QUESTION_ANSWERS, partQuestionAnswersArray);
},
+
resetMoldingAndCapabilityQuestionAnswersIfNeeded(context, matchedParts) {
const partsOrQuestionsDataToCompareWith =
context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS)?.partsOrQuestions ??
@@ -1576,6 +1710,7 @@ export const actions = {
});
}
},
+
saveMoldingQuestionAnswers(context, moldingQuestionAnswers) {
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
context.getters.damage.moldingQuestionAnswers,
@@ -1604,6 +1739,7 @@ export const actions = {
//Save new values
context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, moldingQuestionAnswers);
},
+
saveCapabilityQuestionAnswers(context, capabilityQuestionAnswers) {
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
context.getters.damage.capabilityQuestionAnswers,
@@ -1630,18 +1766,32 @@ export const actions = {
capabilityQuestionAnswers
);
},
+
savePaymentType(context, isInsurance) {
context.commit(storeMutations.UPDATE_IS_INSURANCE, isInsurance);
},
+
saveParentAccountNumber(context, parentAccountNumber) {
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccountNumber);
},
+
saveSupportingItems(context, supportingItems) {
+ if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_APPOINTMENT_TYPE);
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_PROVIDER);
+ }
+
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
},
+
+ saveSupportingItemsSuppressingStateResetting(context, supportingItems) {
+ context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
+ },
+
saveVaps(context, vaps) {
context.commit(storeMutations.UPDATE_VAPS, vaps);
},
+
// Price order actions
async priceOrderItemsAndSaveServerData(
context,
@@ -1678,7 +1828,6 @@ export const actions = {
`&${availableLineItemsFormattedForRequest}`;
const lineItemServerData = context.getters.order.lineItems.serverData;
-
if (lineItemServerData) {
queryString += `&ServerData=${encodeURIComponent(lineItemServerData)}`;
}
@@ -1694,16 +1843,33 @@ export const actions = {
return availableLineItems;
},
+
// Misc order actions
saveSchedule(context, scheduleInfo) {
context.commit(storeMutations.UPDATE_SCHEDULE, scheduleInfo);
},
+
+ saveServiceZipCodeInfo(context, serviceZipCodeInfo) {
+ if (
+ context.state.order.serviceLocation &&
+ serviceZipCodeInfo.zipCode !== context.state.order.serviceLocation.zipCode
+ ) {
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_APPOINTMENT_TYPE);
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_PROVIDER);
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_MOBILE_ADDRESS);
+ }
+
+ context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceZipCodeInfo);
+ },
+
saveServiceLocation(context, serviceLocationInfo) {
context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocationInfo);
},
+
saveEmail(context, email) {
context.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, email);
},
+
saveVin(context, { isSelectedGlassAvailableForVehicle, vehicleInfo }) {
//Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
@@ -1716,12 +1882,24 @@ export const actions = {
context.commit(storeMutations.UPDATE_VEHICLE, vehicleInfo);
}
},
+
saveGlassParts(context, parts) {
+ if (!deepEqual(parts, context.state.order.lineItems.glassParts)) {
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_APPOINTMENT_TYPE);
+ context.commit(storeMutations.RESET_SERVICE_LOCATION_PROVIDER);
+ }
+
context.commit(storeMutations.UPDATE_GLASS_PARTS, parts);
},
+
+ saveGlassPartPrices(context, parts) {
+ context.commit(storeMutations.UPDATE_GLASS_PARTS, parts);
+ },
+
clearVin(context) {
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
},
+
isVinOptionalVehicle(context) {
switch (context.state.order.vehicle.make.toLowerCase()) {
case "mercedes benz":
@@ -1863,7 +2041,7 @@ function addPricesToLineItems(lineItems, pricingLineItems) {
function getFlattenedArrayOfLineItemsWithChildParts(lineItems) {
let flattenedArray = [];
- lineItems.forEach((lineItem) => {
+ lineItems?.forEach((lineItem) => {
flattenedArray.push(lineItem);
if (lineItem.childParts) {
flattenedArray = [
@@ -1885,3 +2063,126 @@ function buildQueryStringParameterFromArrayOfComplexObjects(arrayOfObjects, para
// Remove trailing &
return queryStringParameter.slice(0, -1);
}
+
+function convertGlassPieceToBackEndCompatibleFormat(glassPieces) {
+ return glassPieces.map((glassPiece) => {
+ return {
+ location: glassPiece.glassLocation,
+ name: glassPiece.glassName,
+ };
+ });
+}
+
+// This function will verify schedule info is still valid.
+// check to see if we have an appointment date on the order object.
+// if so, make sure it's not in the past. if in the past, clear schedule info in store.
+// if date not in past, then call schedule service to verify appointment is still available.
+async function resetScheduleIfUnavailable(context, order) {
+ if (!order.schedule?.date) {
+ return;
+ }
+
+ // Date string with slashes is parsed as local time, not UTC. Our date has dashes, '-'.
+ // If you put any kind of time stamp on the date string with dashes, then it IS parsed as local time.
+ var aptDate = new Date(order.schedule.date + "T00:00:00");
+ var curDate = new Date();
+
+ // if appointment date is in the past, clear schedule
+ if (aptDate.getTime() < curDate.getTime()) {
+ context.commit(storeMutations.RESET_SCHEDULE);
+ return;
+ }
+
+ // create date range to pass to the schedule service to see if our appointment is still available.
+ var endRange = new Date(aptDate);
+ endRange.setDate(aptDate.getDate() + 1);
+
+ var endDay = "" + endRange.getDate();
+ var endMonth = "" + (endRange.getMonth() + 1); // 0 based so add 1
+ const endYear = endRange.getFullYear();
+
+ if (endMonth.length < 2) {
+ endMonth = "0" + endMonth;
+ }
+ if (endDay.length < 2) {
+ endDay = "0" + endDay;
+ }
+
+ const endDate = [endYear, endMonth, endDay].join("-");
+
+ let newTimeSlotsResponse;
+ if (order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE) {
+ newTimeSlotsResponse = await context.dispatch(
+ storeActions.GET_MOBILE_TIME_SLOTS,
+ {
+ startDate: order.schedule.date,
+ endDate: endDate,
+ },
+ false
+ );
+
+ if (newTimeSlotsResponse?.data.days?.length === 0) {
+ context.commit(storeMutations.RESET_SCHEDULE);
+ return;
+ }
+
+ var mobileRouteCodeFound = false;
+ // if early bird fee is in supporting items then need to check the timeslot to see if offer premium is also still available
+ if (
+ order.lineItem?.supportingItems?.findIndex(
+ (item) => item.partType == PREMIUM_FEE_PART_TYPE
+ )
+ ) {
+ newTimeSlotsResponse.data.days?.forEach((day) => {
+ day.timeSlots.forEach((ts) => {
+ if (ts.id === order.schedule.routeCode && ts.offerPremium) {
+ mobileRouteCodeFound = true;
+ }
+ });
+ });
+ } else {
+ newTimeSlotsResponse.data.days?.forEach((day) => {
+ day.timeSlots.forEach((ts) => {
+ if (ts.id === order.schedule.routeCode) {
+ mobileRouteCodeFound = true;
+ }
+ });
+ });
+ }
+
+ if (!mobileRouteCodeFound) {
+ context.commit(storeMutations.RESET_SCHEDULE);
+ return;
+ }
+ } else {
+ newTimeSlotsResponse = await context.dispatch(
+ storeActions.GET_SHOP_TIME_SLOTS,
+ {
+ startDate: order.schedule.date,
+ endDate: endDate,
+ shopAppointmentType: order.serviceLocation.appointmentType,
+ providerNumber: order.serviceLocation.provider.providerNumber,
+ },
+ false
+ );
+
+ if (newTimeSlotsResponse?.data.days?.length === 0) {
+ context.commit(storeMutations.RESET_SCHEDULE);
+ return;
+ }
+
+ var routeCodeFound = false;
+ newTimeSlotsResponse.data.days?.forEach((day) => {
+ day.timeSlots.forEach((ts) => {
+ if (ts.id === order.schedule.routeCode) {
+ routeCodeFound = true;
+ }
+ });
+ });
+
+ if (!routeCodeFound) {
+ context.commit(storeMutations.RESET_SCHEDULE);
+ return;
+ }
+ }
+}
diff --git a/src/store/store.spec.js b/src/store/store.spec.js
index 6913c0527..262cb263a 100644
--- a/src/store/store.spec.js
+++ b/src/store/store.spec.js
@@ -961,7 +961,10 @@ describe("Actions", () => {
it("saveGlassParts, should call mutation", () => {
// Arrange
- const context = state;
+ const context = {
+ state: state,
+ };
+
const commit = jest.fn();
context.commit = commit;
diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss
index 73845e5cc..f8e1c50f1 100644
--- a/src/styles/common-styles.scss
+++ b/src/styles/common-styles.scss
@@ -56,3 +56,9 @@ body {
height: calc(100% - 72px);
}
}
+//Disable scroll of main container when modal is open
+.modal-open {
+ .page-container-grouped-styles {
+ overflow: hidden;
+ }
+}
diff --git a/src/styles/shared-input-button-styles.scss b/src/styles/shared-input-button-styles.scss
index 9af066bb0..07329fc71 100644
--- a/src/styles/shared-input-button-styles.scss
+++ b/src/styles/shared-input-button-styles.scss
@@ -9,6 +9,7 @@
position: relative;
z-index: 5;
@include box-shadow-hover($blue-300);
+ border-radius: 0.5rem;
}
}
}
diff --git a/src/styles/ux-variables.scss b/src/styles/ux-variables.scss
index 1e95a4052..976e8ed04 100644
--- a/src/styles/ux-variables.scss
+++ b/src/styles/ux-variables.scss
@@ -190,3 +190,6 @@ $alert-color-scale: 40%;
// This affects all [Bootstrap] modals
$modal-fade-transform: translate(0, 100%);
$modal-backdrop-opacity: 0;
+
+//Disable default !important behavior
+$enable-important-utilities: false;
diff --git a/src/ux-components/alert/alert.spec.js b/src/ux-components/alert/alert.spec.js
index 1f5d0fcc8..9d8112189 100644
--- a/src/ux-components/alert/alert.spec.js
+++ b/src/ux-components/alert/alert.spec.js
@@ -15,7 +15,6 @@ describe("alert.vue", () => {
},
})
);
-
const wrapperDiv = wrapper.find("div");
// Assert
@@ -49,7 +48,7 @@ describe("alert.vue", () => {
expect(wrapper.vm.alertCopy).toBe("testCopy");
});
- it("Should container a
tag if the manualCopy contains a {routerLink: testName, testLink} placeholder", () => {
+ it("Should container a tag if the manualCopy contains a {routerLink: testName, testLink} placeholder", () => {
// Arrange & Act
const wrapper = shallowMount(
alert,
@@ -58,11 +57,12 @@ describe("alert.vue", () => {
manualHeadline: "testHeader",
manualCopy: "testCopy with a {routerLink: testName, testLink} inside of it",
},
- stubs: ["router-link"],
+ stubs: ["textBlock"],
})
);
+
// Assert
- expect(wrapper.find("router-link").exists()).toBe(true);
+ expect(wrapper.html()).toEqual(expect.stringContaining("text-block-stub"));
});
it("Should contain 'n+1' tags if the body copy has 'n'
tags", () => {
diff --git a/src/ux-components/alert/alert.vue b/src/ux-components/alert/alert.vue
index c5899b440..c7e4aca30 100644
--- a/src/ux-components/alert/alert.vue
+++ b/src/ux-components/alert/alert.vue
@@ -14,17 +14,11 @@
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
v-html="paragraph">
-
-
- {{ getRouterLinkDisplayTextFromCopy(copy) }}
-
-
+
+
+
+
+
diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue
index 7755249ab..ee8785022 100644
--- a/src/ux-components/list-card/list-card.vue
+++ b/src/ux-components/list-card/list-card.vue
@@ -94,7 +94,7 @@ export default {
+ .list-card-content {
outline: none;
- display: block;
+ display: flex;
position: relative;
p {
diff --git a/src/ux-components/loader/loader.vue b/src/ux-components/loader/loader.vue
index daea9c511..0635614b8 100644
--- a/src/ux-components/loader/loader.vue
+++ b/src/ux-components/loader/loader.vue
@@ -3,7 +3,7 @@
class="loader"
role="alert"
aria-label="Loading new page"
- v-bind:class="[this.loaderColor, this.loaderPosition]">
+ v-bind:class="[this.loaderColor, this.loaderPosition, this.blockUi]">