mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-15 19:52:15 +01:00
add break time entries and simplified time tracker ui
This commit is contained in:
73
resources/js/packages/ui/src/TimeEntry/TimeRangeFields.vue
Normal file
73
resources/js/packages/ui/src/TimeEntry/TimeRangeFields.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import { watch } from 'vue';
|
||||
import { InformationCircleIcon } from '@heroicons/vue/20/solid';
|
||||
import { Field, FieldLabel } from '../field';
|
||||
import DatePicker from '@/packages/ui/src/Input/DatePicker.vue';
|
||||
import DurationHumanInput from '@/packages/ui/src/Input/DurationHumanInput.vue';
|
||||
import TimePickerSimple from '@/packages/ui/src/Input/TimePickerSimple.vue';
|
||||
import { getLocalizedDayJs } from '@/packages/ui/src/utils/time';
|
||||
|
||||
// Local (user timezone) ISO strings, as produced by getLocalizedDayJs(...).format()
|
||||
const start = defineModel<string>('start', { required: true });
|
||||
const end = defineModel<string>('end', { required: true });
|
||||
|
||||
defineProps<{
|
||||
showHint?: boolean;
|
||||
datePickerSize?: 'sm';
|
||||
}>();
|
||||
|
||||
// Moving the start to or past the end drags the end along, preserving the
|
||||
// range's previous duration, so the range never collapses or inverts.
|
||||
watch(start, (value, oldValue) => {
|
||||
if (getLocalizedDayJs(end.value).isAfter(getLocalizedDayJs(value))) return;
|
||||
const previousDuration = Math.max(
|
||||
0,
|
||||
getLocalizedDayJs(end.value).diff(getLocalizedDayJs(oldValue), 'second')
|
||||
);
|
||||
end.value = getLocalizedDayJs(value).add(previousDuration, 'second').format();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-5 gap-4">
|
||||
<Field class="col-span-2 sm:col-span-3">
|
||||
<FieldLabel>Duration</FieldLabel>
|
||||
<div class="space-y-2 flex flex-col">
|
||||
<DurationHumanInput
|
||||
v-model:start="start"
|
||||
v-model:end="end"
|
||||
name="Duration"></DurationHumanInput>
|
||||
<div v-if="showHint" class="text-sm flex space-x-1">
|
||||
<InformationCircleIcon
|
||||
class="w-4 shrink-0 text-text-quaternary"></InformationCircleIcon>
|
||||
<span class="text-text-secondary text-xs">
|
||||
You can type natural language like
|
||||
<span class="font-semibold"> 2h 30m</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel>Start</FieldLabel>
|
||||
<div class="flex flex-col gap-2">
|
||||
<TimePickerSimple v-model="start" class="w-full"></TimePickerSimple>
|
||||
<DatePicker
|
||||
v-model="start"
|
||||
:size="datePickerSize"
|
||||
class="w-full"
|
||||
tabindex="1"></DatePicker>
|
||||
</div>
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel>End</FieldLabel>
|
||||
<div class="flex flex-col gap-2">
|
||||
<TimePickerSimple v-model="end" class="w-full"></TimePickerSimple>
|
||||
<DatePicker
|
||||
v-model="end"
|
||||
:size="datePickerSize"
|
||||
class="w-full"
|
||||
tabindex="1"></DatePicker>
|
||||
</div>
|
||||
</Field>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user