Files
hrm/app/components/datepicker/Datepicker.vue
2026-04-06 15:53:14 +07:00

146 lines
3.8 KiB
Vue

<template>
<div class="control has-icons-left" :id="docid">
<div :class="`dropdown w-full ${pos || ''} ${focused ? 'is-active' : ''}`">
<div class="dropdown-trigger w-full">
<input
:disabled="disabled"
:class="['input', error && 'is-danger', disabled && 'has-text-dark']"
type="text"
placeholder="DD/MM/YYYY"
maxlength="10"
@focus="setFocus"
@blur="lostFocus"
@keyup.enter="pressEnter"
@keyup="checkDate"
v-model="show"
/>
</div>
<div class="dropdown-menu" role="menu" @click="doClick()">
<div class="dropdown-content">
<PickDay v-bind="{ date, maxdate }" @date="selectDate"></PickDay>
</div>
</div>
</div>
<span class="icon is-left">
<SvgIcon
v-bind="{ name: 'calendar.svg', type: 'gray', size: 21 }"
></SvgIcon>
</span>
</div>
</template>
<script>
export default {
props: ['record', 'attr', 'position', 'mindate', 'maxdate', 'disabled'],
data() {
return {
date: undefined,
show: undefined,
error: false,
focused: false,
docid: this.$id(),
count1: 0,
count2: 0,
pos: undefined,
};
},
created() {
this.getPos();
if (this.record) {
this.date = this.record[this.attr]
? this.$copy(this.record[this.attr])
: undefined;
}
},
watch: {
record: function (newVal) {
if (this.record) {
this.date = this.record[this.attr]
? this.$copy(this.record[this.attr])
: undefined;
}
},
date: function (newDate) {
this.show = newDate && this.$dayjs(newDate).format('DD/MM/YYYY');
},
},
methods: {
pressEnter() {
this.checkDate();
if (!this.error) this.focused = false;
},
setFocus() {
this.focused = true;
this.count1 = 0;
this.count2 = 0;
},
lostFocus() {
let self = this;
setTimeout(() => {
if (self.focused && self.count1 === 0) self.focused = false;
}, 200);
},
processEvent(event) {
var doc = document.getElementById(this.docid);
if (!doc) return;
this.count2 += 1;
var isClickInside = false;
isClickInside = doc.contains(event.target);
if (!isClickInside && this.focused) {
if (this.count2 - 1 !== this.count1) {
this.focused = false;
this.count1 = 0;
this.count2 = 0;
}
}
},
doClick() {
this.count1 += 1;
},
selectDate(v) {
this.date = v;
this.$emit('date', this.date);
if (this.focused) this.focused = false;
this.count1 = 0;
this.count2 = 0;
},
getDate(value) {
let v = value.replace(/\D/g, '').slice(0, 10);
if (v.length >= 5) {
return `${v.slice(0, 2)}/${v.slice(2, 4)}/${v.slice(4)}`;
} else if (v.length >= 3) {
return `${v.slice(0, 2)}/${v.slice(2)}`;
}
return v;
},
checkDate() {
if (!this.focused) this.setFocus();
this.error = false;
this.date = undefined;
if (this.$empty(this.show)) return this.$emit('date', null);
this.show = this.getDate(this.show);
let val = `${this.show.substring(6, 10)}-${this.show.substring(3, 5)}-${this.show.substring(0, 2)}`;
if (this.$dayjs(val, 'YYYY-MM-DD', true).isValid()) {
this.date = val;
this.$emit('date', this.date);
} else this.error = true;
},
getPos() {
switch (this.position) {
case 'is-top-left':
this.pos = 'is-up is-left';
break;
case 'is-top-right':
this.pos = 'is-up is-right';
break;
case 'is-bottom-left':
this.pos = 'is-left';
break;
case 'is-bottom-right':
this.pos = 'is-right';
break;
}
},
},
};
</script>