This commit is contained in:
2026-02-20 21:55:35 +01:00
parent 329b43e07c
commit c258a436a0
13 changed files with 1340 additions and 817 deletions

View File

@@ -0,0 +1,758 @@
<template>
<div>
<section v-if="pending" aria-busy="true" aria-live="polite">
<p>en cours de chargement...</p>
</section>
<section v-else-if="error" aria-live="polite">
<p>Impossible de charger la fiche artiste.</p>
</section>
<template v-else>
<PageSection tone="" content-size="default" class="breadcrum_wp">
<Breadcrumb :current-label="artiste?.nom_artiste_ondif || ''" />
</PageSection>
<section class="fiche_header_wp">
<div class="fiche_header_wp_gauche"></div>
<div class="fiche_header_wp_gauche_carre"></div>
<div class="fiche_header_inner">
<div class="fiche_header_titres">
<div>
<DsHeading as="h1" tone="default" textcase="uppercase" class="concert-card__title">
{{ artiste.nom_artiste_ondif }}
</DsHeading>
</div>
<div>
</div>
</div>
<div class="fiche_header_img">
<DsMedia
v-if="illustration?.url"
:src="illustration.url"
:alt="illustration.alternativeText || artiste?.nom_artiste_ondif || ''"
ratio="3-4"
/>
</div>
<div class="fiche_header_bandeau"></div>
<div class="fiche_header_infos">
<div>
<DsHeading as="h2" tone="invert" textcase="uppercase" class="fiche_header_infos_genre" v-if="postesLabel">
{{ postesLabel }}
</DsHeading>
</div>
<div v-if="artiste.url_artiste_ondif">
<DsText as="p" tone="invert" weight="bold" spacing="space-0" class="">
<a :href="artiste.url_artiste_ondif" target="_blank" rel="noopener noreferrer">Site internet</a>
</DsText>
</div>
<div>
</div>
</div>
</div>
<div class="fiche_header_wp_droite"></div>
</section>
<PageSection tone="" content-size="default">
<section v-if="descriptionBlocks" class="description_wp">
<StrapiBlocksConvert :blocks="descriptionBlocks" />
</section>
<section v-if="imagesArtiste.length" class="img-gallery_wp">
<div class="img-gallery">
<DsMedia
v-for="img in imagesArtiste"
:key="img.id || img.url"
:src="img.url"
:alt="img.alternativeText || artiste?.nom_artiste_ondif || ''"
/>
</div>
</section>
<section v-if="youtubeEmbeds.length" class="youtube_wp">
<div class="youtube-list">
<div v-for="v in youtubeEmbeds" :key="v.id" class="youtube-item">
<iframe
:src="v.src"
title="Vidéo YouTube"
loading="lazy"
referrerpolicy="strict-origin-when-cross-origin"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
allowfullscreen
/>
</div>
</div>
</section>
</PageSection>
</template>
</div>
</template>
<script setup>
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
import DsText from '@root/design-system/primitives/DsText.vue'
const route = useRoute()
//////////////////////////////////////////////////////////////
// RÉCUPÉRATION DU CONTENU
//////////////////////////////////////////////////////////////
const artisteSlug = computed(() => String(route.params.id || ''))
const populate = {
image_illustration_artiste_ondif: true,
postes_artiste_ondif: true,
}
const filters = computed(() => ({
slug_artiste_ondif: {
$eq: artisteSlug.value,
},
}))
const { artistes, pending, error } = useArtistes({
locale: 'fr-FR',
populate,
filters,
limit: 1,
})
const artiste = computed(() => artistes.value?.[0] || {})
useSeoMeta({
title: () => artiste.value?.nom_artiste_ondif || 'Artiste',
})
const postesLabel = computed(() =>
extractStrapiList(artiste.value?.postes_artiste_ondif)
.map((p) => p?.nom_poste)
.filter(Boolean)
.join(', ')
)
const illustration = computed(() => {
const m = artiste.value?.image_illustration_artiste_ondif
if (!m) return null
if (m?.data?.attributes) return { id: m.data.id, ...m.data.attributes }
if (m.url) return m
return null
})
const imagesArtiste = computed(() => {
const value = artiste.value?.images_artiste_ondif
return extractStrapiList(value).filter((img) => Boolean(img?.url))
})
const descriptionBlocks = computed(() =>
artiste.value?.description_artiste_ondif || artiste.value?.description_concert || null
)
const youtube = computed(() => {
const value = artiste.value?.liens_youtube_artiste_ondif
if (!value) return []
return extractStrapiList(value)
})
function getYoutubeId(url = '') {
try {
const u = new URL(url)
if (u.hostname.includes('youtu.be')) return u.pathname.slice(1)
if (u.pathname.startsWith('/shorts/')) return u.pathname.split('/')[2]
if (u.pathname.startsWith('/embed/')) return u.pathname.split('/')[2]
return u.searchParams.get('v')
} catch {
return null
}
}
const youtubeEmbeds = computed(() =>
youtube.value
.map((item) => {
const id = getYoutubeId(item?.lien_youtube)
if (!id) return null
return {
id: item.id || id,
src: `https://www.youtube-nocookie.com/embed/${id}?rel=0&modestbranding=1&iv_load_policy=3&playsinline=1`,
}
})
.filter(Boolean)
)
function extractStrapiList(value) {
if (!value) return []
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
if (value?.data) {
const rows = Array.isArray(value.data) ? value.data : [value.data]
return rows.map(normalizeStrapiItem).filter(Boolean)
}
if (typeof value === 'object') return [normalizeStrapiItem(value)].filter(Boolean)
return []
}
function normalizeStrapiItem(item) {
if (!item || typeof item !== 'object') return null
if (item.attributes && typeof item.attributes === 'object') {
return { id: item.id, ...item.attributes }
}
return item
}
function appendPopulate(query, populateObj, prefix = "populate") {
Object.entries(populateObj).forEach(([key, value]) => {
if (value === true) {
query.set(`${prefix}[${key}]`, "true")
return
}
if (value && typeof value === "object") {
appendPopulate(query, value, `${prefix}[${key}][populate]`)
}
})
}
</script>
<style lang="scss">
.breadcrum_wp {
padding-top: 30px;
}
.fiche_header_wp {
display: grid;
@media (min-width: 0px) and (max-width: 600px) {
grid-template-columns: 1fr;
grid-template-rows: auto 510px 20px 200px;
padding-top: 40px;
}
@media (min-width: 600px) {
grid-template-columns: minmax(10px, 10px) 580px 0px;
grid-template-rows: 40px 280px 20px 230px;
}
@media (min-width: 700px) {
grid-template-columns: minmax(10px, 10px) 660px 0px;
grid-template-rows: 70px 250px 90px 300px;
}
@media (min-width: 800px) {
grid-template-columns: minmax(10px, 10px) 780px minmax(10px, 10px);
grid-template-rows: 60px 280px 70px 300px;
}
@media (min-width: 900px) {
grid-template-columns: minmax(10px, 10px) 860px minmax(10px, 10px);
grid-template-rows: 90px 340px 100px 250px;
}
@media (min-width: 1000px) {
grid-template-columns: minmax(20px, auto) 950px minmax(10px, auto);
grid-template-rows: 90px 340px 120px 270px;
}
@media (min-width: 1100px) {
grid-template-columns: minmax(20px, auto) 1020px minmax(20px, auto);
grid-template-rows: 90px 340px 140px 290px;
}
@media (min-width: 1200px) {
grid-template-columns: minmax(20px, auto) 1100px minmax(20px, auto);
grid-template-rows: 90px 340px 160px 330px;
}
@media (min-width: 1300px) {
grid-template-columns: minmax(20px, auto) 1200px minmax(20px, auto);
grid-template-rows: 90px 340px 160px 330px;
}
@media (min-width: 1400px) {
grid-template-columns: minmax(20px, auto) 1300px minmax(20px, auto);
grid-template-rows: 90px 340px 160px 380px;
}
@media (min-width: 1500px) {
grid-template-columns: minmax(20px, auto) 1400px minmax(20px, auto);
grid-template-rows: 90px 340px 160px 380px;
}
}
.fiche_header_wp_gauche {
@media (min-width: 0px) and (max-width: 600px) {
display: none;
}
@media (min-width: 600px) {
grid-column: 1;
}
}
.fiche_header_wp_gauche_carre {
@media (min-width: 0px) and (max-width: 600px) {
display: none;
}
@media (min-width: 600px) {
grid-column: 1;
grid-row: 4;
}
background-color: var(--c-backgroud-black);
}
.fiche_header_wp_droite {
@media (min-width: 0px) and (max-width: 600px) {
display: none;
}
@media (min-width: 600px) {
grid-column: 3;
}
}
.fiche_header_inner {
@media (min-width: 0px) and (max-width: 600px) {
grid-column: 1;
grid-row: 1/5;
}
@media (min-width: 600px) {
grid-column: 2;
grid-row: 1/5;
}
display: grid;
@media (min-width: 0px) and (max-width: 600px) {
grid-template-columns: 4fr 1fr 0.5fr;
grid-template-rows: auto 510px 20px 200px;
}
@media (min-width: 600px) {
width: 575px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 40px 280px 20px 230px;
}
@media (min-width: 700px) {
width: 675px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 70px 250px 90px 300px;
}
@media (min-width: 800px) {
width: 780px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 60px 280px 70px 300px;
}
@media (min-width: 900px) {
width: 860px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 100px 250px;
}
@media (min-width: 1000px) {
width: 950px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 120px 270px;
}
@media (min-width: 1100px) {
width: 1020px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 140px 290px;
}
@media (min-width: 1200px) {
width: 1100px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 330px;
}
@media (min-width: 1300px) {
width: 1200px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 330px;
}
@media (min-width: 1400px) {
width: 1300px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 380px;
}
@media (min-width: 1500px) {
width: 1400px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 380px;
}
@media (min-width: 1600px) {
width: 1400px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 380px;
}
@media (min-width: 1700px) {
width: 1400px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 380px;
}
@media (min-width: 1800px) {
width: 1400px;
grid-template-columns: 4fr 0.5fr 0.5fr 6.5fr;
grid-template-rows: 90px 340px 160px 380px;
}
}
.fiche_header_titres {
@media (min-width: 0px) and (max-width: 600px) {
grid-column: 1;
grid-row: 1;
padding-bottom: 20px;
padding-left: 10px;
}
@media (min-width: 600px) {
grid-column: 1;
grid-row: 2;
}
display: grid;
align-content: start;
gap: 0.75rem;
h1 {
font-size: 55px;
@media (min-width: 0px) and (max-width: 600px) {
font-size: 25px;
}
@media (min-width: 600px) {
font-size: 25px;
}
@media (min-width: 700px) {
font-size: 30px;
}
@media (min-width: 800px) {
font-size: 30px;
}
@media (min-width: 900px) {
font-size: 40px;
}
@media (min-width: 1000px) {
font-size: 40px;
}
@media (min-width: 1100px) {
font-size: 40px;
}
@media (min-width: 1200px) {
font-size: 50px;
}
@media (min-width: 1300px) {
font-size: 55px;
}
@media (min-width: 1400px) {
font-size: 55px;
}
@media (min-width: 1500px) {
font-size: 55px;
}
@media (min-width: 1600px) {
font-size: 55px;
}
@media (min-width: 1700px) {
font-size: 55px;
}
@media (min-width: 1800px) {
font-size: 55px;
}
}
}
.fiche_header_img {
@media (min-width: 0px) and (max-width: 600px) {
grid-column: 1 / 4;
grid-row: 2 / 4;
}
@media (min-width: 600px) {
grid-column: 3 / 5;
grid-row: 1 / 5;
}
overflow: hidden;
.ds-media {
height: 100%;
}
}
.fiche_header_infos {
@media (min-width: 0px) and (max-width: 600px) {
grid-column: 1 / 2;
grid-row: 4;
margin-top: -30px;
}
@media (min-width: 600px) {
grid-column: 1;
grid-row: 4;
}
display: grid;
align-content: center;
justify-content: end;
@media (min-width: 0px) and (max-width: 700px) {
gap: 7px;
}
@media (min-width: 700px) {
gap: 20px;
}
text-align: right;
.fiche_header_infos_genre {
font-weight: 900;
}
}
.fiche_header_bandeau {
@media (min-width: 0px) and (max-width: 600px) {
grid-column: 1 / 3;
grid-row: 4;
margin-top: -30px;
}
@media (min-width: 600px) {
grid-column: 1 / 4;
grid-row: 4;
}
background-color: var(--c-backgroud-black);
}
/* ============================ */
/* DISTRIBUTION / PROGRAMME */
/* ============================ */
.fiche_details_wp {
.distribution_wp {
padding-top: 50px;
padding-bottom: 50px;
padding-left: 20px;
.distribution_item {
display: flex;
.distribution_item_poste {
padding-right: 10px;
font-weight: 200;
}
.direction {
font-weight: 400;
}
}
}
.programme_wp {
background-color: var(--c-backgroud-brandreverse);
margin-bottom: 70px;
padding-top: 50px;
padding-right: 30px;
padding-left: 40px;
padding-bottom: 50px;
/* DÉCALAGE DU BLOC VERS LA DROITE */
position: relative;
@media (min-width: 0px) and (max-width: 700px) {
width: 89vw;
left: 5%;
}
@media (min-width: 700px) {
width: 67vw;
left: 30%;
}
@media (min-width: 800px) {
width: 50vw;
left: 49%;
}
transform: translateX(0px);
margin-left: 0px;
margin-right: 0px;
box-sizing: border-box;
display: block;
justify-content: initial;
align-items: initial;
.programme_titre {
padding-bottom: 20px;
}
.programme_list {
display: flex;
flex-wrap: wrap;
column-gap: 20px;
row-gap: 20px;
}
.programme_item {
flex: 1 0 200px;
background-color: var(--c-surface);
padding-top: 14px;
padding-right: 20px;
padding-left: 18px;
padding-bottom: 10px;
}
}
}
/* ============================ */
/* REPRÉSENTATIONS */
/* ============================ */
.representation_wp {
display: flex;
flex-wrap: wrap;
/* justify-content: center; */
column-gap: 30px;
row-gap: 30px;
padding-bottom: 70px;
@media (min-width: 0px) and (max-width: 600px) {
padding-left: 20px;
padding-right: 5px;
}
.representation_item {
@media (min-width: 0px) and (max-width: 500px) {
width: 100%;
}
@media (min-width: 500px) {
max-width: 215px;
}
@media (min-width: 600px) {
max-width: 262px;
}
@media (min-width: 700px) {
max-width: 300px;
}
flex: 1 1 300px;
display: grid;
border: 2px var(--c-brand_rouge) solid;
padding-top: 20px;
> * {
padding-left: 20px;
padding-right: 20px;
}
.representation_item_comment_wp {
padding-top: 5px;
}
.representation_item_comment {
background-color: lightgray;
padding: 5px;
}
}
.representation_cta {
color: var(--c-surface);
background-color: var(--c-brand_rouge);
margin-top: 15px;
padding-top: 10px;
padding-bottom: 10px;
text-align: center;
a {
font-family: var(--font-roboto);
font-weight: 600;
font-size: 18px;
}
}
}
/* ============================ */
/* DESCRIPTION */
/* ============================ */
.description_wp {
display: flex;
justify-content: center;
padding-bottom: 70px;
padding-left: 10px;
padding-right: 10px;
> * {
max-width: 570px;
display: flex;
flex-direction: column;
}
}
/* ============================ */
/* GALERIES */
/* ============================ */
.img-gallery_wp {
padding-bottom: 50px;
}
.img-gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 520px));
gap: 1rem;
justify-content: center;
margin-top: 1.5rem;
width: 100%;
}
.img-gallery > * {
display: block;
width: 100%;
overflow: hidden;
border-radius: 5px;
}
.img-gallery :deep(.ds-media) {
display: block;
width: 100%;
height: auto;
background: transparent;
}
.img-gallery :deep(.ds-media__img) {
display: block;
width: 100%;
max-width: 100%;
height: auto;
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.img-gallery :deep(.ds-media__img:hover) {
transform: scale(1.02);
}
@media (max-width: 1100px) {
.img-gallery {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
}
@media (max-width: 820px) {
.img-gallery {
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.75rem;
}
}
@media (max-width: 520px) {
.img-gallery {
grid-template-columns: 1fr;
}
}
.youtube_wp {
margin-bottom: 70px;
}
.youtube-list {
display: grid;
justify-content: center;
/* flex-wrap: wrap; */
gap: 20px;
}
.youtube-item {
@media (min-width: 0px) and (max-width: 300px) {
min-width: 290px;
}
@media (min-width: 300px) {
min-width: 298px;
}
@media (min-width: 400px) {
min-width: 398px;
}
@media (min-width: 500px) {
min-width: 480px;
}
@media (min-width: 600px) {
min-width: 580px;
}
@media (min-width: 700px) {
min-width: 670px;
}
}
.youtube-item iframe {
aspect-ratio: 16 / 9;
border: 0;
}
</style>

View File

@@ -1,13 +1,309 @@
<template>
<div>
<!-- ================== -->
<!-- Fond noir -->
<!-- ================== -->
<PageSection tone="dark" content-size="default" class="theme_bandeau--grid">
<SectionContent pad="xs" class="theme_bandeau--grid--left">
<SectionTitle tone="invert" pad="">
LES MUSICIENS
</SectionTitle>
<DsHeading as="h3" tone="invert">
95 musiciens engagés Partout et pour tous en Île-de-France !
</DsHeading>
</SectionContent>
<SectionContent pad="xs" class="theme_bandeau--grid--right">
<DsText tone="invert" size="lg" class="theme_bandeau--grid--right--text" >
Les 95 musiciennes et musiciens proposent chaque saison plus de 120 concerts dans des salles et théâtres, des lieux culturels et des espaces atypiques de la région francilienne. Porté par une forte mission territoriale, lorchestre sengage à rendre la musique symphonique accessible à toutes et tous, en la faisant vivre au plus près des habitants grâce notamment à des actions culturelles, pédagogiques et participatives au cœur du territoire.
</DsText>
</SectionContent>
</PageSection>
<!-- ================== -->
<!-- Listes des musiciens -->
<!-- ================== -->
<!-- ================== -->
<!-- DIRECTION -->
<!-- ================== -->
<PageSection padded_size="md" content-size="default" class="musiciens_list_section remonter_artistes_list">
<section v-if="pending" aria-busy="true" aria-live="polite">
<DsText as="p" tone="default">Chargement des artistes...</DsText>
</section>
<section v-else-if="error">
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
</section>
<section v-else-if="artistesDirection.length" class="musiciens_list">
<article v-for="a in artistesDirection" :key="a.id" class="musicien_card">
<DsMedia
v-if="a.image?.url"
:src="a.image.url"
:alt="a.image.alternativeText || a.nom_artiste_ondif || ''"
ratio="square"
/>
<DsHeading as="h4" tone="default" class="musicien_card_nom">
<NuxtLink :to="`/orchestre/artiste-${a.slug_artiste_ondif}`">
{{ a.nom_artiste_ondif }}
</NuxtLink>
</DsHeading>
<DsText
v-if="a.postesLabel"
as="p"
tone="default"
size="md"
class="musicien_card_postes"
>
{{ a.postesLabel }}
</DsText>
</article>
</section>
<section v-else>
<DsText as="p" tone="default">Aucun artiste pour la direction.</DsText>
</section>
</PageSection>
<!-- ================== -->
<!-- MUSICIENS -->
<!-- ================== -->
<PageSection padded_size="md" content-size="default" class="musiciens_list_section musiciens_list_wp">
<section v-if="pending" aria-busy="true" aria-live="polite">
<DsText as="p" tone="default">Chargement des artistes...</DsText>
</section>
<section v-else-if="error">
<DsText as="p" tone="default">Impossible de charger les artistes.</DsText>
</section>
<section v-else-if="artistesAutres.length" class="musiciens_list">
<article v-for="a in artistesAutres" :key="a.id" class="musicien_card">
<DsMedia
v-if="a.image?.url"
:src="a.image.url"
:alt="a.image.alternativeText || a.nom_artiste_ondif || ''"
ratio="square"
/>
<DsHeading as="h4" tone="default" class="musicien_card_nom">
<NuxtLink :to="`/orchestre/artiste-${a.slug_artiste_ondif}`">
{{ a.nom_artiste_ondif }}
</NuxtLink>
</DsHeading>
<DsText
v-if="a.postesLabel"
as="p"
tone="default"
size="md"
class="musicien_card_postes"
>
{{ a.postesLabel }}
</DsText>
</article>
</section>
<section v-else>
<DsText as="p" tone="default">Aucun autre artiste trouvé.</DsText>
</section>
</PageSection>
</div>
</template>
<script lang="ts" setup>
<script setup>
import DsHeading from '@root/design-system/primitives/DsHeading.vue'
import DsText from '@root/design-system/primitives/DsText.vue'
import DsMedia from '@root/design-system/primitives/DsMedia.vue'
const runtimeConfig = useRuntimeConfig()
const saisonFiltre = computed(() => String(runtimeConfig.public.saison || '').trim())
const artistesFilters = computed(() => {
if (!saisonFiltre.value) return null
return {
saisons_artiste_ondif: {
nom_saison: {
$eq: saisonFiltre.value,
},
},
}
})
//--------------------
// DONNÉES POUR LES ARTISTES
//--------------------
const { artistes, pending, error } = useArtistes({
locale: "fr-FR",
sort: "ordre_artiste_ondif:asc",
populate: {
saisons_artiste_ondif: true,
image_illustration_artiste_ondif: true,
postes_artiste_ondif: true,
},
filters: artistesFilters,
})
const artistesDisplay = computed(() => {
return (artistes.value || []).map((artiste) => ({
...artiste,
image: getArtisteImage(artiste),
postesLabel: getPostesLabel(artiste),
}))
})
const postesDirection = [
"direction",
"cheffe assistante",
"chef assistante",
]
const artistesDirection = computed(() =>
artistesDisplay.value.filter((a) => isDirectionArtist(a))
)
const artistesAutres = computed(() =>
artistesDisplay.value.filter((a) => !isDirectionArtist(a))
)
function getArtisteImage(artiste) {
const media = artiste?.image_illustration_artiste_ondif
const rows = extractStrapiList(media)
if (rows.length) return rows[0]
if (media && typeof media === "object" && media.url) return media
return null
}
function getPostesLabel(artiste) {
const postes = extractStrapiList(artiste?.postes_artiste_ondif)
return postes
.map((p) => p?.nom_poste)
.filter(Boolean)
.join(", ")
}
function isDirectionArtist(artiste) {
const postes = extractStrapiList(artiste?.postes_artiste_ondif)
.map((p) => String(p?.nom_poste || "").trim().toLowerCase())
.filter(Boolean)
return postes.some((poste) => postesDirection.includes(poste))
}
function extractStrapiList(value) {
if (!value) return []
if (Array.isArray(value)) return value.map(normalizeStrapiItem).filter(Boolean)
if (value?.data) {
const rows = Array.isArray(value.data) ? value.data : [value.data]
return rows.map(normalizeStrapiItem).filter(Boolean)
}
if (typeof value === "object") return [normalizeStrapiItem(value)].filter(Boolean)
return []
}
function normalizeStrapiItem(item) {
if (!item || typeof item !== "object") return null
if (item.attributes && typeof item.attributes === "object") {
return { id: item.id, ...item.attributes }
}
return item
}
</script>
<style>
<style lang="scss">
</style>
.remonter_artistes_list {
transform: translateY(-90px);
}
.theme_bandeau--grid {
> .page-section--inner {
padding-top: 70px;
padding-bottom: 150px;
display: flex;
flex-wrap: wrap;
column-gap: 120px;
row-gap: 30px;
}
&--left {
max-width: 40%;
h1 {
padding-bottom: 20px;
}
}
&--right {
max-width: 60%;
&--text {
max-width: 500px;
}
}
}
.musiciens_list_wp {
// parce que le bloc du dessus à un transform: translateY(-170px); alors cela laisse un espace vide que l'on comble avec ce margin-top négatif
margin-top: -120px;
}
.musiciens_list {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 28px;
}
.musicien_card {
display: flex;
flex-direction: column;
gap: 10px;
}
.musicien_card_nom {
margin-top: 8px;
margin-left: 5px;
&:hover {
color: var(--c-brand_rouge);
}
}
.musicien_card_postes {
margin-left: 5px;
text-transform: lowercase;
&::first-letter {
text-transform: uppercase;
}
}
@media (max-width: 980px) {
.musiciens_list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 400px) {
.musiciens_list {
grid-template-columns: 1fr;
padding-left: 5px;
padding-right: 5px;
}
}
@media (max-width: 600px) {
.musiciens_list {
padding-left: 5px;
padding-right: 5px;
}
}
</style>