diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index a20884d40..2f42ebd16 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() { @@ -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,9 +940,6 @@ export default { margin-bottom: 0; overflow: hidden; } - &.last-available-month:not(&.month-hidden) { - margin-bottom: 14rem; - } } .btn-link { @@ -996,4 +1017,10 @@ export default { text-underline-offset: 4px; z-index: 2; } + +.form-test-error { + margin: 0 auto 2rem 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/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 6045d3a4c..e49069154 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" />