<script setup> import { computed, ref } from 'vue'; import { useI18n } from 'vue-i18n'; import isValidDate from 'filters/isValidDate'; const props = defineProps({ modelValue: { type: String, default: null, }, readonly: { type: Boolean, default: false, }, isOutlined: { type: Boolean, default: false, }, emitDateFormat: { type: Boolean, default: false, }, }); const hover = ref(false); const emit = defineEmits(['update:modelValue']); const { t } = useI18n(); const requiredFieldRule = (val) => !!val || t('globals.fieldRequired'); const joinDateAndTime = (date, time) => { if (!date) { return null; } if (!time) { return new Date(date).toISOString(); } const [year, month, day] = date.split('/'); return new Date(`${year}-${month}-${day}T${time}`).toISOString(); }; const time = computed(() => (props.modelValue ? props.modelValue.split('T')?.[1] : null)); const value = computed({ get() { return props.modelValue; }, set(value) { emit( 'update:modelValue', props.emitDateFormat ? new Date(value) : joinDateAndTime(value, time.value) ); }, }); const isPopupOpen = ref(false); const onDateUpdate = (date) => { value.value = date; isPopupOpen.value = false; }; const padDate = (value) => value.toString().padStart(2, '0'); const formatDate = (dateString) => { const date = new Date(dateString || ''); return `${date.getFullYear()}/${padDate(date.getMonth() + 1)}/${padDate( date.getDate() )}`; }; const displayDate = (dateString) => { if (!dateString || !isValidDate(dateString)) { return ''; } return new Date(dateString).toLocaleDateString([], { year: 'numeric', month: '2-digit', day: '2-digit', }); }; const styleAttrs = computed(() => { return props.isOutlined ? { dense: true, outlined: true, rounded: true, } : {}; }); </script> <template> <div @mouseover="hover = true" @mouseleave="hover = false"> <QInput class="vn-input-date" readonly :model-value="displayDate(value)" v-bind="{ ...$attrs, ...styleAttrs }" :class="{ required: $attrs.required }" :rules="$attrs.required ? [requiredFieldRule] : null" @click="isPopupOpen = true" > <template #append> <QIcon name="close" size="xs" v-if="hover && value && !readonly" @click="onDateUpdate(null)" ></QIcon> <QIcon name="event" class="cursor-pointer"> <QPopupProxy v-model="isPopupOpen" cover transition-show="scale" transition-hide="scale" :no-parent-event="props.readonly" > <QDate :today-btn="true" :model-value="formatDate(value)" @update:model-value="onDateUpdate" /> </QPopupProxy> </QIcon> </template> </QInput> </div> </template> <style lang="scss"> .vn-input-date.q-field--standard.q-field--readonly .q-field__control:before { border-bottom-style: solid; } .vn-input-date.q-field--outlined.q-field--readonly .q-field__control:before { border-style: solid; } </style>