improve initial mount performance for groupedtimeentrytable by streaming in the rows

mounting the rows mounts lots of nested components which results in a delay on the initial mount.
This commit is contained in:
Gregor Vostrak
2025-11-13 15:20:30 +01:00
parent 8a2c260533
commit 8d3ee58bed

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import type {
CreateClientBody,
CreateProjectBody,
@@ -38,6 +38,8 @@ const props = defineProps<{
canCreateProject: boolean;
}>();
const maxVisibleGroups = ref(7); // Start with 10 day groups, then show all
const groupedTimeEntries = computed(() => {
const groupedEntriesByDay: Record<string, TimeEntry[]> = {};
for (const entry of props.timeEntries) {
@@ -94,6 +96,7 @@ const groupedTimeEntries = computed(() => {
groupedEntriesByDayAndType[dailyEntriesKey] = newDailyEntries;
}
return groupedEntriesByDayAndType;
});
@@ -134,11 +137,43 @@ function unselectAllTimeEntries(value: TimeEntriesGroupedByType[]) {
);
});
}
const visibleGroupedEntries = computed(() => {
const allGroups = Object.entries(groupedTimeEntries.value);
return Object.fromEntries(allGroups.slice(0, maxVisibleGroups.value));
});
const totalGroups = computed(() => Object.keys(groupedTimeEntries.value).length);
function startProgressiveLoading() {
const loadMoreGroups = () => {
if (maxVisibleGroups.value < totalGroups.value) {
maxVisibleGroups.value = Math.min(maxVisibleGroups.value + 5, totalGroups.value);
if (maxVisibleGroups.value < totalGroups.value) {
requestIdleCallback(loadMoreGroups);
}
}
};
requestIdleCallback(loadMoreGroups);
}
// Watch for changes to totalGroups and adjust maxVisibleGroups accordingly
watch(totalGroups, (newTotal, oldTotal) => {
if (newTotal !== oldTotal) {
maxVisibleGroups.value = newTotal;
}
});
onMounted(() => {
startProgressiveLoading();
});
</script>
<template>
<div class="@container">
<div v-for="(value, key) in groupedTimeEntries" :key="key">
<div v-for="(value, key) in visibleGroupedEntries" :key="key">
<TimeEntryRowHeading
:date="key"
:duration="sumDuration(value)"