diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index 50ecfeb88..e6b44e130 100644 --- a/src/digital-components/date-picker/date-picker.vue +++ b/src/digital-components/date-picker/date-picker.vue @@ -56,15 +56,19 @@ :class="[!isLoading ? 'date-picker-hidden' : '']" loaderColor="blue" loaderPosition="center" /> +
+ +
+ - @@ -78,6 +82,7 @@ import { convertDateToDateString, convertDateStringToDate, } from "@/layouts/schedule/helpers/schedule-helper"; +import { useField, ErrorMessage } from "vee-validate"; export default { name: "datePicker", @@ -112,6 +117,32 @@ export default { return []; }, }, + validationRules: { + type: String, + default: "", + }, + }, + setup(props) { + const propsClone = Object.assign({}, props); + const modelValue = propsClone.modelValue; + + const fieldOptions = { + value: modelValue, + initialValue: modelValue, + }; + + const { errorMessage, handleBlur, handleChange, meta, validate, errors, resetField } = + useField("date-of-month", props.validationRules, fieldOptions); + + return { + errorMessage, + handleBlur, + handleChange, + validate, + meta, + errors, + resetField, + }; }, computed: { todayString() { @@ -419,7 +450,7 @@ export default { monthsAfterToLoadOffset (number), hideSecondMonth (boolean), preSelectedDate (string) - + data used: todayDate (date object) this.hideSomeDaysForInitialView (string) @@ -615,41 +646,39 @@ export default { }); }); }, - scrollToElement(elementId, speed, easing) { - // TODO - needs to be cleaned up & refactored - function scrollTopSmooth(wrapper, target, duration = 300, timingName = "linear") { - const initY = wrapper.scrollTop; - const wrapperRect = wrapper.getBoundingClientRect(); - const targetRect = target.getBoundingClientRect(); - const targetY = targetRect.top - wrapperRect.top - BUFFER_OFFSET; - const timingFunc = TIMINGFUNC_MAP[timingName]; - let start = null; - - const step = (timestamp) => { - start = start || timestamp; - const progress = timestamp - start, - // Growing from 0 to 1 - time = Math.min(1, (timestamp - start) / duration); - const percentageNew = timingFunc(time); - const distanceToGo = targetY; - const thisDistance = percentageNew * distanceToGo; - - wrapper.scrollTo(0, initY + thisDistance); - if (percentageNew < 1) { - window.requestAnimationFrame(step); - } - }; - window.requestAnimationFrame(step); - } - - const wrapper = document.getElementById("date-picker-fieldset"); - const targetMonth = document.getElementById(elementId); - - scrollTopSmooth(wrapper, targetMonth, 800, "ease-in-out"); + scrollToElement(elementId, duration = 800, easing = "ease-in-out") { + const wrapper = document.querySelector(".page-container-grouped-styles"); + const target = document.getElementById(elementId); + const initY = wrapper.scrollTop; + const wrapperRect = wrapper.getBoundingClientRect(); + const targetRect = target.getBoundingClientRect(); + const targetY = targetRect.top - wrapperRect.top - BUFFER_OFFSET; + const timingFunc = TIMINGFUNC_MAP[easing]; + let start = null; + const step = (timestamp) => { + start = start || timestamp; + const time = Math.min(1, (timestamp - start) / duration); + const percentageNew = timingFunc(time); + const distanceToGo = targetY; + const thisDistance = percentageNew * distanceToGo; + wrapper.scrollTo(0, initY + thisDistance); + if (percentageNew < 1) { + window.requestAnimationFrame(step); + } + }; + window.requestAnimationFrame(step); + }, + }, + watch: { + modelValue(newValue, oldValue) { + this.resetField({ + value: newValue, + }); }, }, components: { loader, + ErrorMessage, }, }; @@ -660,27 +689,22 @@ export default { max-height: 0; } .date-picker { - overflow: hidden; position: relative; flex-grow: 1; display: flex; flex-direction: column; fieldset { - overflow-y: auto; flex-grow: 1; position: relative; - padding-bottom: 6rem; // arbitrary amount to provide enough spacing for scroll animation - max-height: 21.25rem; // 340px... arbitrary amount to not push View More link out of view on iphones } .loader { - position: absolute; height: 2rem; - width: 2rem; + width: calc(100% - 1.5rem); &::after { - width: 100%; - height: 100%; + width: 1.5rem; + height: 1.5rem; } } .calendar-grid-container { @@ -813,9 +837,9 @@ export default { display: flex; justify-content: center; align-items: center; - width: 3rem; + min-width: 2.5rem; + width: 2.5rem; height: 2.5rem; - min-width: 3rem; span { &.small { @@ -916,16 +940,15 @@ export default { margin-bottom: 0; overflow: hidden; } - &.last-available-month:not(&.month-hidden) { - margin-bottom: 14rem; - } } .btn-link { font-weight: 500; text-underline-offset: 4px; - position: absolute; - bottom: 0; + flex-grow: 0; + &:focus { + box-shadow: none; + } } .past { @@ -997,4 +1020,10 @@ export default { text-underline-offset: 4px; z-index: 2; } + +.form-test-error { + margin: 0 auto; + max-width: 414px; + text-align: left; +} diff --git a/src/fmg-components/funnel-sub-header/funnel-sub-header.vue b/src/fmg-components/funnel-sub-header/funnel-sub-header.vue index 6beeaf321..a5cdf5c0b 100644 --- a/src/fmg-components/funnel-sub-header/funnel-sub-header.vue +++ b/src/fmg-components/funnel-sub-header/funnel-sub-header.vue @@ -2,7 +2,7 @@
-
+
{{ text }} diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js index 099a3778e..6895b5d0b 100644 --- a/src/layouts/quote/quote.spec.js +++ b/src/layouts/quote/quote.spec.js @@ -162,6 +162,11 @@ describe("quote.vue", () => { }, referralNumber: "1234567", }, + payment: { + insuranceCoverage: { + isVerified: false, + }, + }, }; let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); @@ -185,6 +190,11 @@ describe("quote.vue", () => { glassParts: ["item", "item2"], }, }, + payment: { + insuranceCoverage: { + isVerified: false, + }, + }, }; let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue index e48524336..16a934d12 100644 --- a/src/layouts/quote/quote.vue +++ b/src/layouts/quote/quote.vue @@ -150,7 +150,7 @@ export default { (store.getters.order.damage.isRepair || (store.getters.order.lineItems?.glassParts != null && store.getters.order.lineItems.glassParts.length > 0)) && - store.getters.order.referralNumber?.length !== 6 + !store.getters.payment.insuranceCoverage.isVerified ); }, getDefaultIsInsuranceSelectedValue(availableLineItems) { @@ -166,7 +166,7 @@ export default { return availableLineItems ? baseMixin.methods.getTierOnePackagePrice( baseMixin.methods.filterOutFees(availableLineItems) - ) > 500 + ) > 300 : null; } }, diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 39abffdf0..4bb947199 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -18,6 +18,7 @@ v-model="selectedDate" class="text-link-small" :customSelectableDatesCallback="getAvailableDatesMethod" + validationRules="date-required" @date-clicked="openInshopTimeSlotsModal" /> apiEndDateLimit) { + apiEndDate = apiEndDateLimit; + } } if (appointmentType === AppointmentTypeStrings.MOBILE) { @@ -126,13 +131,13 @@ const getAvailableDates = async ( }, }; } - storeActionConfigs.push(storeActionConfig); + if (apiStartDate < apiEndDate) storeActionConfigs.push(storeActionConfig); } - // ASYNC METHOD const timeSlotsResponsesData = { days: [], }; + function compareDayStrings(a, b) { if (a.date < b.date) return -1; if (a.date > b.date) return 1; diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue index eff2358f0..b278578be 100644 --- a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue +++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue @@ -319,15 +319,19 @@ export default { return `${hours}:${minutes} ${meridianNotation}`; }, getDisplayTextForDurationLength(durationMinimum, durationMaximum) { - let displayTextForDurationLength; - if (durationMaximum >= 120) { - displayTextForDurationLength = `${durationMinimum / 60} - ${ - durationMaximum / 60 - } hours`; - } else { - displayTextForDurationLength = `${durationMinimum} - ${durationMaximum} minutes`; - } - return displayTextForDurationLength; + const isLongAppointment = durationMaximum >= 120; + const isDurationRange = durationMinimum !== durationMaximum; + + const adjustedMinimum = isLongAppointment ? durationMinimum / 60 : durationMinimum; + const adjustedMaximum = isLongAppointment ? durationMaximum / 60 : durationMaximum; + + const durationText = isDurationRange + ? `${adjustedMinimum} - ${adjustedMaximum}` + : adjustedMinimum; + + const unitText = isLongAppointment ? "hours" : "minutes"; + + return `${durationText} ${unitText}`; }, getRelevantDropOffCmsWidgetNameForSelectedTimeSlot( selectedTimeSlotId, diff --git a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue index 3006c8f25..31c415a2d 100644 --- a/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue +++ b/src/layouts/service-location/shop-question/shop-list-button/shop-list-button.vue @@ -25,8 +25,10 @@ {{ badgeText }} - - +
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 033c10601..ba1764bd3 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -79,7 +79,12 @@ :manualHeadline="AlertPerfectMatchInsuranceVerifiedHeader" :manualCopy="AlertPerfectMatchInsuranceVerifiedBody" v-model="customAlertData" - v-if="vinPopulatedOnPageLoad && isInsuranceVerified && !displayInvalidZipAlert" + v-if=" + vinPopulatedOnPageLoad && + isInsuranceVerified && + !displayInvalidZipAlert && + !displayNonServiceableZipAlert + " alertClass="alert-success" />
+ v-bind:class="[ + this.loaderColor, + this.loaderPosition, + this.allowPageInteraction ? 'allow-ui-interaction' : '', + ]"> @@ -83,8 +93,8 @@ export default { &.black:after { background-color: $black; } - //no-block to enable clicking on certain buttons with loaders while the loader is actives - &.no-block::before { + &.allow-ui-interaction::before { + //no-block to enable clicking on certain buttons with loaders while the loader is actives z-index: -1; } }