|
|
@@ -4,7 +4,7 @@
|
|
|
|
<ul>
|
|
|
|
<ul>
|
|
|
|
<!-- First crumb (always visible) -->
|
|
|
|
<!-- First crumb (always visible) -->
|
|
|
|
<li>
|
|
|
|
<li>
|
|
|
|
<NuxtLink :to="crumbs[0].path" class="text-base-content/60 hover:text-primary transition-colors">
|
|
|
|
<NuxtLink :to="crumbs[0].to" class="text-base-content/60 hover:text-primary transition-colors">
|
|
|
|
{{ crumbs[0].label }}
|
|
|
|
{{ crumbs[0].label }}
|
|
|
|
</NuxtLink>
|
|
|
|
</NuxtLink>
|
|
|
|
</li>
|
|
|
|
</li>
|
|
|
@@ -18,7 +18,7 @@
|
|
|
|
:key="i"
|
|
|
|
:key="i"
|
|
|
|
class="hidden sm:list-item"
|
|
|
|
class="hidden sm:list-item"
|
|
|
|
>
|
|
|
|
>
|
|
|
|
<NuxtLink :to="crumb.path" class="text-base-content/60 hover:text-primary transition-colors">
|
|
|
|
<NuxtLink :to="crumb.to" class="text-base-content/60 hover:text-primary transition-colors">
|
|
|
|
{{ crumb.label }}
|
|
|
|
{{ crumb.label }}
|
|
|
|
</NuxtLink>
|
|
|
|
</NuxtLink>
|
|
|
|
</li>
|
|
|
|
</li>
|
|
|
@@ -32,15 +32,40 @@
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
|
|
import type { RouteLocationRaw } from 'vue-router'
|
|
|
|
|
|
|
|
import { useListQueryMemory } from '~/composables/useListQueryMemory'
|
|
|
|
|
|
|
|
|
|
|
|
interface Crumb {
|
|
|
|
interface Crumb {
|
|
|
|
label: string
|
|
|
|
label: string
|
|
|
|
path: string
|
|
|
|
to: RouteLocationRaw
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
|
|
const { remember, recall } = useListQueryMemory()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Routes-listes dont la recherche / tri / pagination doit survivre à une
|
|
|
|
|
|
|
|
// navigation par fil d'Ariane ou menu (qui ne passe pas par l'historique).
|
|
|
|
|
|
|
|
const LIST_PATHS = ['/machines', '/catalogues/composants', '/catalogues/pieces', '/catalogues/produits']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// On enregistre la query courante dès qu'on est sur une route-liste (et à chaque
|
|
|
|
|
|
|
|
// changement de recherche/tri/pagination, qui modifie fullPath).
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
|
|
|
() => route.fullPath,
|
|
|
|
|
|
|
|
() => {
|
|
|
|
|
|
|
|
if (LIST_PATHS.includes(route.path)) remember(route.path, route.query)
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{ immediate: true },
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Cible d'un crumb pointant vers une liste : on réinjecte la dernière query
|
|
|
|
|
|
|
|
// mémorisée pour restaurer l'état, sinon chemin nu (liste neuve).
|
|
|
|
|
|
|
|
const listTo = (path: string): RouteLocationRaw => {
|
|
|
|
|
|
|
|
const query = recall(path)
|
|
|
|
|
|
|
|
return query && Object.keys(query).length > 0 ? { path, query } : path
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const crumbs = computed<Crumb[]>(() => {
|
|
|
|
const crumbs = computed<Crumb[]>(() => {
|
|
|
|
const result: Crumb[] = [{ label: 'Accueil', path: '/' }]
|
|
|
|
const result: Crumb[] = [{ label: 'Accueil', to: '/' }]
|
|
|
|
const path = route.path
|
|
|
|
const path = route.path
|
|
|
|
|
|
|
|
|
|
|
|
// Home page — no breadcrumb
|
|
|
|
// Home page — no breadcrumb
|
|
|
@@ -48,88 +73,88 @@ const crumbs = computed<Crumb[]>(() => {
|
|
|
|
|
|
|
|
|
|
|
|
// Machine context from query param (when navigating from a machine detail page)
|
|
|
|
// Machine context from query param (when navigating from a machine detail page)
|
|
|
|
if (route.query.from === 'machine' && route.query.machineId) {
|
|
|
|
if (route.query.from === 'machine' && route.query.machineId) {
|
|
|
|
result.push({ label: 'Parc machines', path: '/machines' })
|
|
|
|
result.push({ label: 'Parc machines', to: listTo('/machines') })
|
|
|
|
result.push({ label: 'Machine', path: `/machine/${route.query.machineId}` })
|
|
|
|
result.push({ label: 'Machine', to: `/machine/${route.query.machineId}` })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Machines
|
|
|
|
// Machines
|
|
|
|
if (path === '/machines') {
|
|
|
|
if (path === '/machines') {
|
|
|
|
result.push({ label: 'Parc machines', path: '/machines' })
|
|
|
|
result.push({ label: 'Parc machines', to: listTo('/machines') })
|
|
|
|
} else if (path.startsWith('/machine/') && !route.query.from) {
|
|
|
|
} else if (path.startsWith('/machine/') && !route.query.from) {
|
|
|
|
result.push({ label: 'Parc machines', path: '/machines' })
|
|
|
|
result.push({ label: 'Parc machines', to: listTo('/machines') })
|
|
|
|
result.push({ label: 'Machine', path })
|
|
|
|
result.push({ label: 'Machine', to: path })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Catalogs
|
|
|
|
// Catalogs
|
|
|
|
else if (path.startsWith('/catalogues/composants')) {
|
|
|
|
else if (path.startsWith('/catalogues/composants')) {
|
|
|
|
result.push({ label: 'Composants', path: '/catalogues/composants' })
|
|
|
|
result.push({ label: 'Composants', to: listTo('/catalogues/composants') })
|
|
|
|
} else if (path.startsWith('/catalogues/pieces')) {
|
|
|
|
} else if (path.startsWith('/catalogues/pieces')) {
|
|
|
|
result.push({ label: 'Pièces', path: '/catalogues/pieces' })
|
|
|
|
result.push({ label: 'Pièces', to: listTo('/catalogues/pieces') })
|
|
|
|
} else if (path.startsWith('/catalogues/produits')) {
|
|
|
|
} else if (path.startsWith('/catalogues/produits')) {
|
|
|
|
result.push({ label: 'Produits', path: '/catalogues/produits' })
|
|
|
|
result.push({ label: 'Produits', to: listTo('/catalogues/produits') })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Entity detail pages (when NOT from machine context)
|
|
|
|
// Entity detail pages (when NOT from machine context)
|
|
|
|
else if (path.startsWith('/component/') && !route.query.from) {
|
|
|
|
else if (path.startsWith('/component/') && !route.query.from) {
|
|
|
|
result.push({ label: 'Composants', path: '/catalogues/composants' })
|
|
|
|
result.push({ label: 'Composants', to: listTo('/catalogues/composants') })
|
|
|
|
result.push({ label: 'Composant', path })
|
|
|
|
result.push({ label: 'Composant', to: path })
|
|
|
|
} else if (path.startsWith('/piece/') && !route.query.from) {
|
|
|
|
} else if (path.startsWith('/piece/') && !route.query.from) {
|
|
|
|
result.push({ label: 'Pièces', path: '/catalogues/pieces' })
|
|
|
|
result.push({ label: 'Pièces', to: listTo('/catalogues/pieces') })
|
|
|
|
result.push({ label: 'Pièce', path })
|
|
|
|
result.push({ label: 'Pièce', to: path })
|
|
|
|
} else if (path.startsWith('/product/') && !route.query.from) {
|
|
|
|
} else if (path.startsWith('/product/') && !route.query.from) {
|
|
|
|
result.push({ label: 'Produits', path: '/catalogues/produits' })
|
|
|
|
result.push({ label: 'Produits', to: listTo('/catalogues/produits') })
|
|
|
|
result.push({ label: 'Produit', path })
|
|
|
|
result.push({ label: 'Produit', to: path })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Entity detail pages WITH machine context — add entity as last crumb
|
|
|
|
// Entity detail pages WITH machine context — add entity as last crumb
|
|
|
|
else if (path.startsWith('/component/') && route.query.from === 'machine') {
|
|
|
|
else if (path.startsWith('/component/') && route.query.from === 'machine') {
|
|
|
|
result.push({ label: 'Composant', path })
|
|
|
|
result.push({ label: 'Composant', to: path })
|
|
|
|
} else if (path.startsWith('/piece/') && route.query.from === 'machine') {
|
|
|
|
} else if (path.startsWith('/piece/') && route.query.from === 'machine') {
|
|
|
|
result.push({ label: 'Pièce', path })
|
|
|
|
result.push({ label: 'Pièce', to: path })
|
|
|
|
} else if (path.startsWith('/product/') && route.query.from === 'machine') {
|
|
|
|
} else if (path.startsWith('/product/') && route.query.from === 'machine') {
|
|
|
|
result.push({ label: 'Produit', path })
|
|
|
|
result.push({ label: 'Produit', to: path })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Admin pages
|
|
|
|
// Admin pages
|
|
|
|
else if (path.startsWith('/sites')) {
|
|
|
|
else if (path.startsWith('/sites')) {
|
|
|
|
result.push({ label: 'Sites', path: '/sites' })
|
|
|
|
result.push({ label: 'Sites', to: '/sites' })
|
|
|
|
} else if (path.startsWith('/constructeurs')) {
|
|
|
|
} else if (path.startsWith('/constructeurs')) {
|
|
|
|
result.push({ label: 'Fournisseurs', path: '/constructeurs' })
|
|
|
|
result.push({ label: 'Fournisseurs', to: '/constructeurs' })
|
|
|
|
} else if (path.startsWith('/activity-log')) {
|
|
|
|
} else if (path.startsWith('/activity-log')) {
|
|
|
|
result.push({ label: 'Journal d\'activité', path: '/activity-log' })
|
|
|
|
result.push({ label: 'Journal d\'activité', to: '/activity-log' })
|
|
|
|
} else if (path.startsWith('/admin')) {
|
|
|
|
} else if (path.startsWith('/admin')) {
|
|
|
|
result.push({ label: 'Administration', path: '/admin' })
|
|
|
|
result.push({ label: 'Administration', to: '/admin' })
|
|
|
|
} else if (path.startsWith('/documents')) {
|
|
|
|
} else if (path.startsWith('/documents')) {
|
|
|
|
result.push({ label: 'Documents', path: '/documents' })
|
|
|
|
result.push({ label: 'Documents', to: '/documents' })
|
|
|
|
} else if (path.startsWith('/comments')) {
|
|
|
|
} else if (path.startsWith('/comments')) {
|
|
|
|
result.push({ label: 'Commentaires', path: '/comments' })
|
|
|
|
result.push({ label: 'Commentaires', to: '/comments' })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Category pages
|
|
|
|
// Category pages
|
|
|
|
else if (path.startsWith('/component-category')) {
|
|
|
|
else if (path.startsWith('/component-category')) {
|
|
|
|
result.push({ label: 'Composants', path: '/catalogues/composants' })
|
|
|
|
result.push({ label: 'Composants', to: listTo('/catalogues/composants') })
|
|
|
|
result.push({ label: 'Catégorie', path })
|
|
|
|
result.push({ label: 'Catégorie', to: path })
|
|
|
|
} else if (path.startsWith('/piece-category')) {
|
|
|
|
} else if (path.startsWith('/piece-category')) {
|
|
|
|
result.push({ label: 'Pièces', path: '/catalogues/pieces' })
|
|
|
|
result.push({ label: 'Pièces', to: listTo('/catalogues/pieces') })
|
|
|
|
result.push({ label: 'Catégorie', path })
|
|
|
|
result.push({ label: 'Catégorie', to: path })
|
|
|
|
} else if (path.startsWith('/product-category')) {
|
|
|
|
} else if (path.startsWith('/product-category')) {
|
|
|
|
result.push({ label: 'Produits', path: '/catalogues/produits' })
|
|
|
|
result.push({ label: 'Produits', to: listTo('/catalogues/produits') })
|
|
|
|
result.push({ label: 'Catégorie', path })
|
|
|
|
result.push({ label: 'Catégorie', to: path })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create pages
|
|
|
|
// Create pages
|
|
|
|
else if (path.startsWith('/pieces/create')) {
|
|
|
|
else if (path.startsWith('/pieces/create')) {
|
|
|
|
result.push({ label: 'Pièces', path: '/catalogues/pieces' })
|
|
|
|
result.push({ label: 'Pièces', to: listTo('/catalogues/pieces') })
|
|
|
|
result.push({ label: 'Nouvelle pièce', path })
|
|
|
|
result.push({ label: 'Nouvelle pièce', to: path })
|
|
|
|
} else if (path.startsWith('/component/create')) {
|
|
|
|
} else if (path.startsWith('/component/create')) {
|
|
|
|
result.push({ label: 'Composants', path: '/catalogues/composants' })
|
|
|
|
result.push({ label: 'Composants', to: listTo('/catalogues/composants') })
|
|
|
|
result.push({ label: 'Nouveau composant', path })
|
|
|
|
result.push({ label: 'Nouveau composant', to: path })
|
|
|
|
} else if (path.startsWith('/product/create')) {
|
|
|
|
} else if (path.startsWith('/product/create')) {
|
|
|
|
result.push({ label: 'Produits', path: '/catalogues/produits' })
|
|
|
|
result.push({ label: 'Produits', to: listTo('/catalogues/produits') })
|
|
|
|
result.push({ label: 'Nouveau produit', path })
|
|
|
|
result.push({ label: 'Nouveau produit', to: path })
|
|
|
|
} else if (path === '/machines/new') {
|
|
|
|
} else if (path === '/machines/new') {
|
|
|
|
result.push({ label: 'Parc machines', path: '/machines' })
|
|
|
|
result.push({ label: 'Parc machines', to: listTo('/machines') })
|
|
|
|
result.push({ label: 'Nouvelle machine', path })
|
|
|
|
result.push({ label: 'Nouvelle machine', to: path })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
return result
|
|
|
|