0
0
Fork 0

feat: rework VnInputTime and fix VnInputDate bugs

This commit is contained in:
Alex Moreno 2024-07-02 08:06:31 +02:00
parent 938389de2e
commit cb5c33dcc9
4 changed files with 99 additions and 106 deletions

View File

@ -7,6 +7,7 @@ import { useArrayData } from 'composables/useArrayData';
import VnSelect from 'components/common/VnSelect.vue';
import VnInput from 'components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputTime from 'components/common/VnInputTime.vue';
import VnTableColumn from 'components/VnTable/VnColumn.vue';
const $props = defineProps({
@ -75,6 +76,17 @@ const components = {
},
forceAttrs,
},
time: {
component: markRaw(VnInputTime),
event: updateEvent,
attrs: {
...defaultAttrs,
disable: !$props.isEditable,
},
forceAttrs: {
label: $props.showLabel && $props.column.label,
},
},
checkbox: {
component: markRaw(QCheckbox),
event: updateEvent,

View File

@ -5,10 +5,6 @@ import { useI18n } from 'vue-i18n';
const model = defineModel({ type: String });
const $props = defineProps({
readonly: {
type: Boolean,
default: false,
},
isOutlined: {
type: Boolean,
default: false,
@ -48,6 +44,7 @@ const formattedDate = computed({
return date.formatDate(new Date(model.value), dateFormat);
},
set(value) {
if (value == model.value) return;
let newDate;
if (value) {
// parse input
@ -97,12 +94,18 @@ watch(
v-bind="{ ...$attrs, ...styleAttrs }"
:class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null"
:clearable="false"
>
<template #append>
<QIcon
name="close"
size="xs"
v-if="hover && model && !readonly"
v-if="
($attrs.clearable != undefined || $attrs.clearable) &&
hover &&
model &&
!$attrs.disable
"
@click="
model = null;
isPopupOpen = false;
@ -132,13 +135,3 @@ watch(
</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>

View File

@ -1,14 +1,11 @@
<script setup>
import { computed, ref } from 'vue';
import { watch, computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import isValidDate from 'filters/isValidDate';
import { date } from 'quasar';
const model = defineModel({ type: String });
const props = defineProps({
modelValue: {
type: String,
default: null,
},
readonly: {
timeOnly: {
type: Boolean,
default: false,
},
@ -17,44 +14,33 @@ const props = defineProps({
default: false,
},
});
const emit = defineEmits(['update:modelValue']);
const { t } = useI18n();
const requiredFieldRule = (val) => !!val || t('globals.fieldRequired');
const value = computed({
const dateFormat = 'HH:mm';
const isPopupOpen = ref();
const hover = ref();
const formattedTime = computed({
get() {
return props.modelValue;
if (!model.value || model.value?.length <= 5) return model.value;
return dateToTime(model.value);
},
set(value) {
const [hours, minutes] = value.split(':');
const date = new Date(props.modelValue);
date.setHours(Number.parseInt(hours) || 0, Number.parseInt(minutes) || 0, 0, 0);
emit('update:modelValue', value ? date.toISOString() : null);
if (value == model.value) return;
let time = value;
if (time) {
if (time?.length > 5) time = dateToTime(time);
if (!props.timeOnly) {
const hours = time.split(':');
const date = new Date();
date.setHours(hours[0], hours[1], 0);
time = date.toISOString();
}
}
model.value = time;
},
});
const isPopupOpen = ref(false);
const onDateUpdate = (date) => {
internalValue.value = date;
};
const save = () => {
value.value = internalValue.value;
};
const formatTime = (dateString) => {
if (!dateString || !isValidDate(dateString)) {
return '';
}
const date = new Date(dateString || '');
return date.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit',
});
};
const internalValue = ref(formatTime(value));
const styleAttrs = computed(() => {
return props.isOutlined
? {
@ -64,64 +50,66 @@ const styleAttrs = computed(() => {
}
: {};
});
function dateToTime(newDate) {
return date.formatDate(new Date(newDate), dateFormat);
}
watch(
() => model.value,
(val) => (formattedTime.value = val),
{ immediate: true }
);
</script>
<template>
<QInput
class="vn-input-time"
readonly
:model-value="formatTime(value)"
v-bind="{ ...$attrs, ...styleAttrs }"
:class="{ required: $attrs.required }"
:rules="$attrs.required ? [requiredFieldRule] : null"
@click="isPopupOpen = true"
>
<template #append>
<QIcon name="Schedule" class="cursor-pointer">
<QPopupProxy
v-model="isPopupOpen"
cover
transition-show="scale"
transition-hide="scale"
:no-parent-event="props.readonly"
>
<QTime
:format24h="false"
:model-value="formatTime(value)"
@update:model-value="onDateUpdate"
>
<div class="row items-center justify-end q-gutter-sm">
<QBtn
:label="t('Cancel')"
color="primary"
flat
v-close-popup
/>
<QBtn
label="Ok"
color="primary"
flat
@click="save"
v-close-popup
/>
</div>
</QTime>
</QPopupProxy>
</QIcon>
</template>
</QInput>
<div @mouseover="hover = true" @mouseleave="hover = false">
<QInput
class="vn-input-time"
mask="##:##"
placeholder="--:--"
v-model="formattedTime"
v-bind="{ ...$attrs, ...styleAttrs }"
:class="{ required: $attrs.required }"
style="min-width: 100px"
:rules="$attrs.required ? [requiredFieldRule] : null"
>
<template #append>
<QIcon
name="close"
size="xs"
v-if="
($attrs.clearable != undefined || $attrs.clearable) &&
hover &&
model &&
!$attrs.disable
"
@click="
model = null;
isPopupOpen = false;
"
/>
<QIcon name="Schedule" class="cursor-pointer" />
</template>
<QMenu
transition-show="scale"
transition-hide="scale"
v-model="isPopupOpen"
anchor="bottom left"
self="top start"
:no-focus="true"
>
<QTime
:format24h="false"
v-model="formattedTime"
mask="HH:mm"
landscape
now-btn
/>
</QMenu>
</QInput>
</div>
</template>
<style lang="scss">
.vn-input-time.q-field--standard.q-field--readonly .q-field__control:before {
border-bottom-style: solid;
}
.vn-input-time.q-field--outlined.q-field--readonly .q-field__control:before {
border-style: solid;
}
</style>
<i18n>
es:
Cancel: Cancelar

View File

@ -74,7 +74,7 @@ const agencyOptions = ref([]);
type="number"
min="0"
/>
<VnInputTime v-model="data.hour" :label="t('Closing')" clearable />
<VnInputTime v-model="data.hour" :label="t('Closing')" />
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">