Skip to content

Commit

Permalink
improve time picker focus handling and number input, fixes ST-251
Browse files Browse the repository at this point in the history
  • Loading branch information
Onatcer committed Jun 18, 2024
1 parent ce8e503 commit 9f374c7
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 12 deletions.
49 changes: 38 additions & 11 deletions resources/js/Components/Common/TimePicker.vue
Original file line number Diff line number Diff line change
@@ -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>({
Expand All @@ -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;
Expand All @@ -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>
Expand All @@ -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()"
Expand All @@ -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()"
Expand Down
7 changes: 6 additions & 1 deletion resources/js/Components/Common/TimeRangeSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9f374c7

Please sign in to comment.