From a9f8d0c7bf1fa956bcf6ae7a63083e0dfb398ece Mon Sep 17 00:00:00 2001 From: louispaulb Date: Wed, 8 Apr 2026 18:24:16 -0400 Subject: [PATCH] perf: memoize dispatch timeline segments + load/capacity as computed Maps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: techDayJobsWithTravel(tech), periodLoadH(tech), techPeriodCapacityH(tech) were called as functions in the template v-for — recalculated on EVERY render for every tech (10 techs × 3 functions = 30 expensive recomputations per render). After: Pre-computed as Vue computed Maps (segmentsMap, loadMap, capMap) that only recompute when their reactive dependencies actually change. Template reads from map[tech.id] — instant O(1) lookup, no recalculation. Co-Authored-By: Claude Opus 4.6 --- apps/ops/src/pages/DispatchPage.vue | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/apps/ops/src/pages/DispatchPage.vue b/apps/ops/src/pages/DispatchPage.vue index b044169..8f42d95 100644 --- a/apps/ops/src/pages/DispatchPage.vue +++ b/apps/ops/src/pages/DispatchPage.vue @@ -155,6 +155,23 @@ const hourTicks = computed(() => { const isCalView = computed(() => currentView.value === 'week') const unassignDropActive = ref(false) +// Pre-compute expensive per-tech data (memoized — avoids recalculating on every render) +const segmentsMap = computed(() => { + const map = {} + for (const tech of filteredResources.value) map[tech.id] = techDayJobsWithTravel(tech) + return map +}) +const loadMap = computed(() => { + const map = {} + for (const tech of filteredResources.value) map[tech.id] = periodLoadH(tech) + return map +}) +const capMap = computed(() => { + const map = {} + for (const tech of filteredResources.value) map[tech.id] = techPeriodCapacityH(tech) + return map +}) + const { pushUndo, performUndo } = useUndo(store, invalidateRoutes) const smartAssign = (job, newTechId, dateStr) => store.smartAssign(job.id, newTechId, dateStr) @@ -501,8 +518,8 @@ provide('onRenameTag', onRenameTag) provide('onDeleteTag', onDeleteTag) provide('selectedJob', selectedJob) provide('hoveredJobId', hoveredJobId) -provide('periodLoadH', periodLoadH) -provide('techPeriodCapacityH', techPeriodCapacityH) +provide('periodLoadH', (tech) => loadMap.value[tech.id] ?? 0) +provide('techPeriodCapacityH', (tech) => capMap.value[tech.id] ?? 8) provide('techDayEndH', techDayEndH) provide('isJobMultiSelected', isJobMultiSelected) provide('btColW', btColW) @@ -766,7 +783,7 @@ onUnmounted(() => { document.removeEventListener('keydown', onKeyDown); document Aucune ressource.