mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-08 00:02:15 +01:00
add date selector to time entries, fixes ST-134
This commit is contained in:
@@ -183,7 +183,7 @@ test('test that adding a new tag to an existing time entry works', async ({
|
||||
});
|
||||
|
||||
// Test that Start / End Time Update Works
|
||||
test('test that updating a the start of an existing time entry in the overview works on blur', async ({
|
||||
test('test that updating a the start of an existing time entry in the overview works on enter', async ({
|
||||
page,
|
||||
}) => {
|
||||
await goToTimeOverview(page);
|
||||
@@ -220,7 +220,7 @@ test('test that updating a the start of an existing time entry in the overview w
|
||||
page
|
||||
.getByTestId('time_entry_range_end')
|
||||
.getByTestId('time_picker_minute')
|
||||
.press('Tab'),
|
||||
.press('Enter'),
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { getLocalizedDayJs } from '@/utils/time';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
const props = defineProps<{
|
||||
class?: string;
|
||||
}>();
|
||||
const model = defineModel<string | null>({
|
||||
default: null,
|
||||
});
|
||||
@@ -19,6 +23,7 @@ function updateDate(event: Event) {
|
||||
.set('date', newDate.date())
|
||||
.utc()
|
||||
.format();
|
||||
emit('changed', model.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +33,8 @@ function updateTempValue(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
tempDate.value = target.value;
|
||||
}
|
||||
|
||||
const emit = defineEmits(['changed']);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -36,7 +43,13 @@ function updateTempValue(event: Event) {
|
||||
ref="datePicker"
|
||||
@change="updateTempValue"
|
||||
@blur="updateDate"
|
||||
class="bg-input-background border text-white border-input-border rounded-md"
|
||||
@keydown.enter="updateDate"
|
||||
:class="
|
||||
twMerge(
|
||||
'bg-input-background border text-white border-input-border rounded-md',
|
||||
props.class
|
||||
)
|
||||
"
|
||||
type="date"
|
||||
id="start"
|
||||
name="trip-start"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue';
|
||||
import { getDayJsInstance, getLocalizedDayJs } from '@/utils/time';
|
||||
import { computed } from 'vue';
|
||||
import { getLocalizedDayJs } from '@/utils/time';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
const model = defineModel<string | null>({
|
||||
@@ -47,11 +47,6 @@ function updateHours(event: Event) {
|
||||
}
|
||||
|
||||
const emit = defineEmits(['changed']);
|
||||
onMounted(() => {
|
||||
if (!model.value) {
|
||||
model.value = getDayJsInstance().utc().format();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -86,7 +81,7 @@ onMounted(() => {
|
||||
type="text"
|
||||
:class="
|
||||
twMerge(
|
||||
'border-none bg-transparent px-1 py-0.5 w-[30px] text-center focus:ring-0 focus:bg-card-background-active',
|
||||
'border-none bg-transparent px-1 py-1 w-[30px] text-center focus:ring-0 focus:bg-card-background-active',
|
||||
props.size === 'large' ? 'text-base' : 'text-sm'
|
||||
)
|
||||
" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { defineProps, ref, watch } from 'vue';
|
||||
import TimePicker from '@/Components/Common/TimePicker.vue';
|
||||
import { useFocusWithin } from '@vueuse/core';
|
||||
import DatePicker from '@/Components/Common/DatePicker.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
start: string;
|
||||
@@ -35,21 +36,32 @@ watch(focused, (newValue, oldValue) => {
|
||||
<template>
|
||||
<div
|
||||
ref="dropdownContent"
|
||||
class="grid grid-cols-2 divide-x divide-card-background-separator text-center py-1">
|
||||
<div>
|
||||
<div class="font-bold text-white text-sm pb-1">Start</div>
|
||||
<TimePicker
|
||||
data-testid="time_entry_range_start"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempStart"></TimePicker>
|
||||
class="grid grid-cols-2 divide-x divide-card-background-separator text-center py-2">
|
||||
<div class="px-2">
|
||||
<div class="font-bold text-white text-sm pb-2">Start</div>
|
||||
<div class="space-y-1">
|
||||
<TimePicker
|
||||
data-testid="time_entry_range_start"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempStart"></TimePicker>
|
||||
<DatePicker
|
||||
class="text-sm px-2 py-1"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempStart"></DatePicker>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="font-bold text-white text-sm pb-1">End</div>
|
||||
<TimePicker
|
||||
v-if="tempEnd !== null"
|
||||
data-testid="time_entry_range_end"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempEnd"></TimePicker>
|
||||
<div class="px-2">
|
||||
<div class="font-bold text-white text-sm pb-2">End</div>
|
||||
<div v-if="tempEnd !== null" class="space-y-1">
|
||||
<TimePicker
|
||||
data-testid="time_entry_range_end"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempEnd"></TimePicker>
|
||||
<DatePicker
|
||||
class="text-sm px-2 py-1"
|
||||
@changed="updateTimeEntry"
|
||||
v-model="tempEnd"></DatePicker>
|
||||
</div>
|
||||
<div class="text-muted" v-else>-- : --</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ import dayjs from 'dayjs';
|
||||
import parse from 'parse-duration';
|
||||
import { useCurrentTimeEntryStore } from '@/utils/useCurrentTimeEntry';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { getDayJsInstance } from '@/utils/time';
|
||||
import { formatDuration, getDayJsInstance } from '@/utils/time';
|
||||
const currentTimeEntryStore = useCurrentTimeEntryStore();
|
||||
const { startLiveTimer, stopLiveTimer, updateTimer, startTimer } =
|
||||
currentTimeEntryStore;
|
||||
@@ -34,8 +34,8 @@ const currentTime = computed({
|
||||
}
|
||||
if (now.value && currentTimeEntry.value.start) {
|
||||
const startTime = dayjs(currentTimeEntry.value.start);
|
||||
const diff = now.value.diff(startTime);
|
||||
return dayjs(diff).utc().format('HH:mm:ss');
|
||||
const diff = now.value.diff(startTime, 'seconds');
|
||||
return formatDuration(diff);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
@@ -46,6 +46,14 @@ export function formatHumanReadableDuration(duration: number): string {
|
||||
return `${hours}h ${minutes.toString().padStart(2, '0')}min`;
|
||||
}
|
||||
|
||||
export function formatDuration(duration: number): string {
|
||||
const dayJsDuration = dayjs.duration(duration, 's');
|
||||
const hours = dayJsDuration.hours() + dayJsDuration.days() * 24;
|
||||
const minutes = dayJsDuration.minutes();
|
||||
const seconds = dayJsDuration.seconds();
|
||||
return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
export function calculateDifference(start: string, end: string | null) {
|
||||
if (end === null) {
|
||||
end = dayjs().utc().format();
|
||||
|
||||
Reference in New Issue
Block a user