mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-14 19:22:14 +01:00
improve time picker focus handling and number input, fixes ST-251
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import { getDayJsInstance, getLocalizedDayJs } from '@/utils/time';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
import { useFocus } from '@vueuse/core';
|
||||
|
||||
// This has to be a localized timestamp, not UTC
|
||||
const model = defineModel<string | null>({
|
||||
@@ -11,19 +12,31 @@ const model = defineModel<string | null>({
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
size: 'base' | 'large';
|
||||
focus: boolean;
|
||||
}>(),
|
||||
{
|
||||
size: 'base',
|
||||
focus: false,
|
||||
}
|
||||
);
|
||||
|
||||
const hours = computed(() => {
|
||||
return model.value ? getLocalizedDayJs(model.value).format('HH') : null;
|
||||
});
|
||||
|
||||
const minutes = computed(() => {
|
||||
return model.value ? getLocalizedDayJs(model.value).format('mm') : null;
|
||||
});
|
||||
const hours = ref(
|
||||
model.value ? getLocalizedDayJs(model.value).format('HH') : null
|
||||
);
|
||||
const minutes = ref(
|
||||
model.value ? getLocalizedDayJs(model.value).format('mm') : null
|
||||
);
|
||||
watch(
|
||||
() => model.value,
|
||||
() => {
|
||||
hours.value = model.value
|
||||
? getLocalizedDayJs(model.value).format('HH')
|
||||
: null;
|
||||
minutes.value = model.value
|
||||
? getLocalizedDayJs(model.value).format('mm')
|
||||
: null;
|
||||
}
|
||||
);
|
||||
|
||||
function updateMinutes(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
@@ -33,19 +46,31 @@ function updateMinutes(event: Event) {
|
||||
.set('minutes', Math.min(parseInt(newValue), 59))
|
||||
.format();
|
||||
}
|
||||
minutes.value = model.value
|
||||
? getLocalizedDayJs(model.value).format('mm')
|
||||
: null;
|
||||
}
|
||||
|
||||
function updateHours(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const newValue = target.value;
|
||||
if (!isNaN(parseInt(newValue))) {
|
||||
if (newValue.endsWith(':')) {
|
||||
minutesInput.value?.focus();
|
||||
} else if (!isNaN(parseInt(newValue))) {
|
||||
model.value = getLocalizedDayJs(model.value)
|
||||
.set('hours', Math.min(parseInt(newValue), 23))
|
||||
.format();
|
||||
}
|
||||
hours.value = model.value
|
||||
? getLocalizedDayJs(model.value).format('HH')
|
||||
: null;
|
||||
}
|
||||
|
||||
const hoursInput = ref<HTMLInputElement | null>(null);
|
||||
const minutesInput = ref<HTMLInputElement | null>(null);
|
||||
const emit = defineEmits(['changed']);
|
||||
|
||||
useFocus(hoursInput, { initialValue: props.focus });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -58,7 +83,8 @@ const emit = defineEmits(['changed']);
|
||||
)
|
||||
">
|
||||
<input
|
||||
:value="hours"
|
||||
v-model="hours"
|
||||
ref="hoursInput"
|
||||
@input="updateHours"
|
||||
@keydown.enter="emit('changed')"
|
||||
@focus="($event.target as HTMLInputElement).select()"
|
||||
@@ -72,7 +98,8 @@ const emit = defineEmits(['changed']);
|
||||
" />
|
||||
<span>:</span>
|
||||
<input
|
||||
:value="minutes"
|
||||
v-model="minutes"
|
||||
ref="minutesInput"
|
||||
@keydown.enter="emit('changed')"
|
||||
@input="updateMinutes"
|
||||
@focus="($event.target as HTMLInputElement).select()"
|
||||
|
||||
@@ -24,7 +24,11 @@ watch(props, () => {
|
||||
tempEnd.value = getLocalizedDayJs(props.end).format();
|
||||
});
|
||||
function updateTimeEntry() {
|
||||
if (tempStart.value !== props.start || tempEnd.value !== props.end) {
|
||||
const tempStartUtc = getDayJsInstance()(tempStart.value).utc().format();
|
||||
const tempEndUtc = tempEnd.value
|
||||
? getDayJsInstance()(tempEnd.value).utc().format()
|
||||
: null;
|
||||
if (tempStartUtc !== props.start || tempEndUtc !== props.end) {
|
||||
emit(
|
||||
'changed',
|
||||
getDayJsInstance()(tempStart.value).utc().format(),
|
||||
@@ -52,6 +56,7 @@ watch(focused, (newValue, oldValue) => {
|
||||
<div class="space-y-1">
|
||||
<TimePicker
|
||||
data-testid="time_entry_range_start"
|
||||
focus
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempStart"></TimePicker>
|
||||
<DatePicker
|
||||
|
||||
Reference in New Issue
Block a user