From be079cdbe28da41100661feda404261d21553320 Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 25 Jun 2026 20:43:38 +0200 Subject: [PATCH] =?UTF-8?q?feat(directory)=20:=20conserve=20l'onglet=20act?= =?UTF-8?q?if=20au=20retour=20liste=20=E2=86=94=20fiche=20(LST-72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Au retour depuis une fiche (flèche de l'app ou du navigateur), la liste revenait toujours sur l'onglet Clients. L'onglet actif est désormais transmis via history.state (hors URL), comme sur Starseed. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../pages/directory/clients/[id].vue | 3 +- .../directory/pages/directory/index.vue | 18 ++++++++-- .../pages/directory/prestataires/[id].vue | 3 +- .../pages/directory/prospects/[id].vue | 3 +- frontend/utils/historyTab.ts | 35 +++++++++++++++++++ 5 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 frontend/utils/historyTab.ts diff --git a/frontend/modules/directory/pages/directory/clients/[id].vue b/frontend/modules/directory/pages/directory/clients/[id].vue index 3d28983..de6a28b 100644 --- a/frontend/modules/directory/pages/directory/clients/[id].vue +++ b/frontend/modules/directory/pages/directory/clients/[id].vue @@ -192,7 +192,8 @@ async function saveInfo(): Promise { } function goBack(): void { - router.push('/directory') + // Retour sur l'onglet Clients de la liste (via history.state, hors URL). + router.push({ path: '/directory', state: { tab: 'clients' } }) } onMounted(async () => { diff --git a/frontend/modules/directory/pages/directory/index.vue b/frontend/modules/directory/pages/directory/index.vue index b4e8005..21a63a8 100644 --- a/frontend/modules/directory/pages/directory/index.vue +++ b/frontend/modules/directory/pages/directory/index.vue @@ -183,6 +183,7 @@ import type { Prospect, ProspectStatus } from '~/modules/directory/services/dto/ import { useProspectService } from '~/modules/directory/services/prospects' import type { Prestataire } from '~/modules/directory/services/dto/prestataire' import { usePrestataireService } from '~/modules/directory/services/prestataires' +import { readHistoryTab, stampHistoryTab } from '~/utils/historyTab' definePageMeta({ middleware: ['admin'] }) @@ -201,6 +202,14 @@ const tabs = [ { key: 'prospects', label: t('directory.tabs.prospects'), icon: 'mdi:account-search-outline' }, { key: 'prestataires', label: t('directory.tabs.prestataires'), icon: 'mdi:account-hard-hat-outline' }, ] +const tabKeys = tabs.map((tab) => tab.key) + +// Avant d'ouvrir une fiche : on estampille l'entrée d'historique courante avec +// l'onglet actif → la flèche « précédent » du navigateur restaure le bon onglet. +function navigateToDetail(path: string): void { + stampHistoryTab(activeTab.value) + navigateTo(path) +} // --- Clients --- const clients = ref([]) @@ -224,7 +233,7 @@ function openCreateClient() { } function openEditClient(item: Record) { - navigateTo(`/directory/clients/${(item as Client).id}`) + navigateToDetail(`/directory/clients/${(item as Client).id}`) } // --- Prospects --- @@ -282,7 +291,7 @@ function openCreateProspect() { } function openEditProspect(item: Record) { - navigateTo(`/directory/prospects/${(item as Prospect).id}`) + navigateToDetail(`/directory/prospects/${(item as Prospect).id}`) } async function convertProspect(row: ProspectRow) { @@ -319,7 +328,7 @@ function openCreatePrestataire() { } function openEditPrestataire(item: Record) { - navigateTo(`/directory/prestataires/${(item as Prestataire).id}`) + navigateToDetail(`/directory/prestataires/${(item as Prestataire).id}`) } // --- Suppression (clients, prospects & prestataires) --- @@ -392,6 +401,9 @@ async function confirmDelete() { watch(statusFilter, loadProspects) onMounted(async () => { + // Restaure l'onglet quitté lors d'un retour depuis une fiche (flèche app ou + // navigateur). `null` (deep link / reload) → onglet Clients par défaut. + activeTab.value = readHistoryTab(tabKeys) ?? 'clients' await Promise.all([loadClients(), loadProspects(), loadPrestataires()]) }) diff --git a/frontend/modules/directory/pages/directory/prestataires/[id].vue b/frontend/modules/directory/pages/directory/prestataires/[id].vue index d677e9b..8d1e2b9 100644 --- a/frontend/modules/directory/pages/directory/prestataires/[id].vue +++ b/frontend/modules/directory/pages/directory/prestataires/[id].vue @@ -190,7 +190,8 @@ async function saveInfo(): Promise { } function goBack(): void { - router.push('/directory') + // Retour sur l'onglet Prestataires de la liste (via history.state, hors URL). + router.push({ path: '/directory', state: { tab: 'prestataires' } }) } onMounted(async () => { diff --git a/frontend/modules/directory/pages/directory/prospects/[id].vue b/frontend/modules/directory/pages/directory/prospects/[id].vue index ef8d568..0bce0b6 100644 --- a/frontend/modules/directory/pages/directory/prospects/[id].vue +++ b/frontend/modules/directory/pages/directory/prospects/[id].vue @@ -226,7 +226,8 @@ async function saveInfo(): Promise { } function goBack(): void { - router.push('/directory') + // Retour sur l'onglet Prospects de la liste (via history.state, hors URL). + router.push({ path: '/directory', state: { tab: 'prospects' } }) } onMounted(async () => { diff --git a/frontend/utils/historyTab.ts b/frontend/utils/historyTab.ts new file mode 100644 index 0000000..4656aa8 --- /dev/null +++ b/frontend/utils/historyTab.ts @@ -0,0 +1,35 @@ +/** + * Onglet actif transmis d'une page à l'autre via l'état d'historique + * (`history.state`), SANS le mettre dans l'URL. Sert à préserver l'onglet courant + * du Répertoire (Clients / Prospects / Prestataires) lors de l'aller-retour + * liste ↔ fiche, dans les deux sens (flèche de l'app ET flèche du navigateur). + * + * On reste fidèle à la règle « état d'UI local, pas dans l'URL » : l'onglet + * voyage dans l'entrée d'historique de la navigation, l'URL ne change pas. + */ + +/** + * Lit la clé d'onglet posée dans `history.state.tab` si elle fait partie des + * onglets valides. Retourne `null` sinon : navigation directe / deep link, + * rechargement de page, ou onglet inexistant. + */ +export function readHistoryTab(validKeys: string[]): string | null { + if (typeof window === 'undefined') { + return null + } + const tab = (window.history.state as Record | null)?.tab + return typeof tab === 'string' && validKeys.includes(tab) ? tab : null +} + +/** + * Estampille l'entrée d'historique COURANTE avec l'onglet actif, sans créer de + * nouvelle entrée ni changer l'URL. À appeler juste avant de naviguer vers une + * fiche : au retour via la flèche du navigateur (popstate), cette entrée + * « liste » est restaurée avec son onglet. + */ +export function stampHistoryTab(tab: string): void { + if (typeof window === 'undefined') { + return + } + window.history.replaceState({ ...window.history.state, tab }, '') +}