Files
wondif_vue/app/pages/concerts/saison.vue
2026-04-08 02:56:59 +02:00

201 lines
6.1 KiB
Vue

<template>
<div>
<PageSection tone="dark" content-size="default">
<SectionTitle tone="invert" pad="md">
SAISON
<div class="saison-select-wrap">
<select
id="saison-select"
v-model="selectedSeason"
class="saison-select"
@change="hasUserSelectedSeason = true"
>
<option v-for="season in seasonOptions" :key="season" :value="season">
{{ season }}
</option>
</select>
</div>
</SectionTitle>
</PageSection>
<PageSection padded_size="md" content-size="default" class="remonter_concert_list">
<ConcertCardList :highlight-first="false" :limit-cards-on-breakpoint="false">
<ConcertCard
v-for="c in concerts"
:key="c.id"
:id="c.slug_concert"
:title="c.titre_concert"
:dateISO="c.representation_concert?.[0]?.date_debut_representation"
:dateLabel="formatDateLong(c.representation_concert?.[0]?.date_debut_representation)"
:lieu="c.representation_concert?.[0]?.lieu_representation?.nom_lieu"
:adresse_lieu="c.representation_concert?.[0]?.lieu_representation?.nom_lieu"
:description="c.resume_concert"
:imageUrl="c.image_illustration_concert?.url"
:imageAlt="c.image_illustration_concert?.alternativeText"
:href="`concert-${c.slug_concert}?from=saison`"
/>
</ConcertCardList>
</PageSection>
</div>
</template>
<script setup>
import { computed, onMounted, ref, watch, watchEffect } from "vue"
const runtimeConfig = useRuntimeConfig()
const route = useRoute()
const router = useRouter()
import { formatDateLong } from "@/utils/dateFormat.js"
const defaultSeason = computed(() => String(runtimeConfig.public.saison || "").trim())
const selectedSeason = ref(String(route.query.saison || defaultSeason.value || "").trim())
const hasUserSelectedSeason = ref(false)
const seasonFilters = computed(() => {
if (!selectedSeason.value) return null
return {
saison_concert: {
nom_saison: {
$eq: selectedSeason.value,
},
},
}
})
const { items: seasonSource } = useStrapi("/api/__strapi__/concerts", {
locale: "fr-FR",
populate: {
saison_concert: true,
},
})
const seasonOptions = computed(() => {
const seasons = new Set()
;(seasonSource.value || []).forEach((concert) => {
const season = concert?.saison_concert?.nom_saison
if (season) seasons.add(String(season).trim())
})
const values = Array.from(seasons).sort((a, b) => b.localeCompare(a, "fr"))
if (selectedSeason.value && !values.includes(selectedSeason.value)) {
values.unshift(selectedSeason.value)
}
if (!values.length && defaultSeason.value) {
values.push(defaultSeason.value)
}
return values
})
watchEffect(() => {
if (route.query.saison) return
if (hasUserSelectedSeason.value) return
if (!defaultSeason.value) return
if (selectedSeason.value !== defaultSeason.value) {
selectedSeason.value = defaultSeason.value
}
})
const { concerts, refresh } = useConcerts({
locale: "fr-FR",
populate: {
saison_concert: true,
genre_concert: true,
type_audience_concert: true,
direction_ondif_concert: { postes_artiste_ondif: true },
direction_invite_concert: { postes_artiste_invite: true },
artistes_ondif_concert: { postes_artiste_ondif: true },
artistes_invite_concert: { postes_artiste_invite: true },
image_illustration_concert: true,
images_concert: true,
videos_concert: true,
audios_concert: true,
programme_concert: true,
representation_concert: { lieu_representation: true },
liens_youtube_concert: true,
},
filters: seasonFilters,
upcomingOnly: false,
})
onMounted(() => {
if (!concerts.value?.length) {
refresh()
}
})
watch(
selectedSeason,
(value) => {
const saison = String(value || "").trim()
router.replace({
query: {
...route.query,
...(saison ? { saison } : {}),
},
})
},
{ immediate: true }
)
</script>
<style lang="scss">
.saison-header {
display: flex;
align-items: center;
gap: 12px;
padding: var(--sp-16) 0;
}
.saison-select-label {
color: var(--c-text-invert);
font-family: var(--font-barlow-condensed);
font-size: 1.75rem;
line-height: 1;
text-transform: uppercase;
}
.saison-select {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
min-width: 220px;
padding: 10px 42px 10px 14px;
border: 1px solid var(--c-text);
border-radius: 0;
background: transparent;
color: var(--c-text-invert);
font-family: var(--font-roboto);
font-weight: var(--fw-extrabold);
font-size: 40px;
line-height: 1;
text-transform: uppercase;
}
.saison-select-wrap {
position: relative;
display: inline-block;
}
.saison-select-wrap::after {
content: "";
position: absolute;
top: 50%;
right: 16px;
width: 12px;
height: 12px;
border-right: 4px solid var(--c-text-invert);
border-bottom: 4px solid var(--c-text-invert);
transform: translateY(-65%) rotate(45deg);
pointer-events: none;
}
.saison-select option {
color: var(--c-text);
}
</style>