345 lines
12 KiB
Vue
345 lines
12 KiB
Vue
<template>
|
|
<div id="multi-location-modal-container">
|
|
<modal
|
|
:ref="modalName"
|
|
:headerText="modalHeaderText"
|
|
suppressPageScroll
|
|
:onModalClosedCallback="onModalClosed"
|
|
:footerButtonText="modalFooterText"
|
|
:isFooterButtonPrimary="true"
|
|
@footer-button-event="confirmAppointment"
|
|
@isModalOpened="setIsModalOpen">
|
|
<buttonQuestion
|
|
ref="buttonQuestion"
|
|
buttonTypeString="multiLocationRadioButton"
|
|
:buttonTypeObject="multiLocationRadioButton"
|
|
class="mt-5"
|
|
:answers="availableAppointments"
|
|
groupName="multiLocationQuestion"
|
|
textPosition="text-center"
|
|
v-model="selectedValue"
|
|
isRequired
|
|
validationRules="time-slot-required" />
|
|
|
|
<template v-slot:modal-header-slot>
|
|
<span>{{ modalSubHeaderText }}</span>
|
|
</template>
|
|
<template v-slot:modal-footer-slot>
|
|
<button
|
|
type="button"
|
|
class="btn btn-link"
|
|
id="see-more-options"
|
|
:disabled="isLoading"
|
|
@click="closeModal">
|
|
{{ buttonText }}
|
|
</button>
|
|
</template>
|
|
</modal>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
// Supporting files
|
|
import store from "@/store";
|
|
import modal from "@/digital-components/modal/modal";
|
|
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
|
import { get12HourTimeFormat } from "@/helpers/date-helper";
|
|
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
|
import multiLocationRadioButton from "./multi-location-radio/multi-location-radio";
|
|
|
|
// Validation
|
|
import { defineRule, useField } from "vee-validate";
|
|
import { errorMessages } from "@/constants/error-messages";
|
|
import { required } from "@/helpers/validation-rules";
|
|
|
|
const NULL_APPOINTMENT = {
|
|
estimatedServiceMinutes: {
|
|
minimum: null,
|
|
maximum: null,
|
|
},
|
|
timeSlot: null,
|
|
date: null,
|
|
};
|
|
|
|
// Validation for the modal button
|
|
defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
|
|
|
export default {
|
|
name: "multi-location-modal",
|
|
props: {
|
|
cmsWidgetName: String,
|
|
modalWidgetName: String,
|
|
buttonWidgetName: String,
|
|
},
|
|
data() {
|
|
return {
|
|
isModalOpen: false,
|
|
mobileAppointmentOption: NULL_APPOINTMENT,
|
|
inshopAppointmentOption: NULL_APPOINTMENT,
|
|
confirmedAppointment: false,
|
|
multiLocationRadioButton: multiLocationRadioButton,
|
|
selectedValue: null,
|
|
experimentSettings: "",
|
|
};
|
|
},
|
|
methods: {
|
|
splitCopyOnCMSPlaceHolder,
|
|
get12HourTimeFormat,
|
|
openModal() {
|
|
this.modal.openModal();
|
|
},
|
|
onModalClosed() {
|
|
this.pushEvent();
|
|
this.confirmedAppointment = false;
|
|
},
|
|
closeModal() {
|
|
this.modal.closeModal();
|
|
},
|
|
confirmAppointment() {
|
|
if (!this.selectedAppointment.timeSlot.id) return;
|
|
|
|
const selectedTimeSlot = {
|
|
timeSlot: this.selectedAppointment.timeSlot,
|
|
routeCode: this.selectedAppointment.timeSlot.id,
|
|
date: this.selectedAppointment.date,
|
|
};
|
|
this.confirmedAppointment = true;
|
|
this.$emit("confirm-appointment", {
|
|
selectedTimeSlot: selectedTimeSlot,
|
|
appointmentType: this.selectedValue,
|
|
});
|
|
this.modal.closeModal();
|
|
},
|
|
setPromotedMobileAppointment(appointment) {
|
|
this.mobileAppointmentOption = appointment;
|
|
},
|
|
setPromotedInshopAppointment(appointment) {
|
|
this.inshopAppointmentOption = appointment;
|
|
},
|
|
getIsModalOpen() {
|
|
return this.isModalOpen;
|
|
},
|
|
setIsModalOpen(isOpen) {
|
|
this.isModalOpen = isOpen;
|
|
},
|
|
captureExperimentSettings(settingsString) {
|
|
this.experimentSettings = settingsString;
|
|
},
|
|
pushEvent() {
|
|
let gaAction = this.confirmedAppointment ? this.GaActions.YES : this.GaActions.NO;
|
|
if (
|
|
this.selectedValue?.toLowerCase() === "mobile" &&
|
|
this.mobileAppointmentOption?.timeSlot
|
|
) {
|
|
this.pushEventToGA(
|
|
this.GaCategories.MOBILE_CONFIRMATION_CLICKED,
|
|
gaAction,
|
|
this.mobileAppointmentOption.timeSlot.startTime +
|
|
"-" +
|
|
this.mobileAppointmentOption.timeSlot.endTime +
|
|
" " +
|
|
this.mobileAppointmentOption.date,
|
|
true,
|
|
null,
|
|
this.experimentSettings
|
|
);
|
|
} else if (
|
|
this.selectedValue?.toLowerCase() === "inshop" &&
|
|
this.inshopAppointmentOption?.timeSlot
|
|
) {
|
|
this.pushEventToGA(
|
|
this.GaCategories.INSHOP_CONFIRMATION_CLICKED,
|
|
gaAction,
|
|
this.inshopAppointmentOption.timeSlot.startTime +
|
|
"-" +
|
|
this.inshopAppointmentOption.date,
|
|
true,
|
|
null,
|
|
this.experimentSettings
|
|
);
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
selectedAppointment() {
|
|
if (this.selectedValue?.toLowerCase() === "mobile") {
|
|
return this.mobileAppointmentOption;
|
|
} else if (this.selectedValue?.toLowerCase() === "inshop") {
|
|
return this.inshopAppointmentOption;
|
|
} else {
|
|
return NULL_APPOINTMENT;
|
|
}
|
|
},
|
|
modalName() {
|
|
return this.modalWidgetName;
|
|
},
|
|
modal() {
|
|
return this.$refs[this.modalName];
|
|
},
|
|
modalSubHeaderText() {
|
|
return this.getCmsContent(this.modalWidgetName, "SubheaderText");
|
|
},
|
|
modalHeaderText() {
|
|
return this.getCmsContent(this.modalWidgetName, "HeaderText");
|
|
},
|
|
modalFooterText() {
|
|
return this.getCmsContent(this.modalWidgetName, "FooterText");
|
|
},
|
|
buttonText() {
|
|
return this.getCmsContent(this.modalWidgetName, "FooterText2");
|
|
},
|
|
mobileButtonLabel() {
|
|
return this.getCmsContent(this.buttonWidgetName, "HeaderText");
|
|
},
|
|
inshopButtonLabel() {
|
|
return this.getCmsContent(this.buttonWidgetName, "SubheaderText");
|
|
},
|
|
mobileButtonDate() {
|
|
if (!this.mobileAppointmentOption.date) return "";
|
|
return new Date(this.mobileAppointmentOption.date).toLocaleDateString("en-US", {
|
|
timeZone: "UTC",
|
|
weekday: "short",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
},
|
|
inshopButtonDate() {
|
|
if (!this.inshopAppointmentOption.date) return "";
|
|
return new Date(this.inshopAppointmentOption.date).toLocaleDateString("en-US", {
|
|
timeZone: "UTC",
|
|
weekday: "short",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
},
|
|
mobileButtonTime() {
|
|
const timeslot =
|
|
this.get12HourTimeFormat(this.mobileAppointmentOption.timeSlot?.startTime) +
|
|
" - " +
|
|
this.get12HourTimeFormat(this.mobileAppointmentOption.timeSlot?.endTime);
|
|
return timeslot;
|
|
},
|
|
inshopButtonTime() {
|
|
const timeslot = this.get12HourTimeFormat(
|
|
this.inshopAppointmentOption.timeSlot?.startTime
|
|
);
|
|
return timeslot;
|
|
},
|
|
mobileLocationLabel() {
|
|
return this.getCmsContent(this.buttonWidgetName, "BodyText");
|
|
},
|
|
inshopLocationLabel() {
|
|
return this.inshopAppointmentOption?.addressCopy;
|
|
},
|
|
mobileServiceDuration() {
|
|
const durationTime = getDisplayTextForDurationLength(
|
|
this.mobileAppointmentOption.estimatedServiceMinutes.minimum,
|
|
this.mobileAppointmentOption.estimatedServiceMinutes.maximum
|
|
);
|
|
const footerText = this.getCmsContent(this.buttonWidgetName, "FooterText").replaceAll(
|
|
"{custom:serviceLength}",
|
|
durationTime
|
|
);
|
|
return footerText;
|
|
},
|
|
inshopServiceDuration() {
|
|
const durationTime = getDisplayTextForDurationLength(
|
|
this.inshopAppointmentOption.estimatedServiceMinutes.minimum,
|
|
this.inshopAppointmentOption.estimatedServiceMinutes.maximum
|
|
);
|
|
const footerText = this.getCmsContent(this.buttonWidgetName, "FooterText").replaceAll(
|
|
"{custom:serviceLength}",
|
|
durationTime
|
|
);
|
|
return footerText;
|
|
},
|
|
availableAppointments() {
|
|
return [
|
|
{
|
|
value: "mobile",
|
|
buttonLabel: this.mobileButtonDate,
|
|
buttonLabelSubCopy: this.mobileButtonTime,
|
|
buttonBodyCopy: this.mobileLocationLabel,
|
|
buttonAuxillaryCopy: this.mobileButtonLabel,
|
|
buttonFooterCopy: this.mobileServiceDuration,
|
|
},
|
|
{
|
|
value: "inshop",
|
|
buttonLabel: this.inshopButtonDate,
|
|
buttonLabelSubCopy: this.inshopButtonTime,
|
|
buttonBodyCopy: this.inshopLocationLabel,
|
|
buttonAuxillaryCopy: this.inshopButtonLabel,
|
|
buttonFooterCopy: this.inshopServiceDuration,
|
|
},
|
|
];
|
|
},
|
|
},
|
|
components: { modal, buttonQuestion },
|
|
};
|
|
</script>
|
|
<style lang="scss">
|
|
#multi-location-modal-container {
|
|
.modal-component {
|
|
@include media-breakpoint-up(md) {
|
|
.modal-dialog {
|
|
left: 0;
|
|
align-content: center;
|
|
flex-wrap: wrap;
|
|
width: 22.063rem;
|
|
transform: translate(0, 0);
|
|
|
|
.modal-content {
|
|
border-radius: $border-radius-lg;
|
|
}
|
|
}
|
|
}
|
|
.modal-dialog {
|
|
.modal-content {
|
|
.modal-header {
|
|
flex-direction: column;
|
|
text-align: center;
|
|
padding: 0 1rem;
|
|
|
|
& > span {
|
|
color: $red;
|
|
font-weight: $font-weight-600;
|
|
text-transform: uppercase;
|
|
font-family: $font-family-sans-serif-semibold;
|
|
}
|
|
.modal-title {
|
|
font-size: $font-size-20;
|
|
font-weight: $font-weight-normal;
|
|
}
|
|
}
|
|
.modal-body {
|
|
padding: 0.5rem 1rem;
|
|
|
|
.button-question {
|
|
margin-top: 0.75rem;
|
|
}
|
|
|
|
.modal-body-inner {
|
|
ul {
|
|
list-style: none;
|
|
padding: 1rem;
|
|
background-color: #f4f4f4;
|
|
font-size: $font-size-14;
|
|
}
|
|
}
|
|
}
|
|
.modal-footer {
|
|
flex-flow: wrap-reverse;
|
|
|
|
#see-more-options {
|
|
width: 100%;
|
|
text-decoration: none;
|
|
margin-top: 1.5rem;
|
|
font-weight: $font-weight-600;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|