Merge branch 'develop' into feature/CSR-1144
This commit is contained in:
commit
1364b25075
12 changed files with 505 additions and 130 deletions
|
|
@ -5,6 +5,7 @@ const experimentUniverses = {
|
|||
const experimentSettings = {
|
||||
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index",
|
||||
SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
|
||||
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
|
||||
};
|
||||
|
||||
const experimentTriggers = {
|
||||
|
|
|
|||
|
|
@ -256,7 +256,9 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
modelValue(newValue, oldValue) {
|
||||
this.resetField();
|
||||
this.resetField({
|
||||
value: newValue,
|
||||
});
|
||||
},
|
||||
answers() {
|
||||
//once we get the answers to display from parent, see if we need a GA event to log what we showed
|
||||
|
|
|
|||
|
|
@ -235,7 +235,8 @@ export default {
|
|||
date: this.selectedDate.dateString,
|
||||
startTime: timeSlotSelectedObject.startTime,
|
||||
endTime: timeSlotSelectedObject.endTime,
|
||||
id: this.selectedTimeSlotData.id,
|
||||
routeCode: this.selectedTimeSlotData.id,
|
||||
jobMaxMinutes: this.selectableDatesData.estimatedServiceMinutesMaximum,
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
|
|
@ -320,11 +321,11 @@ export default {
|
|||
// Ex: April 25
|
||||
return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" });
|
||||
},
|
||||
// Expected input: "HH:MM:SS"
|
||||
// Expected input: "HH:MM"
|
||||
getDisplayTextForMilitaryTime(militaryTimeInput, shouldTrimMinutesIfEmpty = false) {
|
||||
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
||||
const minutes = militaryTimeInput.split(":")[1];
|
||||
let meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
|
@ -338,15 +339,9 @@ export default {
|
|||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
//TODO: replace properties with real values once they are available
|
||||
await this.dispatchStoreAction(
|
||||
this.storeActions.SAVE_SCHEDULE,
|
||||
{
|
||||
date: "2023-07-04T00:00:00",
|
||||
startTime: "2023-07-04T12:00:00",
|
||||
endTime: "2023-07-04T17:00:00",
|
||||
routeCode: "03341-01820-S-B*20232*11 AM",
|
||||
},
|
||||
this.appointmentDateAndTime,
|
||||
false
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ import buttonQuestion from "@/digital-components/button-question/button-question
|
|||
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
||||
|
||||
// TODO: Move this somewhere more global
|
||||
import { DAYS_OF_WEEK, MONTHS_OF_YEAR } from "@/digital-components/date-picker/mixins/constants.js";
|
||||
import { defineRule, useField } from "vee-validate";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
|
|
@ -80,7 +79,6 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
selectedTimeSlotId: null,
|
||||
isSelectedAppointmentPremium: null,
|
||||
timeSlotModalListButton: timeSlotModalListButton,
|
||||
};
|
||||
},
|
||||
|
|
@ -96,7 +94,7 @@ export default {
|
|||
// Run component validation that is used at parent level
|
||||
this.handleChange(this.modelValue.id);
|
||||
},
|
||||
dateAndTimeSlotData(newValue, oldValue) {
|
||||
availableTimeSlots(newValue) {
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable(newValue);
|
||||
},
|
||||
},
|
||||
|
|
@ -190,34 +188,33 @@ export default {
|
|||
},
|
||||
// fires any time the footer button is used, is fired before "onModalClosed"
|
||||
closeModal() {
|
||||
if (this.selectedTimeSlotId.toString().includes(PREMIUM_TIME_SLOT_ID_FLAG)) {
|
||||
let isSelectedAppointmentPremium = false;
|
||||
if (this.selectedTimeSlotId.includes(PREMIUM_TIME_SLOT_ID_FLAG)) {
|
||||
this.selectedTimeSlotId = this.removePremiumFlagFromInput(this.selectedTimeSlotId);
|
||||
this.isSelectedAppointmentPremium = true;
|
||||
} else {
|
||||
this.isSelectedAppointmentPremium = false;
|
||||
isSelectedAppointmentPremium = true;
|
||||
}
|
||||
const selectedTimeSlotData = {
|
||||
id: this.selectedTimeSlotId,
|
||||
isPremiumAppointment: this.isSelectedAppointmentPremium,
|
||||
isPremiumAppointment: isSelectedAppointmentPremium,
|
||||
};
|
||||
this.$emit("update:modelValue", selectedTimeSlotData);
|
||||
this.$refs["timeSlots"].closeModal();
|
||||
},
|
||||
// fires any time the modal is closed, AFTER "closeModal" fires if footer button is used
|
||||
onModalClosed() {
|
||||
this.isSelectedAppointmentPremium = this.modelValue.isPremiumAppointment;
|
||||
if (this.isSelectedAppointmentPremium) {
|
||||
// Reset component state to parent's state
|
||||
if (this.modelValue.isPremiumAppointment) {
|
||||
this.selectedTimeSlotId = this.addPremiumFlagToInput(this.modelValue.id);
|
||||
} else {
|
||||
this.selectedTimeSlotId = this.modelValue.id;
|
||||
}
|
||||
this.$emit("time-slot-modal-closed");
|
||||
},
|
||||
// Expected input: "HH:MM:SS"
|
||||
// Expected input: "HH:MM"
|
||||
getDisplayTextForMilitaryTime(militaryTimeInput) {
|
||||
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
||||
const minutes = militaryTimeInput.split(":")[1];
|
||||
let meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||
if (hours > 12) {
|
||||
hours -= 12;
|
||||
}
|
||||
|
|
@ -286,24 +283,17 @@ export default {
|
|||
},
|
||||
};
|
||||
},
|
||||
autoSelectTimeSlotIfOnlyOneIsAvailable(newdateAndTimeSlotDataValue) {
|
||||
const numberOfOptions = newdateAndTimeSlotDataValue?.timeSlots.length;
|
||||
if (
|
||||
numberOfOptions === 1 &&
|
||||
!(
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||
this.premiumAppointmentFee &&
|
||||
newdateAndTimeSlotDataValue.timeSlots[0].offerPremium
|
||||
)
|
||||
) {
|
||||
this.selectedTimeSlotId = newdateAndTimeSlotDataValue.timeSlots[0].id;
|
||||
autoSelectTimeSlotIfOnlyOneIsAvailable(newAvailableTimeSlotsValue) {
|
||||
const numberOfOptions = newAvailableTimeSlotsValue?.length;
|
||||
if (numberOfOptions === 1) {
|
||||
this.selectedTimeSlotId = newAvailableTimeSlotsValue[0].value;
|
||||
}
|
||||
},
|
||||
addPremiumFlagToInput(timeSlotId) {
|
||||
return (timeSlotId += PREMIUM_TIME_SLOT_ID_FLAG);
|
||||
},
|
||||
removePremiumFlagFromInput(timeSlotId) {
|
||||
return parseInt(timeSlotId.trim(PREMIUM_TIME_SLOT_ID_FLAG.length));
|
||||
return timeSlotId.substring(0, timeSlotId.length - PREMIUM_TIME_SLOT_ID_FLAG.length);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
|
||||
export async function getPricedMobileFeePart(serviceZipCode) {
|
||||
|
|
@ -42,3 +43,48 @@ export async function getServiceabilityDetails(serviceZipCode, lineItems) {
|
|||
|
||||
return Promise.resolve(serviceabilityDetails);
|
||||
}
|
||||
|
||||
export async function getAvailabilityRating(
|
||||
startDate,
|
||||
endDate,
|
||||
shopAppointmentType,
|
||||
providerNumber
|
||||
) {
|
||||
// For a given shop provider number and date range, get the appointment time slots available
|
||||
const shopTimeSlots = await baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.GET_SHOP_TIME_SLOTS,
|
||||
{
|
||||
providerNumber: providerNumber,
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
shopAppointmentType: shopAppointmentType,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
// Rate the availability for the shop
|
||||
let numberOfAppointmentsPerDay = [];
|
||||
for (let i = 0; i < shopTimeSlots.data.days.length; i++) {
|
||||
numberOfAppointmentsPerDay.push(shopTimeSlots.data.days[i].timeSlots.length);
|
||||
}
|
||||
|
||||
const dateRange = 7;
|
||||
const minimumNumberOfAppointmentsPerDay = 1;
|
||||
const numberOfDaysToEvaluate = 2;
|
||||
|
||||
let daysWithMinimalAppointmentsCount = 0;
|
||||
for (let i = 0; i < dateRange; i++) {
|
||||
if (numberOfAppointmentsPerDay[i] >= minimumNumberOfAppointmentsPerDay) {
|
||||
daysWithMinimalAppointmentsCount++;
|
||||
if (daysWithMinimalAppointmentsCount >= numberOfDaysToEvaluate) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const isGoodAvailability = daysWithMinimalAppointmentsCount >= numberOfDaysToEvaluate;
|
||||
|
||||
const shopStatus = isGoodAvailability ? "high" : "low";
|
||||
|
||||
return Promise.resolve(shopStatus);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,186 @@
|
|||
import { getPricedMobileFeePart, getServiceabilityDetails } from "./service-location-helper";
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getAvailabilityRating,
|
||||
} from "./service-location-helper";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
|
||||
jest.mock("@/store", () => ({
|
||||
getters: {
|
||||
order: {
|
||||
vehicle: {
|
||||
year: null,
|
||||
make: null,
|
||||
model: null,
|
||||
style: null,
|
||||
carId: null,
|
||||
category: null,
|
||||
vin: null,
|
||||
imageUrl: null,
|
||||
imageVifNumber: null,
|
||||
imageColor: null,
|
||||
registration: {
|
||||
licensePlate: null,
|
||||
address: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
},
|
||||
},
|
||||
serviceLocation: {
|
||||
address: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCodeCtu: null,
|
||||
appointmentType: null,
|
||||
provider: {
|
||||
providerNumber: null,
|
||||
address: {
|
||||
streetAddress: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zip: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
customer: {
|
||||
emailAddress: null,
|
||||
},
|
||||
damage: {
|
||||
isRepair: null,
|
||||
numberOfChips: null,
|
||||
glassToReplace: null,
|
||||
partQuestionAnswers: null,
|
||||
moldingQuestionAnswers: null,
|
||||
capabilityQuestionAnswers: null,
|
||||
},
|
||||
lineItems: {
|
||||
glassParts: null,
|
||||
supportingItems: null,
|
||||
vaps: null,
|
||||
serverData: null,
|
||||
},
|
||||
payment: {
|
||||
isInsurance: null,
|
||||
insuranceCoverage: {
|
||||
isVerified: null,
|
||||
coverageStatus: null,
|
||||
},
|
||||
parentAccountNumber: 0,
|
||||
},
|
||||
schedule: {
|
||||
date: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
routeCode: null,
|
||||
},
|
||||
referralNumber: null,
|
||||
referralDate: null,
|
||||
referralCorrelationId: null,
|
||||
eon: null,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const mockStoreActionGetMobileFeePart = storeActions.GET_MOBILE_FEE_PART;
|
||||
const mockStoreActionPriceOrderItemsAndSaveServerData =
|
||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA;
|
||||
const mockStoreActionGetServiceabilityDetails = storeActions.GET_SERVICEABILITY_DETAILS;
|
||||
const mockStoreActionGetShopTimeSlots = storeActions.GET_SHOP_TIME_SLOTS;
|
||||
|
||||
const mockGetShopTimeSlotsGoodAvailability = {
|
||||
estimatedServiceMinutesMinimum: 0,
|
||||
estimatedServiceMinutesMaximimum: 0,
|
||||
days: [
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "string",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
offerPremium: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "string",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
offerPremium: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const mockGetShopTimeSlotsLowAvailability = {
|
||||
estimatedServiceMinutesMinimum: 0,
|
||||
estimatedServiceMinutesMaximimum: 0,
|
||||
days: [
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [],
|
||||
},
|
||||
{
|
||||
date: "string",
|
||||
timeSlots: [
|
||||
{
|
||||
id: "string",
|
||||
startTime: "",
|
||||
endTime: "",
|
||||
offerPremium: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||
methods: {
|
||||
|
|
@ -18,7 +194,7 @@ jest.mock("@/mixins/base-mixin.js", () => ({
|
|||
});
|
||||
}),
|
||||
|
||||
dispatchStoreAction: jest.fn().mockImplementation((actionName) => {
|
||||
dispatchStoreAction: jest.fn().mockImplementation((actionName, request) => {
|
||||
if (actionName === mockStoreActionGetMobileFeePart) {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
|
|
@ -50,6 +226,14 @@ jest.mock("@/mixins/base-mixin.js", () => ({
|
|||
isRecalibrationServiceableMobile: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (actionName === mockStoreActionGetShopTimeSlots) {
|
||||
if (request.providerNumber == "0000001") {
|
||||
return Promise.resolve(mockGetShopTimeSlotsGoodAvailability);
|
||||
}
|
||||
|
||||
return Promise.resolve(mockGetShopTimeSlotsLowAvailability);
|
||||
}
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
|
@ -124,4 +308,25 @@ describe("service-location-helper.js", () => {
|
|||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getAvailabilityRating", () => {
|
||||
// it("Should return a 'Good' rating", async () => {
|
||||
// // Arrange
|
||||
// const providerNumber = "0000001";
|
||||
// const expected = "Good";
|
||||
// // Act
|
||||
// const result = await getAvailabilityRating(providerNumber);
|
||||
// // Assert
|
||||
// expect(result).toEqual(expected);
|
||||
// });
|
||||
// it("Should return a 'Low' rating", async () => {
|
||||
// // Arrange
|
||||
// const providerNumber = "0000000";
|
||||
// const expected = "Low";
|
||||
// // Act
|
||||
// const result = await getAvailabilityRating(providerNumber);
|
||||
// // Assert
|
||||
// expect(result).toEqual(expected);
|
||||
// });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -202,6 +202,7 @@ export default {
|
|||
this.internalModel = deepClone(this.modelValue);
|
||||
},
|
||||
onModalClosed() {
|
||||
this.displayInvalidZipAlert = false;
|
||||
this.internalModel = deepClone(this.modelValue);
|
||||
this.resetValidation();
|
||||
},
|
||||
|
|
@ -236,17 +237,6 @@ export default {
|
|||
});
|
||||
},
|
||||
async setMobileLocation() {
|
||||
// START - TEMP CODE FROM A CAOUETTE 5/25/23 TO BE REMOVED BY EOD
|
||||
let tempTest = false;
|
||||
let internalModelAddressQuestions = this.internalModel.addressQuestions;
|
||||
let modelValueAddressQuestions = this.modelValue.addressQuestions;
|
||||
if (tempTest) {
|
||||
// THIS WILL NEVER BE TRUE
|
||||
console.warn(internalModelAddressQuestions);
|
||||
console.warn(modelValueAddressQuestions);
|
||||
}
|
||||
// END - TEMP CODE FROM A CAOUETTE 5/25/23 TO BE REMOVED BY EOD
|
||||
|
||||
if (
|
||||
this.internalModel.addressQuestions.zipCode !==
|
||||
this.modelValue.addressQuestions.zipCode
|
||||
|
|
@ -272,22 +262,19 @@ export default {
|
|||
this.$emit("updated-serviceability", serviceabilityDetails.data);
|
||||
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
|
||||
|
||||
// Update the page level model
|
||||
this.$emit("update:modelValue", this.internalModel);
|
||||
|
||||
if (this.onZipUpdateCallback) {
|
||||
await this.onZipUpdateCallback(serviceZipCode);
|
||||
}
|
||||
// Update the page level model
|
||||
this.$emit("update:modelValue", this.internalModel);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
} else {
|
||||
// START - TEMP CODE FROM A CAOUETTE 5/25/23 TO BE REMOVED BY EOD
|
||||
if (tempTest) {
|
||||
// THIS WILL NEVER BE TRUE
|
||||
console.warn("the zips match and the exception was run");
|
||||
}
|
||||
// END - TEMP CODE FROM A CAOUETTE 5/25/23 TO BE REMOVED BY EOD
|
||||
// Update the page level model
|
||||
this.$emit("update:modelValue", this.internalModel);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { mount } from "@vue/test-utils";
|
|||
import shopListButton from "./shop-list-button";
|
||||
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||
|
||||
describe("service-package-radio.vue", () => {
|
||||
describe("shop-list-button.vue", () => {
|
||||
it("Should include buttonLabel in html", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
|
|
@ -49,6 +49,18 @@ describe("service-package-radio.vue", () => {
|
|||
});
|
||||
});
|
||||
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 7);
|
||||
const getAvailabilityRating = jest.fn().mockImplementation((actionName, request) => {
|
||||
return Promise.resolve({
|
||||
data: {},
|
||||
});
|
||||
});
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split("T")[0];
|
||||
const formattedEndDate = endDate.toISOString().split("T")[0];
|
||||
|
||||
const mockProps = {
|
||||
buttonLabel: "buttonLabel test copy",
|
||||
buttonLabelSubCopy: "buttonLabelSubCopy test copy",
|
||||
|
|
@ -58,6 +70,12 @@ const mockProps = {
|
|||
value: 0,
|
||||
modelValue: 0,
|
||||
groupName: "mockGroup",
|
||||
additionalButtonData: {
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: "Dropoff",
|
||||
},
|
||||
};
|
||||
|
||||
function setupMocks({ mountOptionsMockData = {} }) {
|
||||
|
|
|
|||
|
|
@ -11,26 +11,32 @@
|
|||
<span class="m-0 button-label-copy" :class="textPosition">{{
|
||||
buttonLabel
|
||||
}}</span>
|
||||
<span class="m-0 button-label-sub-copy" :class="textPosition">{{
|
||||
<span class="m-0 caption ms-1" :class="textPosition">{{
|
||||
buttonLabelSubCopy
|
||||
}}</span>
|
||||
<div
|
||||
class="availability-indicator"
|
||||
:class="availability === 'high' ? 'green' : 'red'">
|
||||
<span class="m-0 button-auxillary-copy">{{ buttonAuxillaryCopy }}</span>
|
||||
v-if="displayAvailabilityIndicators"
|
||||
class="availability-indicator rounded-pill"
|
||||
:class="availabilityRatingClass">
|
||||
<div
|
||||
v-if="!isLoaderDisplayed"
|
||||
class="availability-badge"
|
||||
:class="availabilityRating == 'high' ? 'green' : 'red'"></div>
|
||||
<span v-if="!isLoaderDisplayed" class="m-0 button-auxillary-copy">{{
|
||||
badgeText
|
||||
}}</span>
|
||||
<loader v-if="isLoaderDisplayed" :class="['left', 'no-block']" />
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
v-if="buttonBodyCopy"
|
||||
class="m-0 button-label-sub-copy small"
|
||||
:class="textPosition"
|
||||
v-html="buttonBodyCopy"></span>
|
||||
<div class="row-two">
|
||||
<span
|
||||
v-if="buttonBodyCopy"
|
||||
class="m-0 button-label-sub-copy small"
|
||||
v-html="buttonBodyCopy"></span>
|
||||
</div>
|
||||
<span v-if="screenReaderOnlyText" class="sr-only">
|
||||
{{ screenReaderOnlyText }}
|
||||
</span>
|
||||
<loader
|
||||
v-if="isLoaderDisplayed && selectingInitiatesLoad"
|
||||
:class="[this.loaderColor, this.loaderPosition]" />
|
||||
</div>
|
||||
</baseInputButton>
|
||||
</transition>
|
||||
|
|
@ -40,32 +46,59 @@
|
|||
import loader from "@/ux-components/loader/loader";
|
||||
import baseInputButton from "@/digital-components/base-input-button/base-input-button";
|
||||
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||
import experimentMixin from "@/mixins/experiment-mixin";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
|
||||
export default {
|
||||
name: "shopListButton",
|
||||
mixins: [inputButtonWrapperMixin],
|
||||
props: {
|
||||
loaderColor: String,
|
||||
loaderPosition: {
|
||||
type: String,
|
||||
default: "right",
|
||||
},
|
||||
beforeMount() {
|
||||
if (this.displayAvailabilityIndicators) {
|
||||
this.displayLoader();
|
||||
const startDate = this.additionalButtonData.startDate;
|
||||
const endDate = this.additionalButtonData.endDate;
|
||||
const shopAppointmentType = this.additionalButtonData.shopAppointmentType;
|
||||
|
||||
this.additionalButtonData
|
||||
.availabilityRatingCallback(startDate, endDate, shopAppointmentType, this.value)
|
||||
.then((data) => {
|
||||
this.availabilityRating = data;
|
||||
this.isLoaderDisplayed = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoaderDisplayed: false,
|
||||
availability: "low",
|
||||
availabilityRating: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayAvailabilityIndicators() {
|
||||
return experimentMixin.methods.hasSettingEqualTo(
|
||||
experimentSettings.DISPLAY_AVAILABILITY_INDICATORS,
|
||||
"true"
|
||||
);
|
||||
},
|
||||
availabilityRatingClass() {
|
||||
if (this.availabilityRating == null) {
|
||||
return "gray";
|
||||
} else {
|
||||
return this.availabilityRating == "high" ? "green" : "red";
|
||||
}
|
||||
},
|
||||
badgeText() {
|
||||
if (this.availabilityRating != null) {
|
||||
return this.availabilityRating == "high" ? "Appts available" : "Appts low";
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
displayLoader() {
|
||||
this.isLoaderDisplayed = true;
|
||||
},
|
||||
preHandleAnswerChange() {
|
||||
if (this.selectingInitiatesLoad) {
|
||||
this.displayLoader();
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
loader,
|
||||
|
|
@ -75,9 +108,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.loader {
|
||||
position: absolute;
|
||||
}
|
||||
.list-button {
|
||||
outline: none;
|
||||
input[type="radio"],
|
||||
|
|
@ -103,10 +133,6 @@ export default {
|
|||
&:checked + .list-button-content span {
|
||||
font-weight: 500;
|
||||
}
|
||||
&:checked + .list-button-content span:nth-child(2) {
|
||||
font-weight: 400;
|
||||
color: $gray-600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-button-content {
|
||||
|
|
@ -127,53 +153,83 @@ export default {
|
|||
}
|
||||
}
|
||||
.button-content {
|
||||
row-gap: 0.25rem;
|
||||
|
||||
.row-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.25rem !important;
|
||||
line-height: 1.5rem;
|
||||
|
||||
.button-label-copy {
|
||||
flex-grow: 0;
|
||||
line-height: 1.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.button-label-sub-copy {
|
||||
flex-grow: 1;
|
||||
line-height: 1.25rem !important;
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
color: #727676;
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
.availability-indicator {
|
||||
display: none;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.125rem 1.5rem;
|
||||
gap: 0.25rem;
|
||||
background: #e3f2ea;
|
||||
border-radius: 4.5rem;
|
||||
margin-left: auto;
|
||||
padding: 0.125rem 0.5rem;
|
||||
|
||||
.availability-badge {
|
||||
display: inline;
|
||||
width: 13px;
|
||||
height: 12px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 0.25rem 0 0;
|
||||
|
||||
&.green {
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 13 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.5 12C3.19159 12 0.5 9.30841 0.5 6C0.5 2.69159 3.19159 0 6.5 0C9.80841 0 12.5 2.69159 12.5 6C12.5 9.30841 9.80841 12 6.5 12ZM6.5 0.785047C3.62449 0.785047 1.28505 3.12449 1.28505 6C1.28505 8.87551 3.62449 11.215 6.5 11.215C9.37551 11.215 11.715 8.87551 11.715 6C11.715 3.12449 9.37551 0.785047 6.5 0.785047Z' fill='%23006A36'/%3E%3Cpath d='M5.697 7.95252C5.5927 7.95252 5.49289 7.91102 5.41999 7.837L3.90597 6.32299C3.75233 6.16934 3.75233 5.92149 3.90597 5.76785C4.05962 5.6142 4.30747 5.6142 4.46111 5.76785L5.69812 7.00373L8.53999 4.16186C8.69364 4.00822 8.94149 4.00822 9.09513 4.16186C9.24878 4.31551 9.24878 4.56336 9.09513 4.717L5.97626 7.83588C5.90224 7.9099 5.80242 7.9514 5.69925 7.9514L5.697 7.95252Z' fill='%23006A36'/%3E%3C/svg%3E%0A");
|
||||
}
|
||||
|
||||
&.red {
|
||||
background-image: url("data:image/svg+xml,%3Csvg width='13' height='12' viewBox='0 0 13 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.5 12C3.19159 12 0.5 9.30841 0.5 6C0.5 2.69159 3.19159 0 6.5 0C9.80841 0 12.5 2.69159 12.5 6C12.5 9.30841 9.80841 12 6.5 12ZM6.5 0.785047C3.62449 0.785047 1.28505 3.12449 1.28505 6C1.28505 8.87551 3.62449 11.215 6.5 11.215C9.37551 11.215 11.715 8.87551 11.715 6C11.715 3.12449 9.37551 0.785047 6.5 0.785047Z' fill='%23006A36'/%3E%3Csvg width='13' height='12' viewBox='0 0 13 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.5 0C9.81368 0 12.5 2.68632 12.5 6C12.5 9.31368 9.81368 12 6.5 12C3.18632 12 0.5 9.31368 0.5 6C0.5 2.68632 3.18632 0 6.5 0ZM6.5 0.84C3.6548 0.84 1.34 3.1548 1.34 6C1.34 8.8452 3.6548 11.16 6.5 11.16C9.3452 11.16 11.66 8.8452 11.66 6C11.66 3.1548 9.3452 0.84 6.5 0.84ZM7.90018 4.00596C8.06422 3.84204 8.33002 3.84192 8.49406 4.00596C8.6581 4.17 8.6581 4.43592 8.49406 4.59996L7.0939 6L8.49406 7.40004C8.6581 7.56408 8.6581 7.83 8.49406 7.99404C8.4121 8.076 8.30458 8.11704 8.19706 8.11704C8.08966 8.11704 7.98214 8.076 7.90018 7.99404L6.50002 6.594L5.09986 7.99404C5.01778 8.076 4.91038 8.11704 4.80286 8.11704C4.69546 8.11704 4.58794 8.076 4.50598 7.99404C4.34182 7.83 4.34182 7.56408 4.50598 7.40004L5.90614 6L4.50598 4.59996C4.34182 4.43592 4.34182 4.17 4.50598 4.00596C4.66978 3.84192 4.93582 3.84204 5.09986 4.00596L6.50002 5.406L7.90018 4.00596Z' fill='%23AC160B'/%3E%3C/svg%3E%3C/svg%3E%0A");
|
||||
}
|
||||
}
|
||||
|
||||
.button-auxillary-copy {
|
||||
box-sizing: border-box;
|
||||
justify-content: right;
|
||||
line-height: 1.25rem !important;
|
||||
font-weight: 400;
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: #006a36;
|
||||
background: #e3f2ea;
|
||||
.loader {
|
||||
padding: 0 0.25rem 0 0.25rem;
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.red {
|
||||
color: #ac160b;
|
||||
background: #e3f2ea;
|
||||
.loader:after {
|
||||
background-color: $gray-300 !important;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
&.green {
|
||||
color: $green-700;
|
||||
background-color: $green-100;
|
||||
}
|
||||
|
||||
&.red {
|
||||
color: $red-600;
|
||||
background-color: $red-100;
|
||||
}
|
||||
|
||||
&.gray {
|
||||
color: $gray-600 !important;
|
||||
background-color: $gray-100;
|
||||
padding-left: 0.125rem;
|
||||
padding-right: 0.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.row-two {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
textPosition="text-start"
|
||||
v-model="selectedProviderNumber"
|
||||
isRequired
|
||||
validationRules="option-required" />
|
||||
validationRules="option-required"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<textLink
|
||||
v-show="displaySeeMoreLocationsLink"
|
||||
ref="showMoreShopsLink"
|
||||
|
|
@ -51,6 +52,8 @@ import { errorMessages } from "@/constants/error-messages";
|
|||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { nextTick } from "vue";
|
||||
|
||||
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||
|
||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
export default {
|
||||
|
|
@ -102,6 +105,21 @@ export default {
|
|||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent("ShowMoreShopsLinkWidget", "Text");
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 7);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split("T")[0];
|
||||
const formattedEndDate = endDate.toISOString().split("T")[0];
|
||||
|
||||
return {
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType,
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
loadInitialData(serviceZipCode) {
|
||||
|
|
@ -158,7 +176,7 @@ export default {
|
|||
});
|
||||
}
|
||||
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
if (this.shopIndex == this.shopProviders.length) {
|
||||
this.displaySeeMoreLocationsLink = false;
|
||||
|
|
@ -166,7 +184,7 @@ export default {
|
|||
this.displaySeeMoreLocationsLink = true;
|
||||
}
|
||||
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
this.scrollToPageBottom();
|
||||
},
|
||||
|
|
@ -203,22 +221,20 @@ export default {
|
|||
async handler(newValue) {
|
||||
this.resetAnswers();
|
||||
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
this.selectedProviderNumber = null;
|
||||
|
||||
this.$refs.buttonQuestion?.resetField();
|
||||
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
if (newValue !== "Mobile") {
|
||||
await this.getNextShopsFromList();
|
||||
this.getNextShopsFromList();
|
||||
}
|
||||
},
|
||||
},
|
||||
shopProviders: {
|
||||
async handler(newValue) {
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
|
||||
if (this.selectedAppointmentType) {
|
||||
const selectedShopIndex = this.getSelectedProviderIndex(
|
||||
|
|
@ -230,7 +246,7 @@ export default {
|
|||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await this.$nextTick();
|
||||
await nextTick();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -261,14 +277,16 @@ export default {
|
|||
background-repeat: no-repeat;
|
||||
background-size: 0.75rem;
|
||||
background-position: 0.5rem 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.5rem !important;
|
||||
gap: 0.25rem;
|
||||
|
||||
.alert-heading {
|
||||
text-align: left;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
p {
|
||||
padding-left: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -551,6 +551,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
lookupVehicleByYmms(context, { year, make, model, style }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVehicleByYmms.method,
|
||||
|
|
@ -558,6 +559,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
lookupVehicleByVin(context, { vin }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVehicleByVin.method,
|
||||
|
|
@ -567,6 +569,7 @@ export const actions = {
|
|||
},
|
||||
});
|
||||
},
|
||||
|
||||
lookupVinByPlate(context, { licensePlate, licenseState }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVinByPlate.method,
|
||||
|
|
@ -577,6 +580,7 @@ export const actions = {
|
|||
},
|
||||
});
|
||||
},
|
||||
|
||||
lookupVinByAddress(
|
||||
context,
|
||||
{ licenseLastName, licenseStreetAddress, licenseZip, licenseState }
|
||||
|
|
@ -592,6 +596,7 @@ export const actions = {
|
|||
},
|
||||
});
|
||||
},
|
||||
|
||||
lookupVinByImage(context, image) {
|
||||
const data = new FormData();
|
||||
data.append("vinImage", image);
|
||||
|
|
@ -602,6 +607,7 @@ export const actions = {
|
|||
isFormData: true,
|
||||
});
|
||||
},
|
||||
|
||||
isVinByAddressPermissible(context, zip) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.IsVinByAddressPermissible.method,
|
||||
|
|
@ -609,6 +615,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
getVehicleMakes(context, { year }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleMakes.method,
|
||||
|
|
@ -616,6 +623,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
getVehicleModels(context, { year, make }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleModels.method,
|
||||
|
|
@ -623,6 +631,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
getVehicleStyles(context, { year, make, model }) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleStyles.method,
|
||||
|
|
@ -630,6 +639,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
setVehicle(context, { year, make, model, style }) {
|
||||
return globalMethods
|
||||
.callHttpClient({
|
||||
|
|
@ -652,6 +662,7 @@ export const actions = {
|
|||
return response;
|
||||
});
|
||||
},
|
||||
|
||||
getDamageOptions(context, { carId }) {
|
||||
return globalMethods.callHttpClient({
|
||||
methods: endpoints.GetDamageOptions.method,
|
||||
|
|
@ -659,6 +670,7 @@ export const actions = {
|
|||
payload: {},
|
||||
});
|
||||
},
|
||||
|
||||
validateZip(context, { zip }) {
|
||||
return globalMethods.callHttpClient({
|
||||
methods: endpoints.ValidateZip.method,
|
||||
|
|
@ -673,18 +685,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 +715,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 +789,7 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_SAVED_SESSION_ID, savedSessionId);
|
||||
context.commit(storeMutations.UPDATE_CRM_CUSTOMER_ID, crmCustomerId);
|
||||
},
|
||||
|
||||
logPageView(
|
||||
context,
|
||||
{
|
||||
|
|
@ -812,6 +831,7 @@ export const actions = {
|
|||
}
|
||||
);
|
||||
},
|
||||
|
||||
logCustomEvent(
|
||||
context,
|
||||
{
|
||||
|
|
@ -1119,6 +1139,7 @@ export const actions = {
|
|||
getShopTimeSlots(context, { startDate, endDate, shopAppointmentType, providerNumber }) {
|
||||
const order = context.state.order;
|
||||
const vehicle = context.state.order.vehicle;
|
||||
|
||||
let partNumbers = [
|
||||
...(order.lineItems.supportingItems ?? []),
|
||||
...(order.lineItems.vaps ?? []),
|
||||
|
|
@ -1161,6 +1182,7 @@ export const actions = {
|
|||
vin: vehicle.vin ?? "",
|
||||
},
|
||||
};
|
||||
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetShopTimeSlots.method,
|
||||
endpoint: endpoints.GetShopTimeSlots.url,
|
||||
|
|
@ -1168,6 +1190,7 @@ export const actions = {
|
|||
logApiCall: false,
|
||||
});
|
||||
},
|
||||
|
||||
getMobileTimeSlots(context, { startDate, endDate }) {
|
||||
const order = context.state.order;
|
||||
const vehicle = context.state.order.vehicle;
|
||||
|
|
@ -1219,6 +1242,7 @@ export const actions = {
|
|||
logApiCall: false,
|
||||
});
|
||||
},
|
||||
|
||||
getMobileEarlyBirdFee(context) {
|
||||
const damageType = context.getters.damage.isRepair ? "Repair" : "Replace";
|
||||
const paymentType = context.getters.order.payment.isInsurance ? "Insurance" : "Cash";
|
||||
|
|
@ -1228,6 +1252,7 @@ export const actions = {
|
|||
endpoint: `${endpoints.GetMobileEarlyBirdFee.url}/${paymentType}/${damageType}`,
|
||||
});
|
||||
},
|
||||
|
||||
// Session API Actions
|
||||
saveSession(context) {
|
||||
const vehicle = context.getters.vehicle;
|
||||
|
|
@ -1328,6 +1353,7 @@ export const actions = {
|
|||
},
|
||||
});
|
||||
},
|
||||
|
||||
loadSession(
|
||||
context,
|
||||
{
|
||||
|
|
@ -1405,6 +1431,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) {
|
||||
|
|
@ -1425,6 +1452,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) {
|
||||
|
|
@ -1444,6 +1472,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) {
|
||||
|
|
@ -1462,6 +1491,7 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_STYLE, style);
|
||||
}
|
||||
},
|
||||
|
||||
saveVehicleDamage(
|
||||
context,
|
||||
{ isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }
|
||||
|
|
@ -1519,6 +1549,7 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
|
||||
}
|
||||
},
|
||||
|
||||
saveRegistrationLicensePlateLookup(
|
||||
context,
|
||||
{ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
|
||||
|
|
@ -1540,6 +1571,7 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
|
||||
}
|
||||
},
|
||||
|
||||
saveRegistrationAddressLookup(
|
||||
context,
|
||||
{ isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
|
||||
|
|
@ -1565,6 +1597,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(
|
||||
|
|
@ -1603,6 +1636,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 ??
|
||||
|
|
@ -1642,6 +1676,7 @@ export const actions = {
|
|||
});
|
||||
}
|
||||
},
|
||||
|
||||
saveMoldingQuestionAnswers(context, moldingQuestionAnswers) {
|
||||
const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
|
||||
context.getters.damage.moldingQuestionAnswers,
|
||||
|
|
@ -1670,6 +1705,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,
|
||||
|
|
@ -1696,18 +1732,23 @@ 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) {
|
||||
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
|
||||
},
|
||||
|
||||
saveVaps(context, vaps) {
|
||||
context.commit(storeMutations.UPDATE_VAPS, vaps);
|
||||
},
|
||||
|
||||
// Price order actions
|
||||
async priceOrderItemsAndSaveServerData(
|
||||
context,
|
||||
|
|
@ -1760,16 +1801,20 @@ export const actions = {
|
|||
|
||||
return availableLineItems;
|
||||
},
|
||||
|
||||
// Misc order actions
|
||||
saveSchedule(context, scheduleInfo) {
|
||||
context.commit(storeMutations.UPDATE_SCHEDULE, scheduleInfo);
|
||||
},
|
||||
|
||||
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) {
|
||||
|
|
@ -1782,12 +1827,15 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_VEHICLE, vehicleInfo);
|
||||
}
|
||||
},
|
||||
|
||||
saveGlassParts(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":
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
class="loader"
|
||||
role="alert"
|
||||
aria-label="Loading new page"
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition]"></div>
|
||||
v-bind:class="[this.loaderColor, this.loaderPosition, this.blockUi]"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -19,6 +19,11 @@ export default {
|
|||
loaderPosition: {
|
||||
type: String,
|
||||
},
|
||||
/* Controls whether we block the UI when the loader is active or now, defaults to true*/
|
||||
blockUi: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -82,5 +87,9 @@ export default {
|
|||
&.black:after {
|
||||
background-color: $black;
|
||||
}
|
||||
|
||||
&.no-block::before {
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue