2020-11-28 14:59:27 +01:00
|
|
|
<template>
|
|
|
|
<div class="datepicker" :class="{'disabled': disabled}">
|
|
|
|
<a @click.stop="toggleDatePopup" class="show">
|
|
|
|
<template v-if="date === null">
|
|
|
|
{{ chooseDateLabel }}
|
|
|
|
</template>
|
|
|
|
<template v-else>
|
|
|
|
{{ formatDateShort(date) }}
|
|
|
|
</template>
|
|
|
|
</a>
|
|
|
|
|
|
|
|
<transition name="fade">
|
|
|
|
<div v-if="show" class="datepicker-popup" ref="datepickerPopup">
|
|
|
|
|
|
|
|
<a @click.stop="() => setDate('today')" v-if="(new Date()).getHours() < 21">
|
|
|
|
<span class="icon">
|
|
|
|
<icon :icon="['far', 'calendar-alt']"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.today') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('today') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
<a @click.stop="() => setDate('tomorrow')">
|
|
|
|
<span class="icon">
|
|
|
|
<icon :icon="['far', 'sun']"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.tomorrow') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('tomorrow') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
<a @click.stop="() => setDate('nextMonday')">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="coffee"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.nextMonday') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('nextMonday') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
<a @click.stop="() => setDate('thisWeekend')">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="cocktail"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.thisWeekend') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('thisWeekend') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
<a @click.stop="() => setDate('laterThisWeek')">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="chess-knight"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.laterThisWeek') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('laterThisWeek') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
<a @click.stop="() => setDate('nextWeek')">
|
|
|
|
<span class="icon">
|
|
|
|
<icon icon="forward"/>
|
|
|
|
</span>
|
|
|
|
<span class="text">
|
|
|
|
<span>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('input.datepicker.nextWeek') }}
|
2020-11-28 14:59:27 +01:00
|
|
|
</span>
|
|
|
|
<span class="weekday">
|
|
|
|
{{ getWeekdayFromStringInterval('nextWeek') }}
|
|
|
|
</span>
|
|
|
|
</span>
|
|
|
|
</a>
|
|
|
|
|
|
|
|
<flat-pickr
|
|
|
|
:config="flatPickerConfig"
|
|
|
|
class="input"
|
|
|
|
v-model="flatPickrDate"
|
|
|
|
/>
|
|
|
|
|
2021-01-17 18:57:57 +01:00
|
|
|
<x-button
|
|
|
|
class="is-fullwidth"
|
|
|
|
:shadow="false"
|
2020-11-28 14:59:27 +01:00
|
|
|
@click="close"
|
|
|
|
>
|
2021-06-24 01:24:57 +02:00
|
|
|
{{ $t('misc.confirm') }}
|
2021-01-17 18:57:57 +01:00
|
|
|
</x-button>
|
2020-11-28 14:59:27 +01:00
|
|
|
</div>
|
|
|
|
</transition>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
|
|
import flatPickr from 'vue-flatpickr-component'
|
|
|
|
import 'flatpickr/dist/flatpickr.css'
|
2021-08-20 15:38:16 +02:00
|
|
|
import { i18n } from '@/i18n'
|
2020-11-28 14:59:27 +01:00
|
|
|
|
|
|
|
import {format} from 'date-fns'
|
2021-02-03 23:06:06 +01:00
|
|
|
import {calculateDayInterval} from '@/helpers/time/calculateDayInterval'
|
2020-11-28 14:59:27 +01:00
|
|
|
import {calculateNearestHours} from '@/helpers/time/calculateNearestHours'
|
2021-01-06 23:36:31 +01:00
|
|
|
import {closeWhenClickedOutside} from '@/helpers/closeWhenClickedOutside'
|
2021-02-03 23:06:06 +01:00
|
|
|
import {createDateFromString} from '@/helpers/time/createDateFromString'
|
2020-11-28 14:59:27 +01:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: 'datepicker',
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
date: null,
|
|
|
|
show: false,
|
|
|
|
changed: false,
|
|
|
|
|
|
|
|
// Since flatpickr dates are strings, we need to convert them to native date objects.
|
|
|
|
// To make that work, we need a separate variable since flatpickr does not have a change event.
|
|
|
|
flatPickrDate: null,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
components: {
|
|
|
|
flatPickr,
|
|
|
|
},
|
|
|
|
props: {
|
2021-08-23 21:18:12 +02:00
|
|
|
modelValue: {
|
2021-07-17 23:21:46 +02:00
|
|
|
validator: prop => prop instanceof Date || prop === null || typeof prop === 'string',
|
2020-11-28 14:59:27 +01:00
|
|
|
},
|
|
|
|
chooseDateLabel: {
|
|
|
|
type: String,
|
2021-06-24 01:24:57 +02:00
|
|
|
default() {
|
2021-08-20 15:38:16 +02:00
|
|
|
return i18n.global.t('input.datepicker.chooseDate')
|
2021-07-17 23:21:46 +02:00
|
|
|
},
|
2020-11-28 14:59:27 +01:00
|
|
|
},
|
|
|
|
disabled: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false,
|
2021-07-17 23:21:46 +02:00
|
|
|
},
|
2020-11-28 14:59:27 +01:00
|
|
|
},
|
2021-08-23 21:18:12 +02:00
|
|
|
emits: ['update:modelValue', 'change', 'close', 'close-on-change'],
|
2020-11-28 14:59:27 +01:00
|
|
|
mounted() {
|
|
|
|
document.addEventListener('click', this.hideDatePopup)
|
|
|
|
},
|
2021-08-19 21:36:09 +02:00
|
|
|
beforeUnmount() {
|
2020-11-28 14:59:27 +01:00
|
|
|
document.removeEventListener('click', this.hideDatePopup)
|
|
|
|
},
|
|
|
|
watch: {
|
2021-08-23 21:18:12 +02:00
|
|
|
modelValue: {
|
2021-09-08 11:59:38 +02:00
|
|
|
handler: 'setDateValue',
|
|
|
|
immediate: true,
|
2020-11-28 14:59:27 +01:00
|
|
|
},
|
|
|
|
flatPickrDate(newVal) {
|
2021-02-03 23:06:06 +01:00
|
|
|
this.date = createDateFromString(newVal)
|
2020-11-28 14:59:27 +01:00
|
|
|
this.updateData()
|
|
|
|
},
|
|
|
|
},
|
2021-06-24 01:24:57 +02:00
|
|
|
computed: {
|
|
|
|
flatPickerConfig() {
|
|
|
|
return {
|
|
|
|
altFormat: this.$t('date.altFormatLong'),
|
|
|
|
altInput: true,
|
|
|
|
dateFormat: 'Y-m-d H:i',
|
|
|
|
enableTime: true,
|
|
|
|
time_24hr: true,
|
|
|
|
inline: true,
|
|
|
|
locale: {
|
|
|
|
firstDayOfWeek: this.$store.state.auth.settings.weekStart,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
},
|
|
|
|
},
|
2020-11-28 14:59:27 +01:00
|
|
|
methods: {
|
2021-04-22 14:26:48 +02:00
|
|
|
setDateValue(newVal) {
|
|
|
|
if(newVal === null) {
|
|
|
|
this.date = null
|
|
|
|
return
|
|
|
|
}
|
|
|
|
this.date = createDateFromString(newVal)
|
|
|
|
},
|
2020-11-28 14:59:27 +01:00
|
|
|
updateData() {
|
|
|
|
this.changed = true
|
2021-08-23 21:18:12 +02:00
|
|
|
this.$emit('update:modelValue', this.date)
|
2020-11-28 14:59:27 +01:00
|
|
|
this.$emit('change', this.date)
|
|
|
|
},
|
|
|
|
toggleDatePopup() {
|
|
|
|
if(this.disabled) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
this.show = !this.show
|
|
|
|
},
|
|
|
|
hideDatePopup(e) {
|
|
|
|
if (this.show) {
|
2021-01-06 23:36:31 +01:00
|
|
|
closeWhenClickedOutside(e, this.$refs.datepickerPopup, this.close)
|
2020-11-28 14:59:27 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
close() {
|
|
|
|
this.show = false
|
|
|
|
this.$emit('close', this.changed)
|
|
|
|
if(this.changed) {
|
|
|
|
this.changed = false
|
|
|
|
this.$emit('close-on-change', this.changed)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
setDate(date) {
|
|
|
|
if (this.date === null) {
|
|
|
|
this.date = new Date()
|
|
|
|
}
|
|
|
|
|
|
|
|
const interval = calculateDayInterval(date)
|
|
|
|
const newDate = new Date()
|
|
|
|
newDate.setDate(newDate.getDate() + interval)
|
|
|
|
newDate.setHours(calculateNearestHours(newDate))
|
|
|
|
newDate.setMinutes(0)
|
|
|
|
newDate.setSeconds(0)
|
|
|
|
this.date = newDate
|
|
|
|
this.flatPickrDate = newDate
|
|
|
|
this.updateData()
|
|
|
|
},
|
|
|
|
getDayIntervalFromString(date) {
|
|
|
|
return calculateDayInterval(date)
|
|
|
|
},
|
|
|
|
getWeekdayFromStringInterval(date) {
|
|
|
|
const interval = calculateDayInterval(date)
|
|
|
|
const newDate = new Date()
|
|
|
|
newDate.setDate(newDate.getDate() + interval)
|
|
|
|
return format(newDate, 'E')
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
</script>
|