avancées centre de ressources

This commit is contained in:
2025-03-28 15:10:03 +01:00
parent a1916e3219
commit d805ef35b1
14 changed files with 380 additions and 225 deletions

View File

@@ -1,8 +1,5 @@
<template>
<div id="centre-de-ressource">
<div v-if="content.intro" class="intro">
<!-- <p v-html="content.intro"></p> -->
</div>
<div id="centre-de-ressource" :style="{ '--couleur': couleur }">
<div class="filters">
<input type="text" v-model="searchQuery" placeholder="Rechercher..." class="search-bar">
<select v-model="selectedType">
@@ -12,24 +9,17 @@
</option>
</select>
</div>
<template v-for="type in filteredTypes" :key="type">
<div v-if="content.intro" v-html="content.intro" class="intro"></div>
<template v-for="(type, typeIndex) in filteredTypes" :key="type">
<div class="type-section" v-if="ressourcesToDisplay[type] && ressourcesToDisplay[type].length > 0">
<h3>{{ type.replace(/_/g, ' ').replace(/^\w/, char => char.toUpperCase()) }}</h3>
<div class="ressource-list">
<TransitionGroup name="itemFade" tag="div" appear>
<div class="ressource-item"
:data-href="ressource.url"
<div class="ressource-item"
v-for="(ressource, ressourceIndex) in ressourcesToDisplay[type]"
:key="`${type}-${ressourceIndex}`"
:style="{ '--index': ressourceIndex - visibleItemsPerSection }">
<figure>
<img :src="ressource.vignette.url" :alt="ressource.vignette.alt" />
</figure>
<div>
<h4>{{ ressource.title }}</h4>
<p>Le {{ ressource.date.d }} {{ ressource.date.m }} {{ ressource.date.y }}</p>
<p>Par {{ ressource.auteurice }}</p>
</div>
<RessourceCard :ressource="ressource" :index="`${typeIndex}-${ressourceIndex}`" />
</div>
</TransitionGroup>
</div>
@@ -52,17 +42,9 @@
</template>
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import router from '../../router/router';
import RessourceCard from './RessourceCard.vue';
import { useContentStore } from '../../stores/content';
import { useMapStore } from '../../stores/map';
import { handleClickableElements } from '../../utils/handle-navigation.js';
const store = useContentStore();
const mapStore = useMapStore();
const siteName = document.querySelector('#site_name').innerText;
import { ref, computed, watch, nextTick } from 'vue';
const props = defineProps({
content: Object,
@@ -111,31 +93,28 @@ watch(searchQuery, () => {
});
});
let relatedItemCards, baseUrl;
watch(ressourcesToDisplay.value, () => {
setClickableElements();
watch(ressourcesToDisplay.value, async () => {
await nextTick();
document.querySelectorAll('.ressource-item > div').forEach(el => {
const card = el.__vueParentComponent.exposed;
if (card && card.setClickableElements) {
card.setClickableElements();
}
});
}, { deep: true });
watch(selectedType, () => {
setClickableElements();
watch(selectedType, async () => {
await nextTick();
document.querySelectorAll('.ressource-item > div').forEach(el => {
const card = el.__vueParentComponent.exposed;
if (card && card.setClickableElements) {
card.setClickableElements();
}
});
});
onMounted(() => {
baseUrl = window.location.protocol + "//" + window.location.host;
setClickableElements();
});
function setClickableElements() {
setTimeout(() => {
relatedItemCards = document.querySelectorAll('.ressource-item');
handleClickableElements(relatedItemCards, store, router, baseUrl, siteName, mapStore);
}, 50);
}
</script>
<style scoped>
<style lang="scss" scoped>
.itemFade-enter-active, .itemFade-leave-active {
transition: all 0.3s ease !important;
transition-delay: calc(0.1s * var(--index)) !important;
@@ -150,4 +129,27 @@ function setClickableElements() {
opacity: 1;
transform: translateY(0px);
}
.filters {
margin: 3rem 0;
margin-top: 5rem;
> .search-bar{
margin-right: 2rem;
border: solid 1px var(--couleur);
padding: 0.5rem 1rem;
border-radius: 1rem;
font-family: 'Marianne', sans-serif;
}
> select {
appearance: none;
border: solid 1px var(--couleur);
padding: 0.5rem 1rem;
font-family: 'Marianne', sans-serif;
border-radius: 1rem;
background-color: white;
background: url("data:image/svg+xml,<svg height='10px' width='10px' viewBox='0 0 16 16' fill='rgba(128, 200, 191)' xmlns='http://www.w3.org/2000/svg'><path d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/></svg>") no-repeat;
background-position: calc(100% - 1rem) center !important;
padding-right: 2.5rem !important;
}
}
</style>

View File

@@ -0,0 +1,39 @@
<template>
<div class="card" :class="direction ? (direction === 'previous' ? 'previous' : 'next') : 'solo'" :data-href="relatedContent.url">
<div class="icon" :style="{ backgroundColor: relatedContent.couleur }"></div>
<div class="card-content">
<div class="infos">
<div class="titre">{{ relatedContent.title }} <span>({{ relatedContent.postalCode.slice(0, 2) }})</span></div>
<div class="date">Du {{ relatedContent.dates.start.d }} {{ relatedContent.dates.start.m }}<br>au {{ relatedContent.dates.end.d }} {{ relatedContent.dates.end.m }} {{ relatedContent.dates.end.y }}</div>
</div>
<div class="vignette">
<img :src="relatedContent.vignette.url.small" :alt="relatedContent.vignette.alt">
</div>
</div>
</div>
</template>
<script setup>
const props = defineProps({
relatedContent: Object,
direction: String,
});
import { onMounted } from 'vue';
import router from '../../router/router';
import { useContentStore } from '../../stores/content';
import { useMapStore } from '../../stores/map';
import { handleClickableElements } from '../../utils/handle-navigation.js';
const store = useContentStore();
const mapStore = useMapStore();
const siteName = document.querySelector('#site_name').innerText;
onMounted(() => {
const relatedEtapesCards = document.querySelectorAll('.card');
const baseUrl = window.location.protocol + "//" + window.location.host;
handleClickableElements(relatedEtapesCards, store, router, baseUrl, siteName, mapStore);
});
</script>

View File

@@ -16,6 +16,7 @@
:navigation="true"
:pagination="true"
:initialSlide="currentSlideIndex"
:keyboard="{ enabled: true }"
:injectStyles="[`
.swiper-button-next, .swiper-button-prev {
color: white;

View File

@@ -5,49 +5,20 @@
</div>
<div v-if="contentType === 'etape' && (content.previous || content.next)" class="related-etape-links">
<div v-if="content.previous" class="card previous" :data-href="content.previous.url">
<div class="icon" :style="{ backgroundColor: content.previous.couleur }"></div>
<div class="card-content">
<div class="infos">
<div class="titre">{{ content.previous.title }} <span>({{ content.previous.postalCode.slice(0, 2) }})</span></div>
<div class="date">Du {{ content.previous.dates.start.d }} {{ content.previous.dates.start.m }}<br>au {{ content.previous.dates.end.d }} {{ content.previous.dates.end.m }} {{ content.previous.dates.end.y }}</div>
</div>
<div class="vignette">
<img :src="content.previous.vignette.url.small" :alt="content.previous.vignette.alt">
</div>
</div>
</div>
<div v-if="content.next" class="card next" :data-href="content.next.url">
<div class="icon" :style="{ backgroundColor: content.next.couleur }"></div>
<div class="card-content">
<div class="infos">
<div class="titre">{{ content.next.title }} <span>({{ content.next.postalCode.slice(0, 2) }})</span></div>
<div class="date">Du {{ content.next.dates.start.d }} {{ content.next.dates.start.m }}<br>au {{ content.next.dates.end.d }} {{ content.next.dates.end.m }} {{ content.next.dates.end.y }}</div>
</div>
<div class="vignette">
<img :src="content.next.vignette.url.small" :alt="content.next.vignette.alt">
</div>
</div>
<EtapeCard v-if="content.previous" :relatedContent="content.previous" :direction="'previous'"/>
<EtapeCard v-if="content.next" :relatedContent="content.next" :direction="'next'"/>
</div>
<div v-if="contentType === 'ressourceItem' && content.relatedEtape" >
<div class="related-etape-label" :style="{ backgroundColor: couleur }">Étape de la ressource</div>
<div class="related-etape-links">
<EtapeCard :relatedContent="content.relatedEtape" :direction="''" />
</div>
</div>
</footer>
</template>
<script setup>
import { onMounted } from 'vue';
import router from '../../router/router';
import { useContentStore } from '../../stores/content';
import { useMapStore } from '../../stores/map';
import { handleClickableElements } from '../../utils/handle-navigation.js';
const brandColor = "#80c8bf";
const store = useContentStore();
const mapStore = useMapStore();
const siteName = document.querySelector('#site_name').innerText;
import EtapeCard from './EtapeCard.vue';
const props = defineProps({
contentType: String,
@@ -55,10 +26,4 @@ const props = defineProps({
couleur: String,
map: Object,
});
onMounted(() => {
const relatedEtapesCards = document.querySelectorAll('.card');
const baseUrl = window.location.protocol + "//" + window.location.host;
handleClickableElements(relatedEtapesCards, store, router, baseUrl, siteName, mapStore);
});
</script>

View File

@@ -0,0 +1,23 @@
<template>
<div class="partie related-ressources">
<h3>
<p :style="{ background: `linear-gradient(transparent 70%, ${couleur} 70%)` }">
Ressources liées
</p>
</h3>
<div class="ressource-list sm-ressource-list">
<div class="ressource-item" v-for="(relatedRessource, index) in relatedRessources">
<RessourceCard :ressource="relatedRessource" :index="index" />
</div>
</div>
</div>
</template>
<script setup>
import RessourceCard from './RessourceCard.vue';
const props = defineProps({
relatedRessources: Object,
couleur: String,
});
</script>

View File

@@ -0,0 +1,49 @@
<template>
<div
:data-href="ressource.url"
:id="`ressource-${index}`">
<figure>
<img :src="ressource.vignette.url" :alt="ressource.vignette.alt" />
</figure>
<div>
<h4>{{ ressource.title }}</h4>
<p>Le {{ ressource.date.d }} {{ ressource.date.m }} {{ ressource.date.y }}</p>
<p>Par {{ ressource.auteurice }}</p>
</div>
</div>
</template>
<script setup>
import { onMounted, defineExpose } from 'vue';
import router from '../../router/router';
import { handleClickableElements } from '../../utils/handle-navigation.js';
import { useContentStore } from '../../stores/content';
import { useMapStore } from '../../stores/map';
const store = useContentStore();
const mapStore = useMapStore();
const siteName = document.querySelector('#site_name').innerText;
let relatedItemCards, baseUrl;
onMounted(() => {
baseUrl = window.location.protocol + "//" + window.location.host;
setClickableElements();
});
const setClickableElements = () => {
relatedItemCards = document.querySelector(`#ressource-${props.index}`);
console.log(relatedItemCards);
handleClickableElements([relatedItemCards], store, router, baseUrl, siteName, mapStore);
}
defineExpose({
setClickableElements,
});
const props = defineProps({
ressource: Object,
index: String,
});
</script>

View File

@@ -47,6 +47,9 @@ function setDisplayedType() {
case 'videos':
props.content.displayedType = 'Vidéo';
break;
case 'reportages':
props.content.displayedType = 'Reportage';
break;
}
}

View File

@@ -21,6 +21,10 @@
import { onMounted } from 'vue';
import { useImageModal } from '../../composables/useImageModale';
import ImageModale from '../ImageModale.vue';
// WebComponent
// https://swiperjs.com/element
import { register } from 'swiper/element/bundle';
register();
const props = defineProps({
partie: Object,
@@ -36,10 +40,10 @@ const {
} = useImageModal();
const handleImageClick = (event) => {
const img = event.target;
if (img.tagName === 'IMG') {
const clickedImg = event.target;
if (clickedImg.tagName === 'IMG') {
let swiperMedia = [];
const imgGrid = img.closest('.images-grid');
const imgGrid = clickedImg.closest('.images-grid');
imgGrid.querySelectorAll('figure').forEach((figure) => {
const img = figure.querySelector('img');
@@ -50,15 +54,13 @@ const handleImageClick = (event) => {
}
});
});
console.log(swiperMedia);
openImageModale(img.src, img.alt, swiperMedia);
openImageModale(clickedImg.src, clickedImg.alt, swiperMedia);
}
}
onMounted(() => {
setVerticalImages();
document.documentElement.style.setProperty('--etape-couleur', props.couleur);
});
function setVerticalImages() {
@@ -70,4 +72,13 @@ function setVerticalImages() {
}
});
}
</script>
</script>
<style lang="scss" scoped>
:root {
--swiper-navigation-color: #1a1918; /* cf main.scss */
--swiper-pagination-color: var(--etape-couleur);
--swiper-navigation-top-offset: calc(100% - 1.5rem);
--swiper-navigation-sides-offset: 5vw; /* cf main.scss */
}
</style>