188 lines
4.9 KiB
Vue
188 lines
4.9 KiB
Vue
<script setup>
|
|
import {computed, onMounted, ref, watch} from "vue";
|
|
import {FORMAT_DATE, FORMAT_DATE_ISO, FORMAT_DATETIME_LONG, FORMAT_ISO, formatDatetime, parseDate} from "src/composables/datetimeUtils";
|
|
import {commonProps} from "src/composables/inputs";
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: [String, Date]
|
|
},
|
|
mask: {
|
|
type: [String, Boolean],
|
|
required: false,
|
|
default: FORMAT_DATETIME_LONG
|
|
},
|
|
minDate: {
|
|
type: [String, Date],
|
|
required: false
|
|
},
|
|
rules: {
|
|
type: Array,
|
|
required: false,
|
|
default: () => ([]),
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue']);
|
|
|
|
const dateModel = ref("");
|
|
const timeModel = ref("");
|
|
const tab = ref("date");
|
|
|
|
let originalTime, originalDate;
|
|
|
|
|
|
const popupProxy = ref(null);
|
|
|
|
const publicModel = computed(() => {
|
|
if (!dateModel.value) {
|
|
return "";
|
|
}
|
|
const dateObject = parseDate(model.value, FORMAT_ISO);
|
|
return formatDatetime(dateObject, props.mask);
|
|
});
|
|
|
|
const showTimePicker = computed(() => containsAnyOf(["H", "h", "m"], props.mask));
|
|
|
|
watch(() => dateModel.value, (newVal, oldVal) => {
|
|
tab.value = "time";
|
|
});
|
|
|
|
const model = computed(() => {
|
|
if (dateModel.value === '' || timeModel.value === '') return null;
|
|
return dateModel.value + "T" + timeModel.value
|
|
});
|
|
const emitModelUpdate = () => {
|
|
if (dateModel.value === '' || timeModel.value === '') {
|
|
// console.log(dateModel.value, timeModel.value);
|
|
return;
|
|
}
|
|
|
|
const val = parseDate(model.value);
|
|
emit("update:modelValue", val);
|
|
|
|
if (popupProxy.value)
|
|
popupProxy.value.hide();
|
|
}
|
|
|
|
const containsAnyOf = (needles, haystack) => {
|
|
for (const i in needles) {
|
|
if (haystack.includes(needles[i])) return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const setOriginalValues = () => {
|
|
originalDate = dateModel.value;
|
|
originalTime = timeModel.value;
|
|
}
|
|
|
|
const cancelSelection = () => {
|
|
dateModel.value = originalDate;
|
|
timeModel.value = originalTime;
|
|
popupProxy.value.hide();
|
|
}
|
|
|
|
const myLocale = {
|
|
/* starting with Sunday */
|
|
days: ["Pondělí", "Úterý", "Středa", "Čtvrtek", "Pátek", "Sobota", "Neděle"],
|
|
daysShort: ["Po", "Út", "St", "Čt", "Pá", "So", "Ne"],
|
|
months: [
|
|
"Leden", "Únor", "Březen", "Duben", "Květen", "Červen", "Červenec", "Srpen", "Září", "Říjen", "Listopad",
|
|
"Prosinec"
|
|
],
|
|
monthsShort: ["led.", "úno.", "bře.", "dub.", "kvě.", "čvn.", "čvc.", "srp.", "zář.", "říj.", "lis.", "pro."],
|
|
firstDayOfWeek: 1, // 0-6, 0 - Sunday, 1 Monday, ...
|
|
format24h: true,
|
|
pluralDay: 'dny'
|
|
}
|
|
|
|
const isDateValid = (date) => {
|
|
if (!props.minDate) return true;
|
|
|
|
const minDate = formatDatetime(props.minDate, "YYYY/MM/DD");
|
|
return date >= minDate;
|
|
}
|
|
|
|
watch(() => props.modelValue, (newVal) => {
|
|
let emitDefaultValue = false;
|
|
if (newVal) {
|
|
let modelVal = newVal;
|
|
if (typeof modelVal === 'string') {
|
|
modelVal = parseDate(newVal);
|
|
emitDefaultValue = true;
|
|
}
|
|
|
|
dateModel.value = formatDatetime(modelVal, "YYYY-MM-DD");
|
|
timeModel.value = formatDatetime(modelVal, "HH:mm:ss");
|
|
}
|
|
|
|
setOriginalValues();
|
|
if (emitDefaultValue) {
|
|
emitModelUpdate();
|
|
}
|
|
}, {immediate: true});
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<q-input readonly v-bind="commonProps" v-model="publicModel" :rules="rules">
|
|
<template #append>
|
|
<q-icon name="event"/>
|
|
</template>
|
|
|
|
<template #default>
|
|
<q-popup-proxy ref="popupProxy" @hide="emitModelUpdate" @show="setOriginalValues">
|
|
<div class="proxy-wrapper relative-position" style="min-height: 500px">
|
|
|
|
<q-tabs v-model="tab" v-if="showTimePicker" class="bg-primary text-white">
|
|
<q-tab name="date" icon="event" :label="dateModel ? formatDatetime(dateModel, 'D. M.', FORMAT_DATE_ISO) : 'datum'"/>
|
|
<q-tab name="time" v-if="showTimePicker" icon="schedule" :label="model ? formatDatetime(model, 'HH:mm') : 'čas'"/>
|
|
</q-tabs>
|
|
|
|
<q-separator/>
|
|
|
|
<q-tab-panels v-model="tab" animated>
|
|
<q-tab-panel name="date">
|
|
<q-date
|
|
minimal
|
|
flat
|
|
v-model="dateModel"
|
|
:options="isDateValid"
|
|
mask="YYYY-MM-DD"
|
|
:locale="myLocale"
|
|
/>
|
|
</q-tab-panel>
|
|
|
|
<q-tab-panel name="time" v-if="showTimePicker">
|
|
<q-time
|
|
v-model="timeModel"
|
|
format24h
|
|
flat
|
|
mask="HH:mm:ss"
|
|
/>
|
|
</q-tab-panel>
|
|
</q-tab-panels>
|
|
|
|
<div class="row q-mb-sm absolute-bottom">
|
|
<div class="col">
|
|
<q-btn color="secondary" class="q-ml-sm" @click="cancelSelection">Zrušit</q-btn>
|
|
</div>
|
|
<div class="col text-right">
|
|
<q-btn color="primary" class="q-mr-sm" :disable="!dateModel || !timeModel" @click="emitModelUpdate">Nastavit</q-btn>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</q-popup-proxy>
|
|
</template>
|
|
</q-input>
|
|
</template>
|
|
|
|
|
|
<style scoped>
|
|
.proxy-wrapper {
|
|
background: white;
|
|
}
|
|
</style>
|