From a1b3c9161325ec42bd6291be252f284da461f983 Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 25 Jun 2026 17:21:05 +0200 Subject: [PATCH] =?UTF-8?q?fix(sidebar)=20:=20items=20contextuels=20projet?= =?UTF-8?q?=20ins=C3=A9r=C3=A9s=20sous=20=C2=AB=20Projets=20=C2=BB=20(et?= =?UTF-8?q?=20non=20en=20fin=20de=20groupe)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/layouts/default.vue | 35 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/frontend/app/layouts/default.vue b/frontend/app/layouts/default.vue index 83822ba..c07bf6f 100644 --- a/frontend/app/layouts/default.vue +++ b/frontend/app/layouts/default.vue @@ -91,15 +91,20 @@ const SECTION_ICON: Record = { 'sidebar.admin.section': 'mdi:cog-outline', } +// Item client avec ancre optionnelle : `after` = `to` de l'item après lequel l'insérer +// (sinon ajouté en fin de section). +type ClientItem = MalioItem & { after?: string } + // Items rendus côté client (dépendent d'un état runtime ignoré du backend). -function clientItemsFor(key: string): MalioItem[] { +function clientItemsFor(key: string): ClientItem[] { if (key === 'sidebar.general.section') { - const items: MalioItem[] = [] + const items: ClientItem[] = [] if (currentProjectId.value) { const id = currentProjectId.value - items.push({ label: t('sidebar.project.kanban'), to: `/projects/${id}`, exact: true }) - items.push({ label: t('sidebar.project.groups'), to: `/projects/${id}/groups` }) - items.push({ label: t('sidebar.project.archives'), to: `/projects/${id}/archives` }) + // Insérés juste sous « Projets », dans l'ordre via ancres chaînées. + items.push({ label: t('sidebar.project.kanban'), to: `/projects/${id}`, exact: true, after: '/projects' }) + items.push({ label: t('sidebar.project.groups'), to: `/projects/${id}/groups`, after: `/projects/${id}` }) + items.push({ label: t('sidebar.project.archives'), to: `/projects/${id}/archives`, after: `/projects/${id}/groups` }) } if (isEmployee.value) { items.push({ label: t('sidebar.general.myAbsences'), to: '/absences' }) @@ -107,7 +112,7 @@ function clientItemsFor(key: string): MalioItem[] { return items } if (key === 'sidebar.tools.section') { - const items: MalioItem[] = [] + const items: ClientItem[] = [] if (isMailVisible.value) { const n = mailStore.globalUnreadCount const suffix = n > 0 ? ` (${n > 99 ? '99+' : n})` : '' @@ -121,6 +126,20 @@ function clientItemsFor(key: string): MalioItem[] { return [] } +// Insère les items client après leur ancre (`after`), sinon en fin de liste. +function mergeClientItems(base: MalioItem[], extra: ClientItem[]): MalioItem[] { + const result = [...base] + for (const { after, ...item } of extra) { + const idx = after ? result.findIndex((i) => i.to === after) : -1 + if (idx !== -1) { + result.splice(idx + 1, 0, item) + } else { + result.push(item) + } + } + return result +} + const mergedSections = computed(() => { // 1. Sections backend (déjà filtrées par permissions), mail retiré (ré-injecté côté client). const backend = new Map() @@ -140,12 +159,12 @@ const mergedSections = computed(() => { const base = backend.get(key) const extra = clientItemsFor(key) if (base) { - base.items.push(...extra) + base.items = mergeClientItems(base.items, extra) if (base.items.length > 0) { result.push(base) } } else if (extra.length > 0) { - result.push({ label: t(key), icon: SECTION_ICON[key] ?? '', items: extra }) + result.push({ label: t(key), icon: SECTION_ICON[key] ?? '', items: mergeClientItems([], extra) }) } }