First roll of refactoring to fix bug and make component more consistent with other modal components
This commit is contained in:
parent
5a9ab3b565
commit
f3ae844989
3 changed files with 175 additions and 145 deletions
|
|
@ -11,24 +11,24 @@
|
||||||
class="mb-3 text-link-small"
|
class="mb-3 text-link-small"
|
||||||
marginTopSizeOverride="1" />
|
marginTopSizeOverride="1" />
|
||||||
</template>
|
</template>
|
||||||
<location-alerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
||||||
<date-picker
|
<datePicker
|
||||||
selectableDatesSetting="custom"
|
selectableDatesSetting="custom"
|
||||||
ref="datePicker"
|
ref="datePicker"
|
||||||
v-model="selectedDate"
|
v-model="selectedDate"
|
||||||
class="text-link-small"
|
class="text-link-small"
|
||||||
:customSelectableDatesCallback="getAvailableDatesMethod"
|
:customSelectableDatesCallback="getAvailableDatesMethod"
|
||||||
@date-clicked="openInshopTimeSlotsModal" />
|
@date-clicked="openInshopTimeSlotsModal" />
|
||||||
<time-slot-modal-question
|
<timeSlotModalQuestion
|
||||||
ref="timeSlotModalQuestion"
|
ref="timeSlotModalQuestion"
|
||||||
|
customComponentId="timeSlotModalQuestion"
|
||||||
cmsWidgetName="TimeSlotModalQuestion"
|
cmsWidgetName="TimeSlotModalQuestion"
|
||||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||||
v-model="selectedTimeSlotData"
|
v-model="selectedTimeSlot"
|
||||||
@time-slot-modal-closed="timeSlotModalClosed"
|
|
||||||
:appointmentType="appointmentType"
|
:appointmentType="appointmentType"
|
||||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||||
:dateAndTimeSlotData="timeSlotsForSelectedDate"
|
:dateAndTimeSlotData="timeSlotsForSelectedDate"
|
||||||
|
|
@ -75,7 +75,18 @@ import { required } from "@/helpers/validation-rules";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
||||||
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
|
||||||
defineRule("time-slot-selection-required", required(errorMessages.DATE_REQUIRED));
|
|
||||||
|
// DEFINE VALIDATION RULES
|
||||||
|
defineRule("time-slot-selection-required", (value) => {
|
||||||
|
if (value.date == null ||
|
||||||
|
value.startTime == null ||
|
||||||
|
value.endTime == null ||
|
||||||
|
value.routeCode == null ||
|
||||||
|
value.estimatedServiceMinutesMaximum) {
|
||||||
|
return errorMessages.DATE_REQUIRED;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
// Define constants
|
// Define constants
|
||||||
const TIME_SLOTS_CALL_DAYS_LIMIT = 34; // needs to be 34 for API limits (35 does not consistently work)
|
const TIME_SLOTS_CALL_DAYS_LIMIT = 34; // needs to be 34 for API limits (35 does not consistently work)
|
||||||
|
|
@ -171,10 +182,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedDate: this.getSelectedDate(),
|
selectedDate: this.getSelectedDate(),
|
||||||
selectedTimeSlotData: {
|
selectedTimeSlot: this.getSelectedTimeSlot(),
|
||||||
id: this.getSelectedRouteCode(),
|
|
||||||
isPremiumAppointment: this.isMobilePremiumFeeOnOrderInVuex(),
|
|
||||||
},
|
|
||||||
selectableDatesData: [],
|
selectableDatesData: [],
|
||||||
mobilePremiumAppointmentFee: null,
|
mobilePremiumAppointmentFee: null,
|
||||||
};
|
};
|
||||||
|
|
@ -217,6 +225,7 @@ export default {
|
||||||
store.getters.order.serviceLocation.zipCodeCtu,
|
store.getters.order.serviceLocation.zipCodeCtu,
|
||||||
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
store.getters.order.serviceLocation.provider?.address?.zipCodeCtu
|
||||||
);
|
);
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
|
|
@ -248,7 +257,7 @@ export default {
|
||||||
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
||||||
? resultMap.premiumFeeWithPrice[0]
|
? resultMap.premiumFeeWithPrice[0]
|
||||||
: null;
|
: null;
|
||||||
vm.updateFooterButtonText(vm.selectedTimeSlotData);
|
vm.updateFooterButtonText(vm.selectedTimeSlot);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -266,30 +275,11 @@ export default {
|
||||||
if (!this.selectedDate) {
|
if (!this.selectedDate) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.selectableDatesData.days?.find(
|
return this.selectableDatesData.days?.find(
|
||||||
(selectableDate) => selectableDate.date === this.selectedDate
|
(selectableDate) => selectableDate.date === this.selectedDate
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
appointmentDateAndTime() {
|
|
||||||
if (!this.selectedTimeSlotData.id) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const timeSlotSelectedObject = this.getTimeSlotObjectFromTimeSlotId(
|
|
||||||
this.selectedTimeSlotData.id
|
|
||||||
);
|
|
||||||
if (timeSlotSelectedObject) {
|
|
||||||
return {
|
|
||||||
date: this.selectedDate,
|
|
||||||
startTime: timeSlotSelectedObject.startTime,
|
|
||||||
endTime: timeSlotSelectedObject.endTime,
|
|
||||||
routeCode: this.selectedTimeSlotData.id,
|
|
||||||
jobMaxMinutes:
|
|
||||||
this.selectableDatesData.estimatedServiceMinutesMaximum.toString(),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
splitCopyOnCMSPlaceHolder,
|
splitCopyOnCMSPlaceHolder,
|
||||||
|
|
@ -328,11 +318,8 @@ export default {
|
||||||
openInshopTimeSlotsModal() {
|
openInshopTimeSlotsModal() {
|
||||||
this.$refs["timeSlotModalQuestion"].openModal();
|
this.$refs["timeSlotModalQuestion"].openModal();
|
||||||
},
|
},
|
||||||
getTimeSlotObjectFromTimeSlotId(timeSlotId) {
|
getSelectedTimeSlot() {
|
||||||
const timeSlots = this.selectableDatesData.days.find(
|
return store.getters.order.schedule;
|
||||||
(selectableDate) => selectableDate.date === this.selectedDate
|
|
||||||
)?.timeSlots;
|
|
||||||
if (timeSlots) return timeSlots.find((timeSlot) => timeSlot.id === timeSlotId);
|
|
||||||
},
|
},
|
||||||
getSelectedDate() {
|
getSelectedDate() {
|
||||||
return store.getters.order.schedule.date;
|
return store.getters.order.schedule.date;
|
||||||
|
|
@ -340,45 +327,39 @@ export default {
|
||||||
getSelectedRouteCode() {
|
getSelectedRouteCode() {
|
||||||
return store.getters.order.schedule.routeCode;
|
return store.getters.order.schedule.routeCode;
|
||||||
},
|
},
|
||||||
|
getSupportingItems() {
|
||||||
|
return store.getters.lineItems.supportingItems;
|
||||||
|
},
|
||||||
isMobilePremiumFeeOnOrderInVuex() {
|
isMobilePremiumFeeOnOrderInVuex() {
|
||||||
const supportingItemsFromVuex = store.getters.lineItems.supportingItems;
|
const supportingItemsFromVuex = store.getters.lineItems.supportingItems;
|
||||||
return !!supportingItemsFromVuex.filter(
|
return !!supportingItemsFromVuex.filter(
|
||||||
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||||
).length;
|
).length;
|
||||||
},
|
},
|
||||||
timeSlotModalClosed() {
|
updateFooterButtonText(timeSlot) {
|
||||||
// Clear the selectedDate if no timeSlot has been selected
|
|
||||||
if (!this.selectedTimeSlotData.id) {
|
|
||||||
this.selectedDate = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
updateFooterButtonText(timeSlotData) {
|
|
||||||
let funnelFooterButtonText;
|
let funnelFooterButtonText;
|
||||||
if (!timeSlotData.id || !this.appointmentDateAndTime) {
|
if (!timeSlot || !timeSlot.date) {
|
||||||
funnelFooterButtonText = "Continue";
|
funnelFooterButtonText = "Continue";
|
||||||
} else {
|
} else {
|
||||||
funnelFooterButtonText =
|
funnelFooterButtonText = `Select ${this.convertSelectedDateToShortMonthAndDay(
|
||||||
"Select " + this.convertSelectedDateToShortMonthAndDay(this.selectedDate);
|
timeSlot.date
|
||||||
|
)}`;
|
||||||
|
|
||||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
funnelFooterButtonText +=
|
funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
" at " +
|
timeSlot.startTime
|
||||||
this.getDisplayTextForMilitaryTime(this.appointmentDateAndTime.startTime);
|
)}`;
|
||||||
} else if (
|
} else if (
|
||||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
!timeSlotData.isPremiumAppointment
|
!timeSlot.isPremiumAppointment
|
||||||
) {
|
) {
|
||||||
funnelFooterButtonText +=
|
funnelFooterButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||||
" at " +
|
timeSlot.startTime,
|
||||||
this.getDisplayTextForMilitaryTime(
|
true
|
||||||
this.appointmentDateAndTime.startTime,
|
)} - ${this.getDisplayTextForMilitaryTime(
|
||||||
true
|
timeSlot.endTime,
|
||||||
) +
|
true
|
||||||
" - " +
|
)}`;
|
||||||
this.getDisplayTextForMilitaryTime(
|
|
||||||
this.appointmentDateAndTime.endTime,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$refs.funnelFooter.updateButtonText(funnelFooterButtonText);
|
this.$refs.funnelFooter.updateButtonText(funnelFooterButtonText);
|
||||||
|
|
@ -408,21 +389,16 @@ export default {
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
this.updateSupportingItems();
|
this.updateSupportingItems();
|
||||||
this.dispatchStoreAction(
|
this.dispatchStoreAction(this.storeActions.SAVE_SCHEDULE, this.selectedTimeSlot, false);
|
||||||
this.storeActions.SAVE_SCHEDULE,
|
|
||||||
this.appointmentDateAndTime,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
navigateToHeritageFunnel({ loadingModal: this.$refs.loadingModal });
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSupportingItems() {
|
updateSupportingItems() {
|
||||||
const supportingItems = store.getters.lineItems.supportingItems;
|
const supportingItems = this.getSupportingItems();
|
||||||
|
|
||||||
// if we have a premium fee(early bird), then save/update supporting items
|
// if we have a premium fee(early bird), then save/update supporting items
|
||||||
if (
|
if (
|
||||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||||
this.selectedTimeSlotData?.isPremiumAppointment
|
this.selectedTimeSlot?.isPremiumAppointment
|
||||||
) {
|
) {
|
||||||
const earlyBirdIndex = supportingItems.findIndex(
|
const earlyBirdIndex = supportingItems.findIndex(
|
||||||
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
(item) => item.partType == PREMIUM_FEE_PART_TYPE
|
||||||
|
|
@ -462,17 +438,8 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedDate(newValue, oldValue) {
|
selectedTimeSlot(newValue) {
|
||||||
// Clear time slot selection if date selected changes
|
this.updateFooterButtonText(newValue);
|
||||||
if (newValue !== oldValue) {
|
|
||||||
this.selectedTimeSlotData = {
|
|
||||||
id: null,
|
|
||||||
isPremiumAppointment: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
selectedTimeSlotData(newValue) {
|
|
||||||
this.updateFooterButtonText(this.selectedTimeSlotData);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -6,33 +6,37 @@
|
||||||
:footerButtonText="footerCloseButtonText"
|
:footerButtonText="footerCloseButtonText"
|
||||||
:onModalOpenedCallback="onModalOpened"
|
:onModalOpenedCallback="onModalOpened"
|
||||||
:onModalClosedCallback="onModalClosed"
|
:onModalClosedCallback="onModalClosed"
|
||||||
@footer-button-event="closeModal">
|
@isModalOpened="setModalStatus"
|
||||||
<textBlock
|
@footer-button-event="setTimeSlot">
|
||||||
v-show="durationTextBlockCopy"
|
<template v-if="isModalOpened">
|
||||||
:customText="durationTextBlockCopy"
|
<textBlock
|
||||||
justifyText="center"
|
v-show="durationTextBlockCopy"
|
||||||
typeStyle="small"
|
:customText="durationTextBlockCopy"
|
||||||
class="duration-text-block" />
|
justifyText="center"
|
||||||
<buttonQuestion
|
typeStyle="small"
|
||||||
buttonTypeString="timeSlotModalListButton"
|
class="duration-text-block" />
|
||||||
:buttonTypeObject="timeSlotModalListButton"
|
<buttonQuestion
|
||||||
:answers="availableTimeSlots"
|
ref="buttonQuestion"
|
||||||
groupName="ChooseTimeSlot"
|
buttonTypeString="timeSlotModalListButton"
|
||||||
textPosition="text-center"
|
:buttonTypeObject="timeSlotModalListButton"
|
||||||
v-model="selectedTimeSlotId"
|
class="mt-5"
|
||||||
isRequired
|
:answers="availableTimeSlots"
|
||||||
validationRules="time-slot-required"
|
groupName="chooseTimeSlot"
|
||||||
class="mt-5" />
|
textPosition="text-center"
|
||||||
<div
|
v-model="selectedTimeSlotId"
|
||||||
class="mt-1 mb-2 supplemental-information"
|
isRequired
|
||||||
v-if="supplementalInformationBlock"
|
validationRules="time-slot-required" />
|
||||||
v-html="supplementalInformationBlock"></div>
|
<div
|
||||||
<textBlock
|
class="mt-1 mb-2 supplemental-information"
|
||||||
v-show="disclaimerTextBlockCopy"
|
v-if="supplementalInformationBlock"
|
||||||
:customText="disclaimerTextBlockCopy"
|
v-html="supplementalInformationBlock"></div>
|
||||||
justifyText="left"
|
<textBlock
|
||||||
typeStyle="caption"
|
v-show="disclaimerTextBlockCopy"
|
||||||
class="mb-2" />
|
:customText="disclaimerTextBlockCopy"
|
||||||
|
justifyText="left"
|
||||||
|
typeStyle="caption"
|
||||||
|
class="mb-2" />
|
||||||
|
</template>
|
||||||
</modal>
|
</modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -41,21 +45,27 @@
|
||||||
import modal from "@/digital-components/modal/modal";
|
import modal from "@/digital-components/modal/modal";
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
import { convertDateStringToDate } from "@/layouts/schedule/helpers/schedule-helper";
|
|
||||||
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
||||||
|
|
||||||
// TODO: Move this somewhere more global
|
// Helpers
|
||||||
|
import { convertDateStringToDate } from "@/layouts/schedule/helpers/schedule-helper";
|
||||||
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
|
|
||||||
|
// Validation - TODO: Move this somewhere more global?
|
||||||
import { defineRule, useField } from "vee-validate";
|
import { defineRule, useField } from "vee-validate";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { required } from "@/helpers/validation-rules";
|
||||||
|
|
||||||
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
|
||||||
// Constants
|
// Constants
|
||||||
import {
|
import {
|
||||||
AppointmentTypeStrings,
|
AppointmentTypeStrings,
|
||||||
|
RouteCodeFlags,
|
||||||
PREMIUM_TIME_SLOT_ID_FLAG,
|
PREMIUM_TIME_SLOT_ID_FLAG,
|
||||||
PREMIUM_FEE_PART_TYPE,
|
PREMIUM_FEE_PART_TYPE,
|
||||||
RouteCodeFlags,
|
|
||||||
} from "@/constants/schedule-constants";
|
} from "@/constants/schedule-constants";
|
||||||
|
|
||||||
const cmsWidgetFieldMappings = {
|
const cmsWidgetFieldMappings = {
|
||||||
MODAL_CLOSE_BUTTON: "FooterText",
|
MODAL_CLOSE_BUTTON: "FooterText",
|
||||||
SUPPLEMENTAL_INFORMATION: "BodyText",
|
SUPPLEMENTAL_INFORMATION: "BodyText",
|
||||||
|
|
@ -67,12 +77,18 @@ const cmsWidgetFieldMappings = {
|
||||||
// Validation for the modal button
|
// Validation for the modal button
|
||||||
defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
// Constants
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "timeSlotModalQuestion",
|
name: "time-slot-modal-question",
|
||||||
|
emits: ["update:modelValue"],
|
||||||
props: {
|
props: {
|
||||||
modelValue: Object,
|
modelValue: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
id: null,
|
||||||
|
isPremiumAppointment: null,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
mobileCmsWidgetName: String,
|
mobileCmsWidgetName: String,
|
||||||
mobilePremiumCmsWidgetName: String,
|
mobilePremiumCmsWidgetName: String,
|
||||||
|
|
@ -85,32 +101,76 @@ export default {
|
||||||
estimatedServiceMinutesMinimum: Number,
|
estimatedServiceMinutesMinimum: Number,
|
||||||
estimatedServiceMinutesMaximum: Number,
|
estimatedServiceMinutesMaximum: Number,
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
|
customComponentId: String,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedTimeSlotId: this.getModifiedSelectedTimeSlotId(),
|
internalModel: deepClone(this.modelValue),
|
||||||
|
isModalOpened: false,
|
||||||
timeSlotModalListButton: timeSlotModalListButton,
|
timeSlotModalListButton: timeSlotModalListButton,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { handleChange } = useField("time-slot-modal-question", props.validationRules);
|
const uuid = uuidv4();
|
||||||
// Run validation on component load
|
const componentId = !props.customComponentId
|
||||||
handleChange(props.modelValue.id);
|
? `component-${uuid}`
|
||||||
|
: props.customComponentId;
|
||||||
|
|
||||||
|
const modelValue = deepClone(props).modelValue;
|
||||||
|
const initialValue = modelValue;
|
||||||
|
|
||||||
|
const fieldOptions = {
|
||||||
|
value: modelValue,
|
||||||
|
initialValue: initialValue,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { errorMessage, handleChange, meta, validate, errors } = useField(
|
||||||
|
componentId,
|
||||||
|
props.validationRules,
|
||||||
|
fieldOptions
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
componentId,
|
||||||
|
errorMessage,
|
||||||
handleChange,
|
handleChange,
|
||||||
|
validate,
|
||||||
|
meta,
|
||||||
|
errors,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue() {
|
modelValue: {
|
||||||
this.selectedTimeSlotId = this.getModifiedSelectedTimeSlotId();
|
handler(newValue) {
|
||||||
// Run component validation that is used at parent level
|
this.internalModel = deepClone(newValue);
|
||||||
this.handleChange(this.modelValue.id);
|
this.handleChange(newValue);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
availableTimeSlots(newValue) {
|
availableTimeSlots(newValue) {
|
||||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable(newValue);
|
this.autoSelectTimeSlotIfOnlyOneIsAvailable(newValue);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
selectedValue: {
|
||||||
|
get: function () {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set: function (newValue) {
|
||||||
|
this.$emit("update:modelValue", newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selectedTimeSlotId: {
|
||||||
|
get: function () {
|
||||||
|
return this.selectedValue?.id;
|
||||||
|
},
|
||||||
|
set: function (newValue) {
|
||||||
|
// Button Question only supports Number, or String data types so we must get the full object to emit
|
||||||
|
this.selectedValue = this.getSelectedTimeSlotObject(newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
modal() {
|
||||||
|
return this.$refs["timeSlots"];
|
||||||
|
},
|
||||||
supplementalInformationBlock() {
|
supplementalInformationBlock() {
|
||||||
let appointmentTypeCmsWidgetName;
|
let appointmentTypeCmsWidgetName;
|
||||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
|
|
@ -281,35 +341,26 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openModal() {
|
openModal() {
|
||||||
this.$refs["timeSlots"].openModal();
|
this.modal.openModal();
|
||||||
|
},
|
||||||
|
onModalOpened() {
|
||||||
|
this.internalModel = deepClone(this.modelValue);
|
||||||
|
},
|
||||||
|
setModalStatus(isOpened) {
|
||||||
|
this.isModalOpened = isOpened;
|
||||||
},
|
},
|
||||||
// fires any time the footer button is used, is fired before "onModalClosed"
|
|
||||||
closeModal() {
|
closeModal() {
|
||||||
let isSelectedAppointmentPremium = false;
|
this.modal.closeModal();
|
||||||
if (this.selectedTimeSlotId.includes(PREMIUM_TIME_SLOT_ID_FLAG)) {
|
|
||||||
this.selectedTimeSlotId = this.removePremiumFlagFromInput(this.selectedTimeSlotId);
|
|
||||||
isSelectedAppointmentPremium = true;
|
|
||||||
}
|
|
||||||
const selectedTimeSlotData = {
|
|
||||||
id: this.selectedTimeSlotId,
|
|
||||||
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() {
|
onModalClosed() {
|
||||||
this.$emit("time-slot-modal-closed");
|
this.internalModel = deepClone(this.modelValue);
|
||||||
},
|
},
|
||||||
getModifiedSelectedTimeSlotId() {
|
setTimeSlot() {
|
||||||
if (this.modelValue.isPremiumAppointment) {
|
this.$emit("update:modelValue", this.internalModel);
|
||||||
return this.addPremiumFlagToInput(this.modelValue.id);
|
this.closeModal();
|
||||||
} else {
|
|
||||||
return this.modelValue.id;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// Expected input: "HH:MM"
|
|
||||||
getDisplayTextForMilitaryTime(militaryTimeInput) {
|
getDisplayTextForMilitaryTime(militaryTimeInput) {
|
||||||
|
// Expected input: "HH:MM"
|
||||||
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
let hours = parseInt(militaryTimeInput.split(":")[0]);
|
||||||
const minutes = militaryTimeInput.split(":")[1];
|
const minutes = militaryTimeInput.split(":")[1];
|
||||||
const meridianNotation = hours > 11 ? "PM" : "AM";
|
const meridianNotation = hours > 11 ? "PM" : "AM";
|
||||||
|
|
@ -414,6 +465,19 @@ export default {
|
||||||
removePremiumFlagFromInput(timeSlotId) {
|
removePremiumFlagFromInput(timeSlotId) {
|
||||||
return timeSlotId.substring(0, timeSlotId.length - PREMIUM_TIME_SLOT_ID_FLAG.length);
|
return timeSlotId.substring(0, timeSlotId.length - PREMIUM_TIME_SLOT_ID_FLAG.length);
|
||||||
},
|
},
|
||||||
|
getSelectedTimeSlotObject(timeSlotId) {
|
||||||
|
const timeSlot = this.dateAndTimeSlotData.timeSlots?.find(
|
||||||
|
(timeSlot) => timeSlot.id == timeSlotId
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
date: this.dateAndTimeSlotData.date,
|
||||||
|
startTime: timeSlot.startTime,
|
||||||
|
endTime: timeSlot.endTime,
|
||||||
|
routeCode: timeSlot.id,
|
||||||
|
jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(),
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
modal,
|
modal,
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,6 @@ export default {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
this.internalModel = deepClone(newValue);
|
this.internalModel = deepClone(newValue);
|
||||||
|
|
||||||
this.handleChange(newValue);
|
this.handleChange(newValue);
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue