generated from gitea_admin/default
615 lines
17 KiB
Vue
615 lines
17 KiB
Vue
<template>
|
|
<div class="actus--page">
|
|
<!-- ================== -->
|
|
<!-- FILS D'ARIANE -->
|
|
<!-- ================== -->
|
|
<PageSection tone="" content-size="default" class="breadcrum_wp">
|
|
<Breadcrumb/>
|
|
</PageSection>
|
|
|
|
<!-- ================== -->
|
|
<!-- EN-TêTE -->
|
|
<!-- ================== -->
|
|
<PageSection padded_size="" position="relative" overflow="hidden" class="">
|
|
<SectionContent>
|
|
<SectionTitle tone="" pad="xs">
|
|
ACTUALITÉS
|
|
</SectionTitle>
|
|
</SectionContent>
|
|
</PageSection>
|
|
|
|
<div ref="actusMainZone" class="actus-main-zone">
|
|
<!-- ================== -->
|
|
<!-- ACTUS FOCUS -->
|
|
<!-- ================== -->
|
|
|
|
<PageSection
|
|
v-if="focusActu"
|
|
padded_size="md"
|
|
position="relative"
|
|
overflow="hidden"
|
|
class=""
|
|
>
|
|
<SectionContent>
|
|
<div class="card_focus">
|
|
<article class="grid_3">
|
|
<div class="card--img">
|
|
<DsMedia :src="getActuCoverSrc(focusActu)" :alt="getActuCoverAlt(focusActu)" ratio="square" />
|
|
</div>
|
|
<div class="card_focus--content card_focus--titre">
|
|
<h2>
|
|
<NuxtLink
|
|
:to="{ path: '/orchestre/actus', query: { actu: focusActu.slug } }"
|
|
class="card--title-link"
|
|
>
|
|
<SectionTitle tone="" pad="" class="card--title-link">
|
|
{{ focusActu.title }}
|
|
</SectionTitle>
|
|
</NuxtLink>
|
|
</h2>
|
|
</div>
|
|
<div class="card_focus--content card_focus--text">
|
|
<DsText v-if="focusActu.subtitle" as="p" tone="default" :clamp="3" class="square-card__description">
|
|
{{ focusActu.subtitle }}
|
|
</DsText>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</SectionContent>
|
|
</PageSection>
|
|
|
|
<!-- ================== -->
|
|
<!-- LISTE DES ACTUS -->
|
|
<!-- ================== -->
|
|
|
|
<PageSection padded_size="md" position="relative" overflow="hidden" class="">
|
|
<SectionContent>
|
|
<div class="grid_3">
|
|
<article
|
|
v-for="actu in listedActus"
|
|
:key="actu.slug"
|
|
class="card"
|
|
>
|
|
<div class="card--img">
|
|
<DsMedia :src="getActuCoverSrc(actu)" :alt="getActuCoverAlt(actu)" ratio="square" />
|
|
</div>
|
|
<div class="card--content">
|
|
<h2>
|
|
<NuxtLink
|
|
:to="{ path: '/orchestre/actus', query: { actu: actu.slug } }"
|
|
class="card--title-link"
|
|
>
|
|
<DsHeading as="h5" tone="default" class="card--title-link">
|
|
{{ actu.title }}
|
|
</DsHeading>
|
|
</NuxtLink>
|
|
</h2>
|
|
<DsText as="p" tone="default" :clamp="3" class="">
|
|
{{ actu.subtitle }}
|
|
</DsText>
|
|
</div>
|
|
</article>
|
|
</div>
|
|
</SectionContent>
|
|
</PageSection>
|
|
|
|
<PageSection
|
|
v-if="selectedActu"
|
|
padded_size=""
|
|
:content="false"
|
|
class="actus-overlay-section"
|
|
@click="closeActuOverlay"
|
|
>
|
|
<aside class="actus-overlay" aria-label="Fiche actualité" @click.stop>
|
|
<NuxtLink
|
|
:to="{ path: '/orchestre/actus' }"
|
|
class="actus-overlay--close"
|
|
aria-label="Fermer la fiche actualité"
|
|
>
|
|
<svg class="actus-overlay--close-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path d="M3 3h18v18H3V3Zm4.4 5.8 3.2 3.2-3.2 3.2 1.4 1.4 3.2-3.2 3.2 3.2 1.4-1.4-3.2-3.2 3.2-3.2-1.4-1.4-3.2 3.2-3.2-3.2-1.4 1.4Z" />
|
|
</svg>
|
|
<span class="sr-only">Fermer</span>
|
|
</NuxtLink>
|
|
<div class="actus-overlay--content">
|
|
<div class="actus-overlay--metas">
|
|
<DsText as="p" weight="bold" tone="default" class="uppercase">
|
|
{{ selectedActu.date }}
|
|
</DsText>
|
|
<DsText as="p" weight="bold" tone="default" class="uppercase">
|
|
{{ selectedActu.categorie }}
|
|
</DsText>
|
|
</div>
|
|
<DsHeading ref="actusOverlayTitle" as="h1" tone="default" class="uppercase" tabindex="-1">
|
|
{{ selectedActu.title }}
|
|
</DsHeading>
|
|
</div>
|
|
<section v-if="selectedActuImagesTop.length" class="img-gallery_wp">
|
|
<div class="img-gallery">
|
|
<DsMedia
|
|
v-for="img in selectedActuImagesTop"
|
|
:key="img.id || img.url"
|
|
:src="img.url"
|
|
:alt="img.alternativeText || selectedActu.imgAlt"
|
|
/>
|
|
</div>
|
|
</section>
|
|
<div class="actus-overlay--content">
|
|
<p v-if="selectedActu.subtitle">{{ selectedActu.subtitle }}</p>
|
|
<StrapiBlocksConvert :blocks="selectedActu.descriptionBlocks" />
|
|
</div>
|
|
<section v-if="selectedActuImagesBottom.length" class="img-gallery_wp">
|
|
<div class="img-gallery">
|
|
<DsMedia
|
|
v-for="img in selectedActuImagesBottom"
|
|
:key="img.id || img.url"
|
|
:src="img.url"
|
|
:alt="img.alternativeText || selectedActu.imgAlt"
|
|
/>
|
|
</div>
|
|
</section>
|
|
<section v-if="selectedActuVideos.length" class="youtube_wp">
|
|
<div class="youtube-list">
|
|
<div v-for="v in selectedActuVideos" :key="v.id" class="youtube-item">
|
|
<iframe
|
|
:src="v.lien_youtube"
|
|
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>
|
|
<div class="actus-overlay--content">
|
|
<NuxtLink
|
|
:to="{ path: '/orchestre/actus' }"
|
|
class="actus-overlay--close actus-overlay--close-bottom"
|
|
aria-label="Fermer la fiche actualité"
|
|
>
|
|
<svg class="actus-overlay--close-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
|
|
<path d="M3 3h18v18H3V3Zm4.4 5.8 3.2 3.2-3.2 3.2 1.4 1.4 3.2-3.2 3.2 3.2 1.4-1.4-3.2-3.2 3.2-3.2-1.4-1.4-3.2 3.2-3.2-3.2-1.4 1.4Z" />
|
|
</svg>
|
|
<span class="sr-only">Fermer</span>
|
|
</NuxtLink>
|
|
</div>
|
|
</aside>
|
|
</PageSection>
|
|
</div>
|
|
|
|
|
|
</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'
|
|
import { computed, nextTick, onBeforeUnmount, ref, watch } from 'vue'
|
|
useHead({
|
|
link: [
|
|
{
|
|
rel: 'preconnect',
|
|
href: 'https://fonts.googleapis.com',
|
|
},
|
|
{
|
|
rel: 'preconnect',
|
|
href: 'https://fonts.gstatic.com',
|
|
crossorigin: '',
|
|
},
|
|
{
|
|
rel: 'stylesheet',
|
|
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap',
|
|
},
|
|
],
|
|
})
|
|
|
|
|
|
// ======================================
|
|
// RÉCUPÉRATION DES DONNÉES DANS STRAPI
|
|
// ======================================
|
|
|
|
|
|
// ======================================
|
|
// PRÉPARATION DES DONNÉES POUR AFFICHAGE DANS LA PAGE
|
|
// ======================================
|
|
const route = useRoute()
|
|
const actusOverlayTitle = ref(null)
|
|
|
|
const { items: actualitesItems } = useStrapi(
|
|
"/api/__strapi__/actualites",
|
|
{
|
|
locale: "fr-FR",
|
|
sort: "date_actu:desc",
|
|
fetchAll: true,
|
|
populate: {
|
|
image_illustration_actu: true,
|
|
images_actu: true,
|
|
liens_youtube_actu: true,
|
|
},
|
|
}
|
|
)
|
|
|
|
const actus = computed(() => {
|
|
return actualitesItems.value.map(normalizeActualite).filter((actu) => actu.slug)
|
|
})
|
|
|
|
const selectedActu = computed(() => {
|
|
return actus.value.find((actu) => actu.slug === route.query.actu) || null
|
|
})
|
|
|
|
const focusActu = computed(() => {
|
|
return actus.value.find((actu) => actu.focus) || null
|
|
})
|
|
|
|
const listedActus = computed(() => {
|
|
return actus.value.filter((actu) => !actu.focus)
|
|
})
|
|
|
|
function normalizeActualite(item) {
|
|
const coverImage = normalizeStrapiMedia(item.image_illustration_actu)
|
|
const galleryImages = (Array.isArray(item.images_actu) ? item.images_actu : [])
|
|
.map(normalizeStrapiMedia)
|
|
.filter(Boolean)
|
|
|
|
return {
|
|
slug: item.slug_actu || item.slug || String(item.id || ''),
|
|
title: item.titre_actu || item.title || '',
|
|
subtitle: item.sous_titre_actu || '',
|
|
descriptionBlocks: Array.isArray(item.description_actu) ? item.description_actu : [],
|
|
date: formatActuDate(item.date_actu),
|
|
categorie: item.categorie_actu || '',
|
|
focus: Boolean(item.focus_actu),
|
|
accueil: Boolean(item.accueil_actu),
|
|
tiroir_videos: Array.isArray(item.liens_youtube_actu) ? item.liens_youtube_actu : [],
|
|
coverImage,
|
|
galleryImages,
|
|
imgAlt: coverImage?.alternativeText || '',
|
|
}
|
|
}
|
|
|
|
function normalizeStrapiMedia(media) {
|
|
if (!media?.url) return null
|
|
|
|
return {
|
|
id: media.id || media.documentId || media.url,
|
|
url: media.url,
|
|
alternativeText: media.alternativeText || media.caption || '',
|
|
}
|
|
}
|
|
|
|
function formatActuDate(date) {
|
|
if (!date) return ''
|
|
const parsedDate = new Date(date)
|
|
if (Number.isNaN(parsedDate.getTime())) return ''
|
|
|
|
return new Intl.DateTimeFormat('fr-FR', {
|
|
day: 'numeric',
|
|
month: 'long',
|
|
year: 'numeric',
|
|
}).format(parsedDate)
|
|
}
|
|
|
|
const getActuImages = (actu) => {
|
|
return Array.isArray(actu?.galleryImages) ? actu.galleryImages : []
|
|
}
|
|
|
|
const getActuCoverSrc = (actu) => {
|
|
return actu?.coverImage?.url || ''
|
|
}
|
|
|
|
const getActuCoverAlt = (actu) => {
|
|
return actu?.coverImage?.alternativeText || actu?.imgAlt || ''
|
|
}
|
|
|
|
const selectedActuImages = computed(() => {
|
|
return getActuImages(selectedActu.value)
|
|
})
|
|
|
|
const selectedActuImagesTop = computed(() => {
|
|
return selectedActuImages.value.slice(0, 2)
|
|
})
|
|
|
|
const selectedActuImagesBottom = computed(() => {
|
|
return selectedActuImages.value.slice(2)
|
|
})
|
|
|
|
const getYoutubeEmbedUrl = (url = '') => {
|
|
if (!url) return ''
|
|
|
|
try {
|
|
const parsedUrl = new URL(url)
|
|
const hostname = parsedUrl.hostname.replace(/^www\./, '')
|
|
let videoId = ''
|
|
|
|
if (hostname === 'youtu.be') {
|
|
videoId = parsedUrl.pathname.split('/').filter(Boolean)[0] || ''
|
|
}
|
|
|
|
if (hostname === 'youtube.com' || hostname === 'm.youtube.com' || hostname === 'youtube-nocookie.com') {
|
|
if (parsedUrl.pathname.startsWith('/embed/')) return url
|
|
|
|
videoId = parsedUrl.searchParams.get('v') || ''
|
|
|
|
if (!videoId && parsedUrl.pathname.startsWith('/shorts/')) {
|
|
videoId = parsedUrl.pathname.split('/').filter(Boolean)[1] || ''
|
|
}
|
|
|
|
if (!videoId && parsedUrl.pathname.startsWith('/live/')) {
|
|
videoId = parsedUrl.pathname.split('/').filter(Boolean)[1] || ''
|
|
}
|
|
}
|
|
|
|
return videoId ? `https://www.youtube-nocookie.com/embed/${videoId}` : url
|
|
} catch {
|
|
return url
|
|
}
|
|
}
|
|
|
|
const selectedActuVideos = computed(() => {
|
|
return (selectedActu.value?.tiroir_videos || [])
|
|
.map((video) => ({
|
|
...video,
|
|
lien_youtube: getYoutubeEmbedUrl(video.lien_youtube)
|
|
}))
|
|
.filter((video) => video.lien_youtube)
|
|
})
|
|
|
|
const closeActuOverlay = () => {
|
|
navigateTo({ path: '/orchestre/actus' })
|
|
}
|
|
|
|
watch(
|
|
selectedActu,
|
|
async (actu) => {
|
|
if (import.meta.client) {
|
|
document.body.style.overflow = actu ? 'hidden' : ''
|
|
}
|
|
|
|
if (!actu) return
|
|
|
|
await nextTick()
|
|
|
|
const titleElement = actusOverlayTitle.value?.$el || actusOverlayTitle.value
|
|
titleElement?.focus?.({ preventScroll: true })
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
onBeforeUnmount(() => {
|
|
if (import.meta.client) {
|
|
document.body.style.overflow = ''
|
|
}
|
|
})
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
// =======================
|
|
// SPÉCIFIQUE À CETTE PAGE
|
|
// =======================
|
|
.actus--page {
|
|
.actus-main-zone {
|
|
position: relative;
|
|
}
|
|
|
|
.grid_3 {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 8%;
|
|
}
|
|
|
|
.card_focus {
|
|
.grid_3 {
|
|
gap: 0px;
|
|
}
|
|
@media (max-width: 700px) {
|
|
.grid_3 {
|
|
grid-template-columns: repeat(3, 1fr);
|
|
|
|
}
|
|
}
|
|
@media (max-width: 500px) {
|
|
.grid_3 {
|
|
grid-template-columns: repeat(1, 1fr);
|
|
}
|
|
}
|
|
.card_focus--content {
|
|
position: relative;
|
|
width: 100%;
|
|
margin-inline: auto;
|
|
padding: 1.5rem;
|
|
background: var(--c-gris);
|
|
}
|
|
}
|
|
.card {
|
|
position: relative;
|
|
display: flex;
|
|
flex-direction: column;
|
|
background: white;
|
|
min-height: 0;
|
|
|
|
&--content {
|
|
position: relative;
|
|
width: 84%;
|
|
min-height: 200px;
|
|
margin-inline: auto;
|
|
margin-top: -35px;
|
|
@media (max-width: 700px) {
|
|
margin-top: -45px;
|
|
}
|
|
padding: 1.5rem;
|
|
background: var(--c-grisclair);
|
|
}
|
|
|
|
&--title-link {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
|
|
&:hover,
|
|
&:focus-visible {
|
|
color: var(--c-bleu);
|
|
text-decoration: none;
|
|
}
|
|
}
|
|
}
|
|
.card--img {
|
|
min-height: 0; /* Crucial pour permettre au flex-item de rétrécir */
|
|
background-color: var(--c-gris);
|
|
}
|
|
|
|
.actus-overlay-section {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 1000;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
overflow: hidden;
|
|
background: linear-gradient(
|
|
to right,
|
|
rgb(0 0 0 / 71%) 0%,
|
|
rgb(0 0 0 / 71%) 20%,
|
|
transparent 20%,
|
|
transparent 100%
|
|
);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.actus-overlay {
|
|
display: flex;
|
|
flex-direction: column;
|
|
width: 80%;
|
|
height: 100vh;
|
|
padding: 2rem;
|
|
overflow-y: auto;
|
|
background: var(--c-backgroud-brandreverse);
|
|
box-shadow: 0 0 40px rgb(0 0 0 / 18%);
|
|
cursor: auto;
|
|
|
|
&--close {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
align-self: flex-end;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
margin-bottom: 1.5rem;
|
|
color: inherit;
|
|
text-decoration: none;
|
|
|
|
&-icon {
|
|
width: 4rem;
|
|
height: 4rem;
|
|
fill: currentColor;
|
|
flex: 0 0 auto;
|
|
}
|
|
}
|
|
|
|
&--close-bottom {
|
|
display: inline-flex;
|
|
margin-top: 2rem;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
&--image {
|
|
max-width: 360px;
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
&--content {
|
|
max-width: 680px;
|
|
}
|
|
&--metas {
|
|
display: flex;
|
|
column-gap: 25px;
|
|
padding-bottom: 10px;
|
|
}
|
|
&--date {
|
|
margin-bottom: 0.75rem;
|
|
}
|
|
}
|
|
|
|
.img-gallery {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 300px));
|
|
gap: 1rem;
|
|
justify-content:left;
|
|
margin-top: 10px;
|
|
padding-bottom: 0px;
|
|
}
|
|
|
|
.youtube_wp {
|
|
margin-top: 1rem;
|
|
margin-bottom: 2rem;
|
|
}
|
|
|
|
.youtube-list {
|
|
display: grid;
|
|
grid-template-columns: 1fr;
|
|
gap: 1rem;
|
|
justify-content: start;
|
|
}
|
|
|
|
.youtube-item {
|
|
max-width: 500px;
|
|
|
|
iframe {
|
|
width: 100%;
|
|
aspect-ratio: 16 / 9;
|
|
border: 0;
|
|
}
|
|
}
|
|
|
|
|
|
@media (max-width: 700px) {
|
|
.grid_3 {
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 2rem;
|
|
}
|
|
.actus-overlay {
|
|
width: 100%;
|
|
margin-left: 0;
|
|
}
|
|
}
|
|
@media (max-width: 360px) {
|
|
.grid_3 {
|
|
grid-template-columns: 1fr;
|
|
gap: 2rem;
|
|
}
|
|
|
|
.actus-overlay {
|
|
width: 100%;
|
|
margin-left: 0;
|
|
}
|
|
|
|
.img-gallery {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
|
|
.fiche_description {
|
|
display: flex;
|
|
justify-content: center;
|
|
padding-top: 10px;
|
|
padding-bottom: 10px;
|
|
padding-left: 10px;
|
|
padding-right: 10px;
|
|
> * {
|
|
max-width: 640px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
.strapi-blocks {
|
|
h2 {
|
|
color: var(--c-bleu);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ============================ */
|
|
/* GALERIES */
|
|
/* ============================ */
|
|
|
|
</style>
|