From bf55a55fa60bf7f8e10c0b245bffb230623f0117 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 23 Jun 2026 12:14:22 +0200 Subject: [PATCH] fix(project-management) : reflect saved task immediately in board, list and reopened modal TaskModal now emits the fresh task returned by the API (same task:read shape as the collection). The board, my-tasks and archives pages reinject it into their local state and selectedTask before the background re-fetch, so the list and a reopened modal no longer show the previous snapshot while loadData() is still running. --- .../project-management/components/TaskModal.vue | 4 ++-- .../modules/project-management/pages/my-tasks.vue | 8 +++++++- .../pages/projects/[id]/archives.vue | 8 +++++++- .../project-management/pages/projects/[id]/index.vue | 11 ++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/frontend/modules/project-management/components/TaskModal.vue b/frontend/modules/project-management/components/TaskModal.vue index 7f11066..bb90876 100644 --- a/frontend/modules/project-management/components/TaskModal.vue +++ b/frontend/modules/project-management/components/TaskModal.vue @@ -569,7 +569,7 @@ const props = defineProps<{ const emit = defineEmits<{ (e: 'update:modelValue', value: boolean): void - (e: 'saved'): void + (e: 'saved', task?: Task): void }>() const isOpen = computed({ @@ -1042,7 +1042,7 @@ async function handleSubmit() { await removeRecurrence(props.task.recurrence.id) } - emit('saved') + emit('saved', savedTask) isOpen.value = false } finally { isSubmitting.value = false diff --git a/frontend/modules/project-management/pages/my-tasks.vue b/frontend/modules/project-management/pages/my-tasks.vue index 35bb536..7b015da 100644 --- a/frontend/modules/project-management/pages/my-tasks.vue +++ b/frontend/modules/project-management/pages/my-tasks.vue @@ -269,7 +269,13 @@ watch(taskModalOpen, (open) => { } }) -async function onSaved() { +async function onSaved(savedTask?: Task) { + // Mise à jour optimiste avant le re-fetch (cf. index.vue) pour éviter le snapshot stale. + if (savedTask) { + const idx = tasks.value.findIndex(t => t.id === savedTask.id) + if (idx !== -1) tasks.value[idx] = savedTask + if (selectedTask.value?.id === savedTask.id) selectedTask.value = savedTask + } await loadTasks() } diff --git a/frontend/modules/project-management/pages/projects/[id]/archives.vue b/frontend/modules/project-management/pages/projects/[id]/archives.vue index b17dd26..de3ea86 100644 --- a/frontend/modules/project-management/pages/projects/[id]/archives.vue +++ b/frontend/modules/project-management/pages/projects/[id]/archives.vue @@ -150,7 +150,13 @@ function openTaskEdit(task: Task) { taskDrawerOpen.value = true } -async function onSaved() { +async function onSaved(savedTask?: Task) { + // Mise à jour optimiste avant le re-fetch (cf. index.vue) pour éviter le snapshot stale. + if (savedTask) { + const idx = archivedTasks.value.findIndex(t => t.id === savedTask.id) + if (idx !== -1) archivedTasks.value[idx] = savedTask + if (selectedTask.value?.id === savedTask.id) selectedTask.value = savedTask + } await loadData() } diff --git a/frontend/modules/project-management/pages/projects/[id]/index.vue b/frontend/modules/project-management/pages/projects/[id]/index.vue index b8165f0..13bd443 100644 --- a/frontend/modules/project-management/pages/projects/[id]/index.vue +++ b/frontend/modules/project-management/pages/projects/[id]/index.vue @@ -473,7 +473,16 @@ async function onBulkDelete() { await loadData() } -async function onSaved() { +async function onSaved(savedTask?: Task) { + // Mise à jour optimiste : la modale se ferme avant la fin du re-fetch, on + // réinjecte immédiatement la tâche fraîche renvoyée par l'API pour éviter + // que la liste (et un éventuel ré-ouverture de la modale) reste sur l'ancien snapshot. + if (savedTask) { + const idx = tasks.value.findIndex(t => t.id === savedTask.id) + if (idx !== -1) tasks.value[idx] = savedTask + else tasks.value.push(savedTask) + if (selectedTask.value?.id === savedTask.id) selectedTask.value = savedTask + } await loadData() }