feat: add duplicate time entry fields

This commit is contained in:
Kaspar Rosin
2025-09-20 03:13:54 +03:00
committed by Gregor Vostrak
parent 4a50145329
commit 639f5332e4
5 changed files with 21 additions and 1 deletions

View File

@@ -400,6 +400,7 @@ async function downloadExport(format: ExportFormat) {
:on-start-stop-click="() => startTimeEntryFromExisting(entry)"
:delete-time-entry="() => deleteTimeEntries([entry])"
:currency="getOrganizationCurrencyString()"
:duplicate-time-entry="() => createTimeEntry(entry)"
:members="members"
show-date
show-member

View File

@@ -33,6 +33,7 @@ const props = defineProps<{
createProject: (project: CreateProjectBody) => Promise<Project | undefined>;
createClient: (client: CreateClientBody) => Promise<Client | undefined>;
onStartStopClick: (timeEntry: TimeEntry) => void;
duplicateTimeEntry: (timeEntry: TimeEntry) => void;
updateTimeEntries: (ids: string[], changes: Partial<TimeEntry>) => void;
updateTimeEntry: (timeEntry: TimeEntry) => void;
deleteTimeEntries: (timeEntries: TimeEntry[]) => void;
@@ -173,6 +174,7 @@ function onSelectChange(checked: boolean) {
@changed="onStartStopClick(timeEntry)"></TimeTrackerStartStop>
<TimeEntryMoreOptionsDropdown
:show-edit="false"
:show-duplicate="false"
@delete="
deleteTimeEntries(timeEntry?.timeEntries ?? [])
"></TimeEntryMoreOptionsDropdown>
@@ -202,6 +204,7 @@ function onSelectChange(checked: boolean) {
:update-time-entry="(timeEntry: TimeEntry) => updateTimeEntry(timeEntry)"
:on-start-stop-click="() => onStartStopClick(subEntry)"
:delete-time-entry="() => deleteTimeEntries([subEntry])"
:duplicate-time-entry="() => duplicateTimeEntry(subEntry)"
:currency="currency"
:create-tag
:time-entry="subEntry"

View File

@@ -108,6 +108,7 @@ function startTimeEntryFromExisting(entry: TimeEntry) {
tags: [...entry.tags],
});
}
function sumDuration(timeEntries: TimeEntry[]) {
return timeEntries.reduce((acc, entry) => acc + (entry?.duration ?? 0), 0);
}
@@ -158,6 +159,7 @@ function unselectAllTimeEntries(value: TimeEntriesGroupedByType[]) {
:tags="tags"
:clients
:on-start-stop-click="startTimeEntryFromExisting"
:duplicate-time-entry="createTimeEntry"
:update-time-entries
:update-time-entry
:delete-time-entries
@@ -198,6 +200,7 @@ function unselectAllTimeEntries(value: TimeEntriesGroupedByType[]) {
:update-time-entry
:on-start-stop-click="() => startTimeEntryFromExisting(entry)"
:delete-time-entry="() => deleteTimeEntries([entry])"
:duplicate-time-entry="() => createTimeEntry(entry)"
:currency="currency"
:time-entry="entry.timeEntries[0]"
@selected="selectedTimeEntries.push(entry)"

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { TrashIcon, PencilIcon } from '@heroicons/vue/20/solid';
import { TrashIcon, PencilIcon, DocumentDuplicateIcon } from '@heroicons/vue/20/solid';
import {
DropdownMenu,
DropdownMenuContent,
@@ -10,8 +10,10 @@ import {
const props = withDefaults(
defineProps<{
showEdit?: boolean;
showDuplicate?: boolean;
}>(),
{
showDuplicate: true,
showEdit: true,
}
);
@@ -19,6 +21,7 @@ const props = withDefaults(
const emit = defineEmits<{
edit: [];
delete: [];
duplicate: [];
}>();
</script>
@@ -51,6 +54,14 @@ const emit = defineEmits<{
<PencilIcon class="w-5" />
<span>Edit</span>
</DropdownMenuItem>
<DropdownMenuItem
v-if="props.showDuplicate"
data-testid="time_entry_duplicate"
class="flex items-center space-x-3 cursor-pointer"
@click="emit('duplicate')">
<DocumentDuplicateIcon class="w-5" />
<span>Duplicate</span>
</DropdownMenuItem>
<DropdownMenuItem
data-testid="time_entry_delete"
class="flex items-center space-x-3 cursor-pointer text-destructive focus:text-destructive"

View File

@@ -36,6 +36,7 @@ const props = defineProps<{
createClient: (client: CreateClientBody) => Promise<Client | undefined>;
onStartStopClick: () => void;
deleteTimeEntry: () => void;
duplicateTimeEntry?: () => void;
updateTimeEntry: (timeEntry: TimeEntry) => void;
currency: string;
showMember?: boolean;
@@ -166,6 +167,7 @@ async function handleDeleteTimeEntry() {
@changed="onStartStopClick"></TimeTrackerStartStop>
<TimeEntryMoreOptionsDropdown
@edit="handleEdit"
@duplicate="duplicateTimeEntry"
@delete="deleteTimeEntry"></TimeEntryMoreOptionsDropdown>
</div>
</div>