filtre ressources par étape + triées par ordre chrono

This commit is contained in:
Valentin Le Moign 2025-05-20 20:07:03 +02:00
parent e7a5e163ff
commit bfb39a0259
6 changed files with 66 additions and 5 deletions

View File

@ -188,9 +188,10 @@ export const useContentStore = defineStore('content', {
case 'gouvernance': case 'gouvernance':
multiItemPageArray = await getGouvernance(rawContent); multiItemPageArray = await getGouvernance(rawContent);
break; break;
} }
this.content[`${this.contentType}s`] = multiItemPageArray; this.content[`${this.contentType}s`] = multiItemPageArray;
} }
} catch (error) { } catch (error) {
this.error = 'Failed to fetch data'; this.error = 'Failed to fetch data';

View File

@ -120,6 +120,8 @@ export async function getRessourceItemCard(item) {
vignette = null; vignette = null;
} }
} }
const relatedEtape = await REST.get(item.relationships.field_etape.links.related.href);
return { return {
ressourceType: item.attributes.field_type_de_ressource, ressourceType: item.attributes.field_type_de_ressource,
@ -127,6 +129,7 @@ export async function getRessourceItemCard(item) {
auteurice: item.attributes.field_autheurice, auteurice: item.attributes.field_autheurice,
date: getCleanDate(item.attributes.field_date_ressource), date: getCleanDate(item.attributes.field_date_ressource),
url: ressourceFetch.data.data.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href, url: ressourceFetch.data.data.attributes.metatag.find(tag => tag.tag === "link")?.attributes.href,
relatedEtape: relatedEtape.data.data.attributes.title,
vignette vignette
}; };
} catch (error) { } catch (error) {

View File

@ -55,6 +55,8 @@ export async function getGouvernance(rawContent) {
} }
export async function getRessources(rawContent) { export async function getRessources(rawContent) {
console.log(rawContent);
const ressourcesPromises = rawContent.map(item => getRessourceItemCard(item)); const ressourcesPromises = rawContent.map(item => getRessourceItemCard(item));
return await Promise.all(ressourcesPromises); return await Promise.all(ressourcesPromises);

View File

@ -8,6 +8,12 @@
{{ type.replace(/_/g, ' ').replace(/^\w/, char => char.toUpperCase()) }} {{ type.replace(/_/g, ' ').replace(/^\w/, char => char.toUpperCase()) }}
</option> </option>
</select> </select>
<select v-model="selectedEtape">
<option value="">Toutes les étapes</option>
<option v-for="etape in allRelatedEtapes" :key="etape" :value="etape">
{{ etape }}
</option>
</select>
</div> </div>
<div v-if="content.intro" v-html="content.intro" class="intro"></div> <div v-if="content.intro" v-html="content.intro" class="intro"></div>
<template v-for="(type, typeIndex) in filteredTypes" :key="type"> <template v-for="(type, typeIndex) in filteredTypes" :key="type">
@ -43,6 +49,7 @@
<script setup> <script setup>
import RessourceCard from './RessourceCard.vue'; import RessourceCard from './RessourceCard.vue';
import useParseDate from '../composables/useParseDates';
import { ref, computed, watch, nextTick } from 'vue'; import { ref, computed, watch, nextTick } from 'vue';
@ -55,6 +62,14 @@ const searchQuery = ref('');
const selectedType = ref(''); const selectedType = ref('');
const ressourcesToDisplay = ref({}); const ressourcesToDisplay = ref({});
const visibleItemsPerSection = 4; const visibleItemsPerSection = 4;
const selectedEtape = ref('');
const allRelatedEtapes = new Set();
props.content.ressources.forEach(ressource => {
if (ressource.relatedEtape) {
allRelatedEtapes.add(ressource.relatedEtape);
}
})
const filteredTypes = computed(() => { const filteredTypes = computed(() => {
return selectedType.value ? [selectedType.value] : props.content.ressourceTypes; return selectedType.value ? [selectedType.value] : props.content.ressourceTypes;
@ -62,12 +77,18 @@ const filteredTypes = computed(() => {
const ressourcesByType = (type) => { const ressourcesByType = (type) => {
return props.content.ressources return props.content.ressources
.filter(ressource => !selectedEtape.value || ressource.relatedEtape === selectedEtape.value)
.filter(ressource => ressource.ressourceType === type) .filter(ressource => ressource.ressourceType === type)
.filter(ressource => .filter(ressource =>
searchQuery.value === '' || searchQuery.value === '' ||
ressource.title.toLowerCase().includes(searchQuery.value.toLowerCase()) ressource.title.toLowerCase().includes(searchQuery.value.toLowerCase())
); ).sort((a, b) => {
} const dateA = useParseDate(a.date);
const dateB = useParseDate(b.date);
return dateB - dateA; // descending order (newest first)
});
};
const initializeRessources = (type) => { const initializeRessources = (type) => {
ressourcesToDisplay.value[type] = ressourcesByType(type).slice(0, visibleItemsPerSection); ressourcesToDisplay.value[type] = ressourcesByType(type).slice(0, visibleItemsPerSection);
@ -112,6 +133,12 @@ watch(selectedType, async () => {
} }
}); });
}); });
watch(selectedEtape, () => {
props.content.ressourceTypes.forEach(type => {
initializeRessources(type);
});
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -0,0 +1,26 @@
const frenchMonthMap = {
janvier: 0,
février: 1,
mars: 2,
avril: 3,
mai: 4,
juin: 5,
juillet: 6,
août: 7,
septembre: 8,
octobre: 9,
novembre: 10,
décembre: 11
};
export default function parseDate(dateObj) {
if (!dateObj || !frenchMonthMap[dateObj.m?.toLowerCase()]) return new Date(0);
const day = Number(dateObj.d);
const month = frenchMonthMap[dateObj.m.toLowerCase()];
const year = Number(dateObj.y);
if (isNaN(day) || isNaN(month) || isNaN(year)) return new Date(0);
return new Date(year, month, day);
}

View File

@ -1292,6 +1292,8 @@ body{
font-family: 'Marianne', sans-serif; font-family: 'Marianne', sans-serif;
} }
> select { > select {
max-width: 20%;
margin-right: 2rem;
appearance: none; appearance: none;
border: solid 1px var(--couleur); border: solid 1px var(--couleur);
padding: 0.5rem 1rem; padding: 0.5rem 1rem;