diff --git a/resources/js/Pages/ReportingDetailed.vue b/resources/js/Pages/ReportingDetailed.vue index 3ae792e6..29df24a1 100644 --- a/resources/js/Pages/ReportingDetailed.vue +++ b/resources/js/Pages/ReportingDetailed.vue @@ -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 diff --git a/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue b/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue index c8a60349..dd794f17 100644 --- a/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue +++ b/resources/js/packages/ui/src/TimeEntry/TimeEntryAggregateRow.vue @@ -33,6 +33,7 @@ const props = defineProps<{ createProject: (project: CreateProjectBody) => Promise; createClient: (client: CreateClientBody) => Promise; onStartStopClick: (timeEntry: TimeEntry) => void; + duplicateTimeEntry: (timeEntry: TimeEntry) => void; updateTimeEntries: (ids: string[], changes: Partial) => void; updateTimeEntry: (timeEntry: TimeEntry) => void; deleteTimeEntries: (timeEntries: TimeEntry[]) => void; @@ -173,6 +174,7 @@ function onSelectChange(checked: boolean) { @changed="onStartStopClick(timeEntry)"> @@ -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" diff --git a/resources/js/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue b/resources/js/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue index 981b2d66..c31ec2ec 100644 --- a/resources/js/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue +++ b/resources/js/packages/ui/src/TimeEntry/TimeEntryGroupedTable.vue @@ -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)" diff --git a/resources/js/packages/ui/src/TimeEntry/TimeEntryMoreOptionsDropdown.vue b/resources/js/packages/ui/src/TimeEntry/TimeEntryMoreOptionsDropdown.vue index 55e3f9d2..f4e9d6db 100644 --- a/resources/js/packages/ui/src/TimeEntry/TimeEntryMoreOptionsDropdown.vue +++ b/resources/js/packages/ui/src/TimeEntry/TimeEntryMoreOptionsDropdown.vue @@ -1,5 +1,5 @@ @@ -51,6 +54,14 @@ const emit = defineEmits<{ Edit + + + Duplicate + Promise; onStartStopClick: () => void; deleteTimeEntry: () => void; + duplicateTimeEntry?: () => void; updateTimeEntry: (timeEntry: TimeEntry) => void; currency: string; showMember?: boolean; @@ -166,6 +167,7 @@ async function handleDeleteTimeEntry() { @changed="onStartStopClick">