Files
wondif_vue/app/components/Breadcrumb.vue
2026-03-18 12:00:19 +01:00

168 lines
4.8 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div v-if="items.length > 1" aria-label="Fil dAriane" class="breadcrumb">
<ul class="breadcrumb__list">
<li v-for="(item, i) in items" :key="item.to" class="breadcrumb__item">
<NuxtLink v-if="i < items.length - 1 && !item.noLink" :to="item.to">
<img
v-if="i === 0"
src="/img/icones/house-grey.svg"
alt="Accueil"
class="breadcrumb__home-icon"
/>
<span v-else>{{ item.label }}</span>
</NuxtLink>
<span v-else aria-current="page">{{ item.label }}</span>
</li>
</ul>
</div>
</template>
<script setup>
const props = defineProps({
currentLabel: { type: String, default: '' } // utile pour les pages dynamiques
})
const route = useRoute()
const labelMap = {
concerts: 'Concerts',
agenda: 'Agenda',
saison: 'Saison',
orchestre: "L'Orchestre",
professionnels: "Professionnels"
}
function resolveTo(part, index, parts, acc) {
if (part === 'concerts') {
const next = parts[index + 1] || ''
if (next.startsWith('concert-')) {
const from = typeof route.query.from === 'string' ? route.query.from : ''
if (from === 'agenda') return '/concerts/agenda'
if (from === 'saison') return '/concerts/saison'
if (from === 'jeune-public') return '/concerts/jeune-public'
}
}
if (part === 'orchestre') {
const next = parts[index + 1] || ''
if (next.startsWith('artiste-') || next.startsWith('artisteinvitee-') || next.startsWith('artistesinvitees-')) {
const from = typeof route.query.from === 'string' ? route.query.from : ''
if (from === 'musiciens') return '/orchestre/musiciens'
if (from === 'artistesinvitees') return '/orchestre/artistesinvitees'
}
}
return acc
}
function humanize(segment) {
return segment
.replace(/-/g, ' ')
.replace(/\b\w/g, (m) => m.toUpperCase())
}
const items = computed(() => {
const parts = route.path.split('/').filter(Boolean)
const crumbs = [{ to: '/', label: 'Accueil' }]
const from = typeof route.query.from === 'string' ? route.query.from : ''
let acc = ''
parts.forEach((part, index) => {
acc += `/${part}`
const isLast = index === parts.length - 1
const label = isLast && props.currentLabel
? props.currentLabel
: (labelMap[part] || humanize(decodeURIComponent(part)))
const noLink = part === 'orchestre' || part === 'concerts'
crumbs.push({ to: resolveTo(part, index, parts, acc), label, noLink })
if (part === 'concerts') {
const next = parts[index + 1] || ''
if (next.startsWith('concert-')) {
if (from === 'agenda') {
crumbs.push({ to: '/concerts/agenda', label: 'Agenda' })
}
if (from === 'saison') {
crumbs.push({ to: '/concerts/saison', label: 'Saison' })
}
if (from === 'jeune-public') {
crumbs.push({ to: '/concerts/jeune-public', label: 'Jeune public' })
}
}
}
if (part === 'orchestre') {
const next = parts[index + 1] || ''
if (next.startsWith('artiste-') || next.startsWith('artisteinvitee-')) {
if (from === 'musiciens') {
crumbs.push({ to: '/orchestre/musiciens', label: 'Les musiciens' })
}
if (from === 'artistesinvitees') {
crumbs.push({ to: '/orchestre/artistesinvitees', label: 'Les artistes invités' })
}
}
}
})
return crumbs
})
</script>
<style lang="scss">
.breadcrumb {
padding-top: 10px;
padding-bottom: 10px;
font-size: 15px;
font-family: var(--font-roboto);
font-weight: var(--fw-extralight);
color: #6D798A;
position: relative;
z-index: 1;
@media (min-width: 0px) {
padding-left: 10px;
}
@media (min-width: 600px) {
padding-left: 0px;
}
@media (min-width: 700px) {
padding-left: 0px;
}
}
.breadcrumb__list {
display: flex;
flex-wrap: wrap;
gap: 8px;
list-style: none;
padding: 0;
}
.breadcrumb__item { display: inline-flex; align-items: center; }
.breadcrumb a {
display: inline-flex;
align-items: center;
cursor: pointer;
pointer-events: auto;
}
.breadcrumb__item:not(:last-child)::after {
content: "";
display: inline-block;
width: 11px;
height: 11px;
margin-left: 8px;
background: url('/img/icones/angle-right-grey.svg') no-repeat center / contain;
vertical-align: middle;
position: relative;
top: -1px; /* ajuste entre 0 et 2px selon ton rendu */
pointer-events: none;
}
.breadcrumb__home-icon {
width: 14px;
height: 14px;
display: inline-block;
vertical-align: middle;
margin-bottom: 4px;
}
</style>