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