add support for interval / duration format in frontend views

This commit is contained in:
Gregor Vostrak
2025-05-07 19:39:23 +02:00
parent e374d8b3de
commit 8b950d99d6
24 changed files with 1219 additions and 843 deletions

View File

@@ -9,13 +9,14 @@ import type {
Task,
TimeEntry,
Client,
Organization,
} from '@/packages/api/src';
import TimeEntryDescriptionInput from '@/packages/ui/src/TimeEntry/TimeEntryDescriptionInput.vue';
import TimeEntryRowTagDropdown from '@/packages/ui/src/TimeEntry/TimeEntryRowTagDropdown.vue';
import TimeEntryMoreOptionsDropdown from '@/packages/ui/src/TimeEntry/TimeEntryMoreOptionsDropdown.vue';
import TimeTrackerProjectTaskDropdown from '@/packages/ui/src/TimeTracker/TimeTrackerProjectTaskDropdown.vue';
import BillableToggleButton from '@/packages/ui/src/Input/BillableToggleButton.vue';
import { ref } from 'vue';
import { ref, inject, type ComputedRef } from 'vue';
import {
formatHumanReadableDuration,
formatStartEnd,
@@ -48,6 +49,8 @@ const emit = defineEmits<{
unselected: [TimeEntry[]];
}>();
const organization = inject<ComputedRef<Organization>>('organization');
function updateTimeEntryDescription(description: string) {
props.updateTimeEntries(
props.timeEntry.timeEntries.map((timeEntry: TimeEntry) => timeEntry.id),
@@ -113,10 +116,10 @@ function onSelectChange(checked: boolean) {
</GroupedItemsCountButton>
<TimeEntryDescriptionInput
class="min-w-0 mr-4"
:model-value="
timeEntry.description
"
@changed="updateTimeEntryDescription"></TimeEntryDescriptionInput>
:model-value="timeEntry.description"
@changed="
updateTimeEntryDescription
"></TimeEntryDescriptionInput>
<TimeTrackerProjectTaskDropdown
:clients
:create-project
@@ -128,10 +131,10 @@ function onSelectChange(checked: boolean) {
:project="timeEntry.project_id"
:enable-estimated-time
:currency="currency"
:task="
timeEntry.task_id
"
@changed="updateProjectAndTask"></TimeTrackerProjectTaskDropdown>
:task="timeEntry.task_id"
@changed="
updateProjectAndTask
"></TimeTrackerProjectTaskDropdown>
</div>
</div>
<div class="flex items-center font-medium lg:space-x-2">
@@ -139,7 +142,9 @@ function onSelectChange(checked: boolean) {
:create-tag
:tags="tags"
:model-value="timeEntry.tags"
@changed="updateTimeEntryTags"></TimeEntryRowTagDropdown>
@changed="
updateTimeEntryTags
"></TimeEntryRowTagDropdown>
<BillableToggleButton
:model-value="timeEntry.billable"
class="opacity-50 focus-visible:opacity-100 group-hover:opacity-100"
@@ -155,17 +160,23 @@ function onSelectChange(checked: boolean) {
</button>
</div>
<button
class="text-text-primary min-w-[90px] px-2 py-1.5 bg-transparent text-center hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold focus-visible:outline-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:bg-tertiary"
class="text-text-primary min-w-[90px] px-2.5 py-1.5 bg-transparent text-right hover:bg-card-background rounded-lg border border-transparent hover:border-card-border text-sm font-semibold focus-visible:outline-none focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:bg-tertiary"
@click="expanded = !expanded">
{{
formatHumanReadableDuration(timeEntry.duration ?? 0)
formatHumanReadableDuration(
timeEntry.duration ?? 0,
organization?.interval_format,
organization?.number_format
)
}}
</button>
<TimeTrackerStartStop
:active="!!(timeEntry.start && !timeEntry.end)"
class="opacity-20 hidden sm:flex group-hover:opacity-100 focus-visible:opacity-100"
@changed="onStartStopClick(timeEntry)"></TimeTrackerStartStop>
@changed="
onStartStopClick(timeEntry)
"></TimeTrackerStartStop>
<TimeEntryMoreOptionsDropdown
@delete="
deleteTimeEntries(timeEntry?.timeEntries ?? [])