1<template> 2 <b-row class="mb-2"> 3 <b-col class="d-sm-flex"> 4 <b-form-group 5 :label="$t('global.table.fromDate')" 6 label-for="input-from-date" 7 class="mr-3 my-0 w-100" 8 > 9 <b-input-group> 10 <b-form-input 11 id="input-from-date" 12 v-model="fromDate" 13 placeholder="YYYY-MM-DD" 14 :state="getValidationState($v.fromDate)" 15 class="form-control-with-button mb-3 mb-md-0" 16 @blur="$v.fromDate.$touch()" 17 /> 18 <b-form-invalid-feedback role="alert"> 19 <template v-if="!$v.fromDate.pattern"> 20 {{ $t('global.form.invalidFormat') }} 21 </template> 22 <template v-if="!$v.fromDate.maxDate"> 23 {{ $t('global.form.dateMustBeBefore', { date: toDate }) }} 24 </template> 25 </b-form-invalid-feedback> 26 <template slot:append> 27 <b-form-datepicker 28 v-model="fromDate" 29 class="input-action" 30 button-only 31 right 32 :max="toDate" 33 :hide-header="true" 34 :locale="locale" 35 :label-help=" 36 $t('global.calendar.useCursorKeysToNavigateCalendarDates') 37 " 38 button-variant="link" 39 aria-controls="input-from-date" 40 > 41 <template v-slot:button-content> 42 <icon-calendar 43 :title="$t('global.calendar.openDatePicker')" 44 aria-hidden="true" 45 /> 46 <span class="sr-only">{{ 47 $t('global.calendar.openDatePicker') 48 }}</span> 49 </template> 50 </b-form-datepicker> 51 </template> 52 </b-input-group> 53 </b-form-group> 54 <b-form-group 55 :label="$t('global.table.toDate')" 56 label-for="input-to-date" 57 class="my-0 w-100" 58 > 59 <b-input-group> 60 <b-form-input 61 id="input-to-date" 62 v-model="toDate" 63 placeholder="YYYY-MM-DD" 64 :state="getValidationState($v.toDate)" 65 class="form-control-with-button" 66 @blur="$v.toDate.$touch()" 67 /> 68 <b-form-invalid-feedback role="alert"> 69 <template v-if="!$v.toDate.pattern"> 70 {{ $t('global.form.invalidFormat') }} 71 </template> 72 <template v-if="!$v.toDate.minDate"> 73 {{ $t('global.form.dateMustBeAfter', { date: fromDate }) }} 74 </template> 75 </b-form-invalid-feedback> 76 <template slot:append> 77 <b-form-datepicker 78 v-model="toDate" 79 class="input-action" 80 button-only 81 right 82 :min="fromDate" 83 :hide-header="true" 84 :locale="locale" 85 :label-help=" 86 $t('global.calendar.useCursorKeysToNavigateCalendarDates') 87 " 88 button-variant="link" 89 aria-controls="input-to-date" 90 > 91 <template v-slot:button-content> 92 <icon-calendar 93 :title="$t('global.calendar.openDatePicker')" 94 aria-hidden="true" 95 /> 96 <span class="sr-only">{{ 97 $t('global.calendar.openDatePicker') 98 }}</span> 99 </template> 100 </b-form-datepicker> 101 </template> 102 </b-input-group> 103 </b-form-group> 104 </b-col> 105 </b-row> 106</template> 107 108<script> 109import IconCalendar from '@carbon/icons-vue/es/calendar/20'; 110import { helpers } from 'vuelidate/lib/validators'; 111 112import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; 113 114const isoDateRegex = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/; 115 116export default { 117 components: { IconCalendar }, 118 mixins: [VuelidateMixin], 119 data() { 120 return { 121 fromDate: '', 122 toDate: '', 123 offsetToDate: '', 124 locale: this.$store.getters['global/languagePreference'] 125 }; 126 }, 127 validations() { 128 return { 129 fromDate: { 130 pattern: helpers.regex('pattern', isoDateRegex), 131 maxDate: value => { 132 if (!this.toDate) return true; 133 const date = new Date(value); 134 const maxDate = new Date(this.toDate); 135 if (date.getTime() > maxDate.getTime()) return false; 136 return true; 137 } 138 }, 139 toDate: { 140 pattern: helpers.regex('pattern', isoDateRegex), 141 minDate: value => { 142 if (!this.fromDate) return true; 143 const date = new Date(value); 144 const minDate = new Date(this.fromDate); 145 if (date.getTime() < minDate.getTime()) return false; 146 return true; 147 } 148 } 149 }; 150 }, 151 watch: { 152 fromDate() { 153 this.emitChange(); 154 }, 155 toDate(newVal) { 156 // Offset the end date to end of day to make sure all 157 // entries from selected end date are included in filter 158 this.offsetToDate = new Date(newVal).setUTCHours(23, 59, 59, 999); 159 this.emitChange(); 160 } 161 }, 162 methods: { 163 emitChange() { 164 if (this.$v.$invalid) return; 165 this.$v.$reset(); //reset to re-validate on blur 166 this.$emit('change', { 167 fromDate: this.fromDate ? new Date(this.fromDate) : null, 168 toDate: this.toDate ? new Date(this.offsetToDate) : null 169 }); 170 } 171 } 172}; 173</script> 174