Merge remote-tracking branch 'origin/release/2025.07.10' into feature/Digital/CASH-814
This commit is contained in:
commit
7bb1060d91
10 changed files with 1155 additions and 84 deletions
|
|
@ -1354,23 +1354,6 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inshop-version {
|
||||
color: limegreen !important; // TODO - THIS IS TEMPORARY CODE; TO BE REMOVED AS PART OF CASH-845
|
||||
}
|
||||
.mobile-version {
|
||||
color: red !important; // TODO - THIS IS TEMPORARY CODE; TO BE REMOVED AS PART OF CASH-845
|
||||
}
|
||||
.radio-wrapper.inshop-version {
|
||||
&.selectable-day label span {
|
||||
color: limegreen !important; // TODO - THIS IS TEMPORARY CODE; TO BE REMOVED AS PART OF CASH-845
|
||||
}
|
||||
}
|
||||
.radio-wrapper.mobile-version {
|
||||
&.selectable-day label span {
|
||||
color: red !important; // TODO - THIS IS TEMPORARY CODE; TO BE REMOVED AS PART OF CASH-845
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.timeslots .button-inner-wrapper) {
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
:autocomplete="autocomplete" />
|
||||
<button
|
||||
v-if="includeSearchIcon"
|
||||
class="search-icon-button"
|
||||
type="submit"
|
||||
aria-label="Search button"
|
||||
@click="focusSearchInput" />
|
||||
|
|
@ -185,6 +186,7 @@ export default {
|
|||
// Focus cursor in input when search icon is clicked
|
||||
const field = document.querySelector("input");
|
||||
field.focus();
|
||||
this.$emit("search-icon-click");
|
||||
},
|
||||
async imageChanged(e) {
|
||||
let file = e.target.files[0];
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { GaCategories, GaActions, GaLabels } from "@/constants/analytics";
|
|||
import { getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||
import { headerKeys } from "@/constants/header-keys";
|
||||
import axiosResponseInterceptorMessages from "@/constants/axios-response-interceptor-messages.js";
|
||||
import { endpoints } from "@/constants/endpoints";
|
||||
|
||||
// Add a response interceptor for global axios error handing.
|
||||
axios.interceptors.response.use(
|
||||
|
|
@ -100,7 +101,7 @@ export default {
|
|||
return resolve(response);
|
||||
},
|
||||
(error) => {
|
||||
if (endpoint.toLowerCase().includes("/digitalconsumer-log")) {
|
||||
if (endpoint.toLowerCase().includes(endpoints.LogDigitalConsumer.url)) {
|
||||
return resolve({ data: null, error: "Ignore errors when logging" });
|
||||
} else {
|
||||
if (logApiCall) {
|
||||
|
|
|
|||
|
|
@ -101,11 +101,6 @@ export default {
|
|||
baseMixin.methods.filterOutFees(allLineItems)
|
||||
);
|
||||
|
||||
let vapsLineItemsForSelectedPackage = this.lineItems.vaps;
|
||||
vapsLineItemsForSelectedPackage.forEach((lineItem) => {
|
||||
price += baseMixin.methods.getTotalLineItemPrice(lineItem);
|
||||
});
|
||||
|
||||
if (this.lineItems.promos) {
|
||||
let allLineItems = getArrayOfAllLineItemsAndChildParts(this.lineItems);
|
||||
const promos = getPromosThatMatchLineItemsOnOrder(
|
||||
|
|
@ -119,12 +114,6 @@ export default {
|
|||
|
||||
return price;
|
||||
},
|
||||
afterpayPrice() {
|
||||
let price = this.getTierOnePackagePrice;
|
||||
const adjusted = (price / 4).toFixed(2);
|
||||
|
||||
return `$${adjusted}`;
|
||||
},
|
||||
showAfterpayExtendedPayOption() {
|
||||
return (
|
||||
this.afterpayExtendedPayOptionThreshold &&
|
||||
|
|
@ -175,15 +164,13 @@ export default {
|
|||
> div:last-of-type {
|
||||
color: $gray-650;
|
||||
text-align: left;
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
@include media-breakpoint-up(md) {
|
||||
padding-left: 1rem;
|
||||
|
||||
&#extended-pay-option {
|
||||
max-width: 28rem;
|
||||
}
|
||||
max-width: 26rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ import {
|
|||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import {
|
||||
AppointmentTypeStrings,
|
||||
RouteCodeFlags,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
PRICING_BY_DAY_PART_TYPE,
|
||||
} from "@/constants/schedule-constants";
|
||||
|
|
@ -447,7 +448,7 @@ export default {
|
|||
if (this.isMobileSelected) {
|
||||
return "Mobile";
|
||||
} else {
|
||||
return "Inshop";
|
||||
return "InshopOrDropoff";
|
||||
}
|
||||
},
|
||||
getServiceMinutesMin() {
|
||||
|
|
@ -569,10 +570,14 @@ export default {
|
|||
timeSlotInfo.timeSlot.date
|
||||
)}`;
|
||||
|
||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime
|
||||
)}`;
|
||||
if (this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF) {
|
||||
if (
|
||||
!timeSlotInfo.timeSlot.routeCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)
|
||||
) {
|
||||
navbarButtonText += ` at ${this.getDisplayTextForMilitaryTime(
|
||||
timeSlotInfo.timeSlot.startTime
|
||||
)}`;
|
||||
}
|
||||
} else if (
|
||||
this.appointmentType === AppointmentTypeStrings.MOBILE &&
|
||||
!timeSlotInfo.isPremiumAppointment
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
class="mt-4 timeslots"
|
||||
:class="[
|
||||
isMobileAppointment ? 'is-mobile-appointment' : '',
|
||||
isDropOffAppointment ? 'is-drop-off-appointment' : '',
|
||||
isInshopOrDropOffAppointment ? 'is-inshop-or-drop-off-appointment' : '',
|
||||
]"
|
||||
:answers="availableTimeSlots"
|
||||
groupName="chooseTimeSlot"
|
||||
|
|
@ -354,7 +354,9 @@ export default {
|
|||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||
return this.getAvailableTimeSlotsForMobile(this.timeSlotsForSelectedDate.timeSlots);
|
||||
} else {
|
||||
return this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots);
|
||||
return this.getAvailableTimeSlotsForInshopOrDropOff(
|
||||
this.timeSlotsForSelectedDate.timeSlots
|
||||
);
|
||||
}
|
||||
},
|
||||
answersForDropOffQuestion() {
|
||||
|
|
@ -408,8 +410,8 @@ export default {
|
|||
isMobileAppointment() {
|
||||
return this.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||
},
|
||||
isDropOffAppointment() {
|
||||
return this.appointmentType === AppointmentTypeStrings.DROP_OFF;
|
||||
isInshopOrDropOffAppointment() {
|
||||
return this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF;
|
||||
},
|
||||
shouldDisplayDropOffAlert() {
|
||||
return this.isDropOffRouteCode(this.selectedAnswerForDropOff);
|
||||
|
|
@ -472,6 +474,26 @@ export default {
|
|||
};
|
||||
});
|
||||
},
|
||||
getAvailableTimeSlotsForInshopOrDropOff(timeSlotsForSelectedDate) {
|
||||
const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => {
|
||||
let buttonLabelValue;
|
||||
if (timeSlot.id.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
buttonLabelValue = this.dropoffButtonText;
|
||||
} else if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
buttonLabelValue = this.overnightDropoffButtonText;
|
||||
} else if (this.isSameDay) {
|
||||
buttonLabelValue = this.sameDayDropoffButtonText;
|
||||
} else {
|
||||
buttonLabelValue = militaryToTwelveHourTime(timeSlot.startTime);
|
||||
}
|
||||
return {
|
||||
value: timeSlot.id,
|
||||
buttonLabel: buttonLabelValue,
|
||||
};
|
||||
});
|
||||
|
||||
return availableTimeSlots;
|
||||
},
|
||||
getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) {
|
||||
const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => {
|
||||
const readableTime = `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime(
|
||||
|
|
|
|||
|
|
@ -219,7 +219,13 @@ describe("service-location.vue", () => {
|
|||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
/* ******NOTE: if we ever want to revert back to the old way of service location using shopQuestion instead of shopQuestionPopup uncomment all 30 of the lines in this file that read - wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn(); - , and commment all of the blocks of code referencing shopQuestionPopup directly under them. Also remove reference to shopQuestionPopup in the setupMocks function*/
|
||||
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({ ref: "shopQuestionPopup" });
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
const mobileFeePart = {
|
||||
partNumber: "MOBILE FEE",
|
||||
|
|
@ -387,7 +393,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -414,7 +426,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -441,7 +459,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -468,7 +492,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -495,7 +525,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -523,7 +559,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -551,7 +593,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -579,7 +627,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -607,7 +661,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -635,7 +695,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -663,7 +729,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -691,7 +763,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -719,7 +797,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -747,7 +831,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -775,7 +865,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -806,7 +902,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -833,7 +935,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -860,7 +968,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -888,7 +1002,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -916,7 +1036,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -944,7 +1070,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -974,7 +1106,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1002,7 +1140,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1030,7 +1174,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1058,7 +1208,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1086,7 +1242,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1114,7 +1276,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1142,7 +1310,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1172,7 +1346,13 @@ describe("service-location.vue", () => {
|
|||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
//wrapper.vm.$refs.shopQuestion.initializeComponent = jest.fn();
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({
|
||||
ref: "shopQuestionPopup",
|
||||
});
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
|
||||
// Act
|
||||
await serviceLocation.beforeRouteEnter.call(
|
||||
|
|
@ -1199,5 +1379,12 @@ function setupMocks({ mountOptionsMockData = {} }) {
|
|||
const mountOptions = getMountOptions(mountOptionsMockData);
|
||||
const wrapper = shallowMount(serviceLocation, mountOptions);
|
||||
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||
if (!wrapper.vm.shopProviderData) {
|
||||
wrapper.vm.shopProviderData = { shopProviders: [] };
|
||||
}
|
||||
const shopQuestionPopupComponent = wrapper.findComponent({ ref: "shopQuestionPopup" });
|
||||
if (shopQuestionPopupComponent.exists()) {
|
||||
shopQuestionPopupComponent.vm.initializeComponent = jest.fn();
|
||||
}
|
||||
return { wrapper, apiPromise };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,6 +89,19 @@
|
|||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<button-question
|
||||
v-if="selectedAppointmentType == appointmentTypeStrings.IN_SHOP"
|
||||
class="shop-question-button"
|
||||
ref="buttonQuestion"
|
||||
:answers="selectedShopAnswer"
|
||||
:modelValue="selectedProvider?.providerNumber"
|
||||
:isMultiSelect="false"
|
||||
:readonly="true"
|
||||
:questionText="questionText"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start" />
|
||||
<div class="text-center">
|
||||
<textBlock
|
||||
v-if="mobileFeeApplies && isMobileSelected"
|
||||
|
|
@ -97,14 +110,24 @@
|
|||
typeStyle="caption"
|
||||
class="ps-4 pe-4 mt-4" />
|
||||
</div>
|
||||
<shopQuestion
|
||||
ref="shopQuestion"
|
||||
v-show="isShopQuestionDisplayed"
|
||||
v-model="selectedProvider"
|
||||
<shopQuestionPopup
|
||||
modalWidgetName="ShopQuestionPopupWidget"
|
||||
:selectedAppointmentType="selectedAppointmentType"
|
||||
:modelValue="{
|
||||
zipCode: zipCode,
|
||||
providerNumber: selectedProvider?.providerNumber,
|
||||
}"
|
||||
:preselectedProviderNumber="selectedProvider?.providerNumber"
|
||||
:shopProviderData="shopProviderData"
|
||||
:isServiceableInshop="isServiceableInshop"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@shop-selected="onShopSelected"
|
||||
@update:modelValue="onShopModelUpdated"
|
||||
@updated-zipcode-ctu="setZipcodeCtu"
|
||||
@update-shop-provider-data="shopProviderData = $event"
|
||||
:zipCode="zipCode"
|
||||
:isDisplayed="isShopQuestionDisplayed"
|
||||
cmsWidgetName="ShopQuestionWidget" />
|
||||
cmsWidgetName="YourSafeliteShopWidget" />
|
||||
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
|
||||
|
|
@ -126,6 +149,10 @@ import alert from "@/ux-components/alert/alert";
|
|||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
||||
import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question";
|
||||
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
||||
import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button";
|
||||
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||
|
||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||
|
|
@ -212,6 +239,7 @@ export default {
|
|||
shopProviderData: null,
|
||||
navigatingForward: false,
|
||||
isMobileAddressValid: true,
|
||||
shopListButton: shopListButton,
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -421,6 +449,57 @@ export default {
|
|||
isForwardActionDisabled() {
|
||||
return this.displayNoShopsAlert || !this.isMobileAddressValid;
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split("T")[0];
|
||||
const formattedEndDate = endDate.toISOString().split("T")[0];
|
||||
|
||||
return {
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType,
|
||||
};
|
||||
},
|
||||
selectedShopAnswer() {
|
||||
const toTitleCase = (str) => {
|
||||
if (!str) return "";
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
if (this.selectedProvider && this.selectedProvider.address) {
|
||||
const provider = this.shopProviderData?.shopProviders?.find(
|
||||
(p) => p.providerNumber === this.selectedProvider?.providerNumber
|
||||
);
|
||||
const streetAddress = toTitleCase(this.selectedProvider.address.streetAddress);
|
||||
const city = toTitleCase(this.selectedProvider.address.city);
|
||||
const state = this.selectedProvider.address.state;
|
||||
const zipCode = this.selectedProvider.address.zipCode;
|
||||
const distanceInMiles = provider ? Math.round(provider.distanceInMiles * 2) / 2 : 0;
|
||||
|
||||
return [
|
||||
{
|
||||
buttonLabel: `${city}`,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
additionalButtonData: this.additionalButtonData,
|
||||
value: this.selectedProvider.providerNumber,
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
questionText() {
|
||||
return this.getCmsContent("YourSafeliteShopWidget", "QuestionText");
|
||||
},
|
||||
appointmentTypeStrings() {
|
||||
return AppointmentTypeStrings;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
|
|
@ -669,8 +748,6 @@ export default {
|
|||
this.selectedProvider.address.zipCode = null;
|
||||
this.selectedProvider.address.zipCodeCtu = null;
|
||||
} else {
|
||||
// if we have a provider.zipCodeCtu that's different than the servicelocation.zipCodeCtu then they
|
||||
// may have selected a shop in a different ctu. change the servicelocation zip/ctu if different
|
||||
if (this.zipCodeCtu != this.selectedProvider.address.zipCodeCtu) {
|
||||
ctu = this.selectedProvider.address.zipCodeCtu;
|
||||
}
|
||||
|
|
@ -756,6 +833,60 @@ export default {
|
|||
startTime: "08:00",
|
||||
};
|
||||
},
|
||||
onShopSelected(providerObject) {
|
||||
const current = this.shopProviderData?.shopProviders?.find(
|
||||
(p) => p.providerNumber === this.selectedProvider?.providerNumber
|
||||
);
|
||||
if (current) {
|
||||
this.selectedProvider = current;
|
||||
}
|
||||
|
||||
let provider = this.shopProviderData?.shopProviders?.find(
|
||||
(p) => p.providerNumber === providerObject?.providerNumber
|
||||
);
|
||||
if (!provider && this.shopProviderData?.shopProviders?.length > 0) {
|
||||
provider = this.shopProviderData.shopProviders[0];
|
||||
}
|
||||
this.selectedProvider = provider;
|
||||
if (provider && provider.address) {
|
||||
this.zipCode = provider.address.zipCode;
|
||||
this.state = provider.address.state;
|
||||
}
|
||||
if (
|
||||
!this.selectedProvider ||
|
||||
!this.shopProviderData?.shopProviders?.some(
|
||||
(p) => p.providerNumber === this.selectedProvider?.providerNumber
|
||||
)
|
||||
) {
|
||||
this.selectedProvider = this.shopProviderData?.shopProviders?.[0];
|
||||
}
|
||||
if (providerObject && providerObject.address) {
|
||||
this.zipCode = providerObject.address.zipCode;
|
||||
this.state = providerObject.address.state;
|
||||
}
|
||||
},
|
||||
setZipcodeCtu(zipcodeCtu) {
|
||||
this.zipCodeCtu = zipcodeCtu;
|
||||
},
|
||||
onShopModelUpdated(newModel) {
|
||||
if (newModel.zipCode) {
|
||||
this.zipCode = newModel.zipCode;
|
||||
}
|
||||
if (newModel.zipCodeCtu) {
|
||||
this.zipCodeCtu = newModel.zipCodeCtu;
|
||||
}
|
||||
if (newModel.state) {
|
||||
this.state = newModel.state;
|
||||
}
|
||||
if (this.shopProviderData && newModel.selectedProviderNumber) {
|
||||
const provider = this.shopProviderData.shopProviders.find(
|
||||
(p) => p.providerNumber === newModel.selectedProviderNumber
|
||||
);
|
||||
if (provider) {
|
||||
this.selectedProvider = provider;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
zipCode: {
|
||||
|
|
@ -768,7 +899,7 @@ export default {
|
|||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
this.isMobileAddressValid = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -781,7 +912,7 @@ export default {
|
|||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
this.selectedProvider = this.shopProviderData.shopProviders[0];
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -796,7 +927,8 @@ export default {
|
|||
Form,
|
||||
loadingModal,
|
||||
contentGroupModal,
|
||||
shopQuestion,
|
||||
shopQuestionPopup,
|
||||
buttonQuestion,
|
||||
textBlock,
|
||||
},
|
||||
};
|
||||
|
|
@ -822,4 +954,8 @@ export default {
|
|||
color: $black;
|
||||
}
|
||||
}
|
||||
.shop-question-button .list-button-content {
|
||||
background: $blue-100 !important;
|
||||
box-shadow: 0 0 0 1px $primary !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@
|
|||
questionAlignment="center"
|
||||
cornerStyle="rounded"
|
||||
mask="#####"
|
||||
:includeSearchIcon="includeSearchIcon"
|
||||
@search-icon-click="$emit('search-icon-click')"
|
||||
:displayQuestionText="false"
|
||||
isRequired
|
||||
validationRules="zip-required|zip-format" />
|
||||
:isRequired="isRequired"
|
||||
:validationRules="computedValidationRules" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -31,6 +33,14 @@ export default {
|
|||
serviceZipCode: String,
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
isRequired: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
includeSearchIcon: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
value: {
|
||||
|
|
@ -41,6 +51,9 @@ export default {
|
|||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
},
|
||||
computedValidationRules() {
|
||||
return this.isRequired ? "zip-required|zip-format" : "zip-format";
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textboxQuestion,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,735 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div v-if="isDisplayed" class="shop-question" aria-live="polite">
|
||||
<alert
|
||||
ref="alertDropoffInformation"
|
||||
v-if="displayDropoffInformation"
|
||||
class="mb-4 drop-off-alert"
|
||||
cmsWidgetName="AlertDropoffInformationWidget"
|
||||
alertClass="alert-info"
|
||||
v-bind:isDismissible="false" />
|
||||
<div class="modal-link">
|
||||
<text-link
|
||||
linkType="text"
|
||||
:text="shopQuestionLinkText"
|
||||
:shopProviderData="shopProviderData"
|
||||
href="#!"
|
||||
@click-event="openModal"></text-link>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<modal
|
||||
ref="shopQuestionModal"
|
||||
:headerText="modalHeaderText"
|
||||
:onModalOpenedCallback="onModalOpened"
|
||||
:onModalClosedCallback="onModalClosed"
|
||||
:footerButtonText="modalFooterText"
|
||||
@footer-button-event="SetZipCodeAndShop">
|
||||
<div class="zip-search-group">
|
||||
<div class="zip-search-input">
|
||||
<serviceZipQuestion
|
||||
ref="serviceZipQuestion"
|
||||
class="shop-question-zipcode"
|
||||
customInputId="serviceZipCode"
|
||||
v-model="internalModel.zipCode"
|
||||
v-on="{ 'textboxQuestionEvent.inputIdAssigned': onInputIdAssigned }"
|
||||
cmsWidgetName="ServiceZipQuestionWidget"
|
||||
@search-icon-click="onSearchZip"
|
||||
@keydown.enter="onSearchZip"
|
||||
includeSearchIcon
|
||||
:isRequired="false" />
|
||||
</div>
|
||||
</div>
|
||||
<alert
|
||||
ref="alertMilitaryBaseZip"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||
v-if="displayMilitaryZipAlert"
|
||||
alertClass="alert-warning" />
|
||||
|
||||
<alert
|
||||
ref="alertMobileOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
v-if="displayServiceableMobileOnly"
|
||||
alertClass="alert-warning" />
|
||||
|
||||
<alert
|
||||
ref="alertRecalNoMobile"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
v-if="displayRecalibrationWarning"
|
||||
@text-link-clicked="openModalAction"
|
||||
alertClass="alert-warning" />
|
||||
|
||||
<alert
|
||||
ref="alertInshopOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
v-if="displayServiceableInshopOnly"
|
||||
alertClass="alert-warning" />
|
||||
|
||||
<alert
|
||||
ref="alertNoShops"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
v-if="displayNoShopsAlert"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertMobileFeeFree"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileFeeFreeWidget"
|
||||
v-if="showMobileFreeAlert"
|
||||
alertClass="alert-success" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="answers"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
v-model="selectedProviderNumber"
|
||||
isRequired
|
||||
validationRules="option-required" />
|
||||
<div class="show-more-shops-link">
|
||||
<textLink
|
||||
v-if="displaySeeMoreLocationsLink"
|
||||
ref="showMoreShopsLink"
|
||||
id="showMoreShopsId2"
|
||||
cmsWidgetName="ShowMoreShopsLinkWidget"
|
||||
linkType="text"
|
||||
:text="showMoreShopsLinkText"
|
||||
href="#!"
|
||||
@click-event="getNextShopsFromList(3)"
|
||||
:aria-label="showMoreShopsLinkText" />
|
||||
</div>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import modal from "@/digital-components/modal/modal";
|
||||
import textLink from "@/ux-components/text-link/text-link.vue";
|
||||
import serviceZipQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import alert from "@/ux-components/alert/alert.vue";
|
||||
import shopListButton from "./shop-list-button/shop-list-button";
|
||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||
|
||||
// Supporting files
|
||||
import { defineRule } from "vee-validate";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
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";
|
||||
|
||||
import { Provider } from "@/layouts/service-location/classes/provider";
|
||||
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getPricedRecycleFeePart,
|
||||
getServiceabilityDetails,
|
||||
getBillToAccountNumber,
|
||||
getClosestApplicableShops,
|
||||
getShopProviderData,
|
||||
getZipCodeData,
|
||||
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||
|
||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
function getShopsByZip(zipCode, shops, numberToGet = 3) {
|
||||
return shops
|
||||
.filter((shop) => shop.address && shop.address.zipCode && shop.address.zipCode !== "")
|
||||
.sort((a, b) => a.distanceInMiles - b.distanceInMiles)
|
||||
.slice(0, numberToGet);
|
||||
}
|
||||
|
||||
export default {
|
||||
name: "shop-question-popup",
|
||||
mixins: [baseMixin],
|
||||
data() {
|
||||
return {
|
||||
isShopQuestionDisplayed: true,
|
||||
internalModel: this.copyModel(this.modelValue),
|
||||
answers: [],
|
||||
shopListButton: shopListButton,
|
||||
shopIndex: 0,
|
||||
displaySeeMoreLocationsLink: false,
|
||||
serviceZipCodeTextInputId: "",
|
||||
localShopProviderData: this.shopProviderData,
|
||||
selectedProviderNumber: null,
|
||||
isLoadingShops: false,
|
||||
lastSearchedZip: "",
|
||||
lastSuccessfulZip: "",
|
||||
hasLoadedShopData: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
selectedAppointmentType: String,
|
||||
shopProviderData: Object,
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
state: "",
|
||||
zipCode: "",
|
||||
}),
|
||||
},
|
||||
isDisplayed: Boolean,
|
||||
modelWidgetName: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isServiceableInshop: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
zipCode: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
preSelectedProviderNumber: {
|
||||
type: [String, Number],
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
shopQuestionLinkText() {
|
||||
return this.getCmsContent("ChangeMyLocationLinkWidget", "Text");
|
||||
},
|
||||
modalName() {
|
||||
return this.modelWidgetName;
|
||||
},
|
||||
modalHeaderText() {
|
||||
return this.getCmsContent("ShopQuestionWidget", "QuestionText");
|
||||
},
|
||||
selectShopText() {
|
||||
return this.getCmsContent("YourSafeliteShopWidget", "QuestionText");
|
||||
},
|
||||
modal() {
|
||||
return this.$refs.shopQuestionModal;
|
||||
},
|
||||
shopProviders() {
|
||||
return this.localShopProviderData?.shopProviders ?? [];
|
||||
},
|
||||
modalFooterText() {
|
||||
return this.getCmsContent("SaveLocationWidget", "Text");
|
||||
},
|
||||
selectedValue: {
|
||||
get: function () {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {},
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split("T")[0];
|
||||
const formattedEndDate = endDate.toISOString().split("T")[0];
|
||||
|
||||
return {
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType,
|
||||
};
|
||||
},
|
||||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent("ShowMoreShopsLinkWidget", "Text");
|
||||
},
|
||||
displayNoShopsAlert() {
|
||||
return this.hasLoadedShopData && this.answers.length === 0;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
openModal(event) {
|
||||
if (event) event.preventDefault();
|
||||
if (
|
||||
!this.shopProviderData ||
|
||||
!this.shopProviderData.shopProviders ||
|
||||
!this.shopProviderData.shopProviders.length
|
||||
) {
|
||||
// Optionally show a loading message or disable the link
|
||||
return;
|
||||
}
|
||||
this.$refs.shopQuestionModal.openModal();
|
||||
},
|
||||
getSelectedProviderObject(providerNumber) {
|
||||
const provider =
|
||||
this.shopProviders?.find((provider) => provider.providerNumber == providerNumber) ??
|
||||
new Provider();
|
||||
|
||||
return provider;
|
||||
},
|
||||
async getNextShopsFromList(numberToGet = 3) {
|
||||
const logFirstShopsDisplayed = this.shopIndex == 0;
|
||||
|
||||
const shopIterator = (array, n) => {
|
||||
const l = array.length;
|
||||
return () => {
|
||||
const end = this.shopIndex + n;
|
||||
const part = array.slice(this.shopIndex, end);
|
||||
this.shopIndex = end < l ? end : this.shopProviders.length;
|
||||
return part;
|
||||
};
|
||||
};
|
||||
|
||||
const toTitleCase = (str) => {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
const nextShop = shopIterator(this.shopProviders, numberToGet);
|
||||
|
||||
// Map API result data
|
||||
const mappedData = nextShop().map((shopProvider) => {
|
||||
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
|
||||
const city = toTitleCase(shopProvider.address.city);
|
||||
const state = shopProvider.address.state;
|
||||
const zipCode = shopProvider.address.zipCode;
|
||||
const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2;
|
||||
|
||||
return {
|
||||
buttonLabel: city,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
additionalButtonData: this.additionalButtonData,
|
||||
value: shopProvider.providerNumber,
|
||||
};
|
||||
});
|
||||
|
||||
var gaAction = this.GaActions.MORE_LOCATIONS_CLICKED;
|
||||
if (logFirstShopsDisplayed) {
|
||||
gaAction = this.GaActions.SHOPS_FIRST_DISPLAYED;
|
||||
}
|
||||
if (
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP ||
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.DROP_OFF
|
||||
) {
|
||||
var shops = mappedData.map((shop) => {
|
||||
if (shop.value.length > 5 && shop.value.startsWith("00")) {
|
||||
return shop.value.substring(1);
|
||||
} else {
|
||||
return shop.value;
|
||||
}
|
||||
});
|
||||
|
||||
var joinedShops = shops.join(",");
|
||||
if (!joinedShops) {
|
||||
joinedShops = "no-shops";
|
||||
}
|
||||
|
||||
this.pushEventToGA(this.GaCategories.SERVICE_LOCATION, gaAction, joinedShops, true);
|
||||
}
|
||||
|
||||
if (this.answers.length === 0) {
|
||||
this.answers = mappedData;
|
||||
} else {
|
||||
mappedData.forEach((shop) => {
|
||||
this.answers.push(shop);
|
||||
});
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (this.shopIndex == this.shopProviders.length) {
|
||||
this.displaySeeMoreLocationsLink = false;
|
||||
} else {
|
||||
this.displaySeeMoreLocationsLink = true;
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
this.scrollToPageBottom();
|
||||
},
|
||||
async handleUpdate(selectedShopIndex = null) {
|
||||
this.resetAnswers();
|
||||
if (selectedShopIndex >= 3) {
|
||||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await nextTick();
|
||||
}
|
||||
},
|
||||
copyModel(modelToCopy) {
|
||||
return {
|
||||
state: modelToCopy.state,
|
||||
zipCode: modelToCopy.zipCode,
|
||||
};
|
||||
},
|
||||
resetAnswers() {
|
||||
this.answers = [];
|
||||
this.shopIndex = 0;
|
||||
},
|
||||
onModalOpened() {
|
||||
this.shopIndex = 3;
|
||||
this.internalModel = this.copyModel(this.modelValue);
|
||||
this.internalModel.zipCode = this.zipCode;
|
||||
this.localShopProviderData = this.shopProviderData;
|
||||
this.answers = [];
|
||||
this.updateShopsForZip(this.internalModel.zipCode);
|
||||
this.focusOnZipInput();
|
||||
this.selectedProviderNumber = this.preSelectedProviderNumber;
|
||||
if (this.internalModel.zipCode && this.shopProviders.length > 0) {
|
||||
this.updateShopsForZip(this.internalModel.zipCode);
|
||||
} else {
|
||||
this.internalModel.zipCode = this.zipCode;
|
||||
this.updateShopsForZip(this.internalModel.zipCode);
|
||||
}
|
||||
if (
|
||||
(!this.selectedProviderNumber ||
|
||||
!this.shopProviders.some(
|
||||
(p) => p.providerNumber == this.selectedProviderNumber
|
||||
)) &&
|
||||
this.shopProviders.length > 0
|
||||
) {
|
||||
this.selectedProviderNumber = this.shopProviders[0].providerNumber;
|
||||
}
|
||||
},
|
||||
closeModal() {
|
||||
this.modal.closeModal();
|
||||
},
|
||||
onModalClosed() {
|
||||
this.internalModel = this.copyModel(this.modelValue);
|
||||
this.selectedProviderNumber = this.preSelectedProviderNumber;
|
||||
this.resetsOnZipInput();
|
||||
let selectedProvider = this.shopProviders.find(
|
||||
(provider) => provider.providerNumber == this.selectedProviderNumber
|
||||
);
|
||||
if (!selectedProvider && this.shopProviders.length > 0) {
|
||||
selectedProvider = this.shopProviders[0];
|
||||
}
|
||||
},
|
||||
resetsOnZipInput() {
|
||||
this.resetAlerts();
|
||||
},
|
||||
async onSearchZip(event) {
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
const zip = this.internalModel.zipCode;
|
||||
if (this.isVehicleHeavyTruck) {
|
||||
// check the location endpoint to verify this zip can service a heavy truck
|
||||
const closestShops = await getClosestApplicableShops(
|
||||
this.internalModel.zipCode,
|
||||
this.carId,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
if (!closestShops || closestShops.providers?.length === 0) {
|
||||
this.displayNoServiceAlert = true;
|
||||
this.focusOnZipInput();
|
||||
this.resetModalButtonStyle();
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
getShopProviderData(zip).then(async (result) => {
|
||||
this.localShopProviderData = result.data;
|
||||
this.updateShopsForZip(this.internalModel.zipCode);
|
||||
if (this.selectedAppointmentType === "Mobile") {
|
||||
this.selectedProvider = new Provider(
|
||||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
async updateShopsForZip(zipCode) {
|
||||
if (!this.selectedAppointmentType) {
|
||||
this.answers = [];
|
||||
this.isLoadingShops = false;
|
||||
return;
|
||||
}
|
||||
this.lastSearchedZip = zipCode;
|
||||
if (!zipCode) {
|
||||
this.isLoadingShops = false;
|
||||
this.answers = [];
|
||||
return;
|
||||
}
|
||||
this.isLoadingShops = true;
|
||||
if (!zipCode || !this.shopProviders.length) {
|
||||
this.handleUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
const sortedShops = getShopsByZip(zipCode, this.shopProviders, 3);
|
||||
|
||||
const toTitleCase = (str) => {
|
||||
return str.replace(/\w\S*/g, function (txt) {
|
||||
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
|
||||
});
|
||||
};
|
||||
|
||||
const mappedData = sortedShops.map((shopProvider) => {
|
||||
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
|
||||
const city = toTitleCase(shopProvider.address.city);
|
||||
const state = shopProvider.address.state;
|
||||
const zipCode = shopProvider.address.zipCode;
|
||||
const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2;
|
||||
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split("T")[0];
|
||||
const formattedEndDate = endDate.toISOString().split("T")[0];
|
||||
|
||||
return {
|
||||
buttonLabel: city,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
additionalButtonData: {
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType,
|
||||
},
|
||||
value: shopProvider.providerNumber,
|
||||
};
|
||||
});
|
||||
this.answers = mappedData;
|
||||
this.shopIndex = mappedData.length;
|
||||
this.displaySeeMoreLocationsLink = this.shopIndex < this.shopProviders.length;
|
||||
if (mappedData.length > 0) {
|
||||
this.lastSuccessfulZip = zipCode;
|
||||
}
|
||||
this.isLoadingShops = false;
|
||||
},
|
||||
onInputIdAssigned(inputId) {
|
||||
this.serviceZipCodeTextInputId = inputId;
|
||||
},
|
||||
focusOnZipInput() {
|
||||
const input = document.getElementById(this.serviceZipCodeTextInputId);
|
||||
input?.focus();
|
||||
},
|
||||
resetAlerts() {
|
||||
this.displayInvalidZipAlert = false;
|
||||
this.displayNoServiceAlert = false;
|
||||
},
|
||||
async SetZipCodeAndShop() {
|
||||
const selectedProvider = this.shopProviders.find(
|
||||
(provider) => provider.providerNumber == this.selectedProviderNumber
|
||||
);
|
||||
this.resetAlerts();
|
||||
|
||||
const zipCodeData = await this.getZipCodeData(
|
||||
selectedProvider.address.zipCode,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.displayInvalidZipAlert = true;
|
||||
this.focusOnZipInput();
|
||||
this.resetModalButtonStyle();
|
||||
} else {
|
||||
if (this.isVehicleHeavyTruck) {
|
||||
// check the location endpoint to verify this zip can service a heavy truck
|
||||
const closestShops = await getClosestApplicableShops(
|
||||
selectedProvider.address.zipCode,
|
||||
this.carId,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
if (!closestShops || closestShops.providers?.length === 0) {
|
||||
this.displayNoServiceAlert = true;
|
||||
this.focusOnZipInput();
|
||||
this.resetModalButtonStyle();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
selectedProvider.address.state = zipCodeData.state;
|
||||
selectedProvider.address.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
|
||||
// retrieve mobile fee part
|
||||
const serviceZipCode = selectedProvider.address.zipCode;
|
||||
const mobileFeePart = await getPricedMobileFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
// retrieve recycle fee part
|
||||
const recycleFeePart = await getPricedRecycleFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
// retrieve serviceability details
|
||||
const serviceabilityDetails = await getServiceabilityDetails(
|
||||
serviceZipCode,
|
||||
null,
|
||||
"service-location"
|
||||
);
|
||||
|
||||
const billToAccountNumber = await getBillToAccountNumber(
|
||||
selectedProvider.address.zipCodeCtu
|
||||
);
|
||||
|
||||
// update content related to service zip code
|
||||
this.$emit("updated-mobile-fee-part", mobileFeePart);
|
||||
this.$emit("updated-recycle-fee-part", recycleFeePart);
|
||||
this.$emit("updated-serviceability", serviceabilityDetails.data);
|
||||
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
|
||||
this.$emit("updated-bill-to-account-number", billToAccountNumber);
|
||||
this.$emit("updated-zipcode-ctu", selectedProvider.address.zipCodeCtu);
|
||||
|
||||
this.$emit("update:modelValue", this.selectedValue);
|
||||
this.$emit("update-shop-provider-data", this.localShopProviderData);
|
||||
this.$emit("shop-selected", selectedProvider);
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
shopProviderData: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
this.localShopProviderData = newVal;
|
||||
this.hasLoadedShopData = true;
|
||||
if (this.internalModel && this.internalModel.zipCode) {
|
||||
this.updateShopsForZip(this.internalModel.zipCode);
|
||||
}
|
||||
},
|
||||
},
|
||||
preSelectedProviderNumber(newVal) {
|
||||
this.selectedProviderNumber = newVal;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
modal,
|
||||
textLink,
|
||||
serviceZipQuestion,
|
||||
buttonQuestion,
|
||||
alert,
|
||||
},
|
||||
mounted() {
|
||||
this.handleUpdate();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.shop-question {
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
|
||||
a {
|
||||
@include responsive-font-size-md(0.875rem, 1rem);
|
||||
}
|
||||
|
||||
.button-question {
|
||||
.question-text {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drop-off-alert {
|
||||
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A");
|
||||
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;
|
||||
gap: 0.25rem;
|
||||
|
||||
.alert-heading {
|
||||
text-align: left;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
.modal-link {
|
||||
text-align: center;
|
||||
}
|
||||
.modal.modal-component .modal-dialog .modal-content .modal-body .textbox-question {
|
||||
padding: 0;
|
||||
}
|
||||
.zip-search-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
border-radius: 48px;
|
||||
padding-left: 16px;
|
||||
border: 1px solid #ccc;
|
||||
background: #fff;
|
||||
margin-bottom: 20px;
|
||||
@include media-breakpoint-up(md) {
|
||||
height: auto;
|
||||
padding-left: 0;
|
||||
}
|
||||
.zip-search-input {
|
||||
align-items: stretch;
|
||||
flex: 1 1 0;
|
||||
height: 100%;
|
||||
margin-bottom: 0;
|
||||
input {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
background: transparent;
|
||||
box-sizing: border-box;
|
||||
border-radius: 48px 0 0 48px;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #e5f1fa;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
|
||||
border: none;
|
||||
|
||||
border-radius: 0 48px 48px 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
@media (max-width: 767.98px) {
|
||||
.zip-search-group {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
.show-more-shops-link a {
|
||||
text-align: center;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
.shop-question-zipcode .search-icon-button {
|
||||
background-color: #e5f1fa !important;
|
||||
border-radius: 0 2.5rem 2.5rem 0;
|
||||
}
|
||||
.shop-question-zipcode .search-icon-button:hover,
|
||||
.shop-question-zipcode .search-icon-button:focus {
|
||||
border: 1px solid $gray-500;
|
||||
box-shadow: 0 0 0 4px $blue-300;
|
||||
background-color: #e5f1fa;
|
||||
outline: none;
|
||||
}
|
||||
.shop-question-zipcode .input-wrapper.has-search-icon .form-control {
|
||||
border-radius: 2.5rem;
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue