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 }, '') +}