CASH-845: move duration text block from time-slot-question to date-picker
This commit is contained in:
parent
749c5cc466
commit
995c2da5a1
4 changed files with 94 additions and 66 deletions
|
|
@ -16,10 +16,19 @@ const RouteCodeFlags = {
|
||||||
OVERNIGHT_DROP_OFF: "OVERNIGHT DROP OFF",
|
OVERNIGHT_DROP_OFF: "OVERNIGHT DROP OFF",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cmsWidgetFieldMappings = {
|
||||||
|
MODAL_CLOSE_BUTTON: "FooterText",
|
||||||
|
SUPPLEMENTAL_INFORMATION: "BodyText",
|
||||||
|
TIME_SLOT_BUTTON: "HeaderText",
|
||||||
|
DISCLAIMER: "FooterText",
|
||||||
|
DURATION: "SubheaderText",
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AppointmentTypeStrings,
|
AppointmentTypeStrings,
|
||||||
PREMIUM_TIME_SLOT_ID_FLAG,
|
PREMIUM_TIME_SLOT_ID_FLAG,
|
||||||
PREMIUM_FEE_PART_TYPE,
|
PREMIUM_FEE_PART_TYPE,
|
||||||
PRICING_BY_DAY_PART_TYPE,
|
PRICING_BY_DAY_PART_TYPE,
|
||||||
RouteCodeFlags,
|
RouteCodeFlags,
|
||||||
|
cmsWidgetFieldMappings,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -142,7 +142,7 @@
|
||||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||||
dropOffOrPickATimeQuestionCmsWidgetName="DropOffOrPickATimeQuestionWidget"
|
dropOffOrPickATimeQuestionCmsWidgetName="DropOffOrPickATimeQuestionWidget"
|
||||||
:selectedDate="selectedDate"
|
:selectedDate="selectedDate"
|
||||||
:appointmentType="appointmentTypeForTimeSlotQuestion"
|
:appointmentType="appointmentType"
|
||||||
:premiumAppointmentFee="premiumAppointmentFee"
|
:premiumAppointmentFee="premiumAppointmentFee"
|
||||||
:displayWaitList="displayWaitList"
|
:displayWaitList="displayWaitList"
|
||||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||||
|
|
@ -156,6 +156,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
||||||
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import loader from "@/ux-components/loader/loader";
|
import loader from "@/ux-components/loader/loader";
|
||||||
|
|
@ -166,7 +167,12 @@ import {
|
||||||
MONTHS_OF_YEAR,
|
MONTHS_OF_YEAR,
|
||||||
DAYS_OF_WEEK,
|
DAYS_OF_WEEK,
|
||||||
} from "@/digital-components/date-picker/mixins/constants";
|
} from "@/digital-components/date-picker/mixins/constants";
|
||||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
|
import {
|
||||||
|
AppointmentTypeStrings,
|
||||||
|
RouteCodeFlags,
|
||||||
|
PREMIUM_FEE_PART_TYPE,
|
||||||
|
cmsWidgetFieldMappings,
|
||||||
|
} from "@/constants/schedule-constants";
|
||||||
import {
|
import {
|
||||||
selectableDaysOptions,
|
selectableDaysOptions,
|
||||||
requiredParameter,
|
requiredParameter,
|
||||||
|
|
@ -178,6 +184,7 @@ import {
|
||||||
import { useField, ErrorMessage } from "vee-validate";
|
import { useField, ErrorMessage } from "vee-validate";
|
||||||
import { deepClone } from "@/helpers/object-helper";
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
import { v4 as uuidv4 } from "uuid";
|
import { v4 as uuidv4 } from "uuid";
|
||||||
|
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "datePicker",
|
name: "datePicker",
|
||||||
|
|
@ -190,6 +197,7 @@ export default {
|
||||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||||
selectableDatesInshop: [], // NOTE: this and the mobile version below use monthNum (1-based), NOT monthIndex (0-based)
|
selectableDatesInshop: [], // NOTE: this and the mobile version below use monthNum (1-based), NOT monthIndex (0-based)
|
||||||
selectableDatesMobile: [],
|
selectableDatesMobile: [],
|
||||||
|
durationTextBlockCopyForInshopOrDropoff: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -224,7 +232,7 @@ export default {
|
||||||
pricingByDayUpcharge: Number,
|
pricingByDayUpcharge: Number,
|
||||||
isPricingByDayExperiment: Boolean,
|
isPricingByDayExperiment: Boolean,
|
||||||
timeSlotsForSelectedDate: Object,
|
timeSlotsForSelectedDate: Object,
|
||||||
appointmentTypeForTimeSlotQuestion: String,
|
appointmentType: String,
|
||||||
premiumAppointmentFee: Object,
|
premiumAppointmentFee: Object,
|
||||||
estimatedServiceMinutesMinimum: Number,
|
estimatedServiceMinutesMinimum: Number,
|
||||||
estimatedServiceMinutesMaximum: Number,
|
estimatedServiceMinutesMaximum: Number,
|
||||||
|
|
@ -289,6 +297,54 @@ export default {
|
||||||
this.$emit("update:modelValue", newSelectedDate);
|
this.$emit("update:modelValue", newSelectedDate);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
dropOffDurationText() {
|
||||||
|
return this.getCmsContent("DropOffTimeSlotModal", cmsWidgetFieldMappings.DURATION);
|
||||||
|
},
|
||||||
|
sameDayDropoffDurationText() {
|
||||||
|
return this.getCmsContent(
|
||||||
|
"SameDayDropOffTimeSlotModal",
|
||||||
|
cmsWidgetFieldMappings.DURATION
|
||||||
|
);
|
||||||
|
},
|
||||||
|
overnightDropoffDurationText() {
|
||||||
|
return this.getCmsContent(
|
||||||
|
"OvernightDropOffTimeSlotModal",
|
||||||
|
cmsWidgetFieldMappings.DURATION
|
||||||
|
);
|
||||||
|
},
|
||||||
|
inshopDurationText() {
|
||||||
|
const inshopDurationTextWithoutTime = this.getCmsContent(
|
||||||
|
"TimeSlotModalQuestion",
|
||||||
|
cmsWidgetFieldMappings.DURATION
|
||||||
|
);
|
||||||
|
|
||||||
|
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||||
|
this.estimatedServiceMinutesMinimum,
|
||||||
|
this.estimatedServiceMinutesMaximum
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${inshopDurationTextWithoutTime} ${inshopDurationTime}`;
|
||||||
|
},
|
||||||
|
durationTextBlockCopy() {
|
||||||
|
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||||
|
return null;
|
||||||
|
} else if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||||
|
return this.inshopDurationText;
|
||||||
|
} else if (
|
||||||
|
this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF ||
|
||||||
|
this.appointmentType === AppointmentTypeStrings.DROP_OFF
|
||||||
|
) {
|
||||||
|
return this.durationTextBlockCopyForInshopOrDropoff ?? this.inshopDurationText;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
isSameDay() {
|
||||||
|
if (!this.timeSlotsForSelectedDate) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const todaysDate = new Date().toISOString().split("T")[0];
|
||||||
|
return this.selectedDate === todaysDate;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
initializeComponent(initialData) {
|
initializeComponent(initialData) {
|
||||||
|
|
@ -877,6 +933,18 @@ export default {
|
||||||
handleWaitListRequested(value) {
|
handleWaitListRequested(value) {
|
||||||
this.$emit("waitListRequested", value);
|
this.$emit("waitListRequested", value);
|
||||||
},
|
},
|
||||||
|
getDurationTextBlockCopyForInshopOrDropoff(selectedRouteCode) {
|
||||||
|
if (selectedRouteCode?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||||
|
return this.overnightDropoffDurationText;
|
||||||
|
} else if (selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||||
|
if (this.isSameDay) {
|
||||||
|
return this.sameDayDropoffDurationText;
|
||||||
|
} else {
|
||||||
|
return this.dropOffDurationText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.inshopDurationText;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
modelValue(newValue) {
|
modelValue(newValue) {
|
||||||
|
|
@ -891,13 +959,17 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
selectedTimeSlotInfo(newValue) {
|
selectedTimeSlotInfo(newValue) {
|
||||||
this.$emit("TimeSlotSelected", newValue); // NEEDED ON SCHEDULE - to update footer button text and to save to Store correctly
|
const routeCode = newValue?.timeSlot?.routeCode;
|
||||||
|
this.durationTextBlockCopyForInshopOrDropoff =
|
||||||
|
this.getDurationTextBlockCopyForInshopOrDropoff(routeCode);
|
||||||
|
this.$emit("TimeSlotSelected", newValue); // needed to update footer button text on Schedule page and to save to Store correctly
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
loader,
|
loader,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
timeSlotQuestion,
|
timeSlotQuestion,
|
||||||
|
textBlock,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
:showPricingByDay="showPricingByDay"
|
:showPricingByDay="showPricingByDay"
|
||||||
:isPricingByDayExperiment="isPricingByDayExperiment"
|
:isPricingByDayExperiment="isPricingByDayExperiment"
|
||||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||||
:appointmentTypeForTimeSlotQuestion="appointmentType"
|
:appointmentType="appointmentType"
|
||||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||||
:estimatedServiceMinutesMinimum="getServiceMinutesMin"
|
:estimatedServiceMinutesMinimum="getServiceMinutesMin"
|
||||||
:estimatedServiceMinutesMaximum="getServiceMinutesMax"
|
:estimatedServiceMinutesMaximum="getServiceMinutesMax"
|
||||||
|
|
@ -1703,7 +1703,7 @@ export default {
|
||||||
.change-location a {
|
.change-location a {
|
||||||
font-family: UrbanistSemibold;
|
font-family: UrbanistSemibold;
|
||||||
}
|
}
|
||||||
.date-picker-wrapper {
|
.date-picker {
|
||||||
border-top: 1px solid $gray-500;
|
border-top: 1px solid $gray-500;
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="time-slots-question">
|
<div class="time-slots-question">
|
||||||
<textBlock
|
|
||||||
v-show="durationTextBlockCopy"
|
|
||||||
:customText="durationTextBlockCopy"
|
|
||||||
justifyText="center"
|
|
||||||
typeStyle="small"
|
|
||||||
class="duration-text-block" />
|
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
v-if="isDropOffAppointmentAvailable"
|
v-if="isDropOffAppointmentAvailable"
|
||||||
v-model="selectedAnswerForDropOffOrInshop"
|
v-model="selectedAnswerForDropOffOrInshop"
|
||||||
|
|
@ -103,16 +97,9 @@ import {
|
||||||
RouteCodeFlags,
|
RouteCodeFlags,
|
||||||
PREMIUM_TIME_SLOT_ID_FLAG,
|
PREMIUM_TIME_SLOT_ID_FLAG,
|
||||||
PREMIUM_FEE_PART_TYPE,
|
PREMIUM_FEE_PART_TYPE,
|
||||||
|
cmsWidgetFieldMappings,
|
||||||
} from "@/constants/schedule-constants";
|
} from "@/constants/schedule-constants";
|
||||||
|
|
||||||
const cmsWidgetFieldMappings = {
|
|
||||||
MODAL_CLOSE_BUTTON: "FooterText",
|
|
||||||
SUPPLEMENTAL_INFORMATION: "BodyText",
|
|
||||||
TIME_SLOT_BUTTON: "HeaderText",
|
|
||||||
DISCLAIMER: "FooterText",
|
|
||||||
DURATION: "SubheaderText",
|
|
||||||
};
|
|
||||||
|
|
||||||
const PICK_A_TIME_BUTTON_VALUE = "pick-a-time-selected";
|
const PICK_A_TIME_BUTTON_VALUE = "pick-a-time-selected";
|
||||||
|
|
||||||
defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
@ -194,7 +181,11 @@ export default {
|
||||||
supplementalInformationBlock() {
|
supplementalInformationBlock() {
|
||||||
let appointmentTypeCmsWidgetName;
|
let appointmentTypeCmsWidgetName;
|
||||||
|
|
||||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF) {
|
if (
|
||||||
|
this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF ||
|
||||||
|
this.appointmentType === AppointmentTypeStrings.IN_SHOP ||
|
||||||
|
this.appointmentType === AppointmentTypeStrings.DROP_OFF
|
||||||
|
) {
|
||||||
return null;
|
return null;
|
||||||
// This is planned to be used again for drop-off
|
// This is planned to be used again for drop-off
|
||||||
// Wrote this to be ready for that eventuality, is untested and no HTML work done yet
|
// Wrote this to be ready for that eventuality, is untested and no HTML work done yet
|
||||||
|
|
@ -286,51 +277,6 @@ export default {
|
||||||
// return null;
|
// return null;
|
||||||
// }
|
// }
|
||||||
// },
|
// },
|
||||||
dropOffDurationText() {
|
|
||||||
return this.getCmsContent(this.dropoffCmsWidgetName, cmsWidgetFieldMappings.DURATION);
|
|
||||||
},
|
|
||||||
sameDayDropoffDurationText() {
|
|
||||||
return this.getCmsContent(
|
|
||||||
this.sameDayDropOffCmsWidgetName,
|
|
||||||
cmsWidgetFieldMappings.DURATION
|
|
||||||
);
|
|
||||||
},
|
|
||||||
overnightDropoffDurationText() {
|
|
||||||
return this.getCmsContent(
|
|
||||||
this.overnightDropOffCmsWidgetName,
|
|
||||||
cmsWidgetFieldMappings.DURATION
|
|
||||||
);
|
|
||||||
},
|
|
||||||
inshopDurationText() {
|
|
||||||
const inshopDurationTextWithoutTime = this.getCmsContent(
|
|
||||||
this.cmsWidgetName,
|
|
||||||
cmsWidgetFieldMappings.DURATION
|
|
||||||
);
|
|
||||||
|
|
||||||
const inshopDurationTime = getDisplayTextForDurationLength(
|
|
||||||
this.estimatedServiceMinutesMinimum,
|
|
||||||
this.estimatedServiceMinutesMaximum
|
|
||||||
);
|
|
||||||
|
|
||||||
return `${inshopDurationTextWithoutTime} ${inshopDurationTime}`;
|
|
||||||
},
|
|
||||||
durationTextBlockCopy() {
|
|
||||||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
|
||||||
return null;
|
|
||||||
} else if (this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF) {
|
|
||||||
if (this.selectedRouteCode?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
|
||||||
return this.overnightDropoffDurationText;
|
|
||||||
} else if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
|
||||||
if (this.isSameDay) {
|
|
||||||
return this.sameDayDropoffDurationText;
|
|
||||||
} else {
|
|
||||||
return this.dropOffDurationText;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.inshopDurationText;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
isSameDay() {
|
isSameDay() {
|
||||||
if (!this.timeSlotsForSelectedDate) {
|
if (!this.timeSlotsForSelectedDate) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -609,6 +555,7 @@ export default {
|
||||||
selectedAnswerForDropOffOrInshop(newValue) {
|
selectedAnswerForDropOffOrInshop(newValue) {
|
||||||
if (newValue == PICK_A_TIME_BUTTON_VALUE) {
|
if (newValue == PICK_A_TIME_BUTTON_VALUE) {
|
||||||
this.selectedRouteCode = null;
|
this.selectedRouteCode = null;
|
||||||
|
this.setSelectedTimeSlot();
|
||||||
} else {
|
} else {
|
||||||
this.selectedAnswerForTimeSlots = null;
|
this.selectedAnswerForTimeSlots = null;
|
||||||
this.selectedRouteCode = newValue;
|
this.selectedRouteCode = newValue;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue