refactor du système de routing (EXPORTS DES SETTINGS DRUPAL)
This commit is contained in:
@@ -1,44 +1,46 @@
|
||||
<template>
|
||||
<Transition>
|
||||
<div v-if="isEtapeValid || isPageValid">
|
||||
<div v-if="!loading && (contentType === 'etape' || contentType === 'static')">
|
||||
<div class="content-wrapper">
|
||||
<ModaleHeader
|
||||
:content="etape.title ? etape : page"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
<ModaleHeader
|
||||
:contentType="contentType"
|
||||
:content="content"
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<main>
|
||||
<div v-for="partie in etape.parties || page.parties" class="partie">
|
||||
<div v-for="partie in content.parties" class="partie">
|
||||
<ModaleCarteSensible
|
||||
v-if="partie.type === 'carte_sensible'"
|
||||
:partie="partie" />
|
||||
<ModaleTitreTexte
|
||||
v-if="partie.type === 'titre_texte'"
|
||||
:partie="partie"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<ModaleChiffresCles
|
||||
v-if="partie.type === 'chiffres_cles'"
|
||||
:partie="partie"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<ModaleDiaporama
|
||||
v-if="partie.type === 'diaporama'"
|
||||
:partie="partie"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<ModaleEntretien
|
||||
v-if="partie.type === 'entretien'"
|
||||
:partie="partie"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<ModaleExergue
|
||||
v-if="partie.type === 'exergue'"
|
||||
:partie="partie"
|
||||
:couleur="etape.couleur || brandColor" />
|
||||
:couleur="content.couleur || brandColor" />
|
||||
<ModaleVideos
|
||||
v-if="partie.type === 'video'"
|
||||
:partie="partie" />
|
||||
</div>
|
||||
</main>
|
||||
<ModaleFooter
|
||||
:content="etape || page"
|
||||
:couleur="etape.couleur || brandColor"
|
||||
:map="map" />
|
||||
:contentType="contentType"
|
||||
:content="content"
|
||||
:couleur="content.couleur || brandColor"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
@@ -46,10 +48,10 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, watch, onMounted } from 'vue';
|
||||
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useContentStore } from '../stores/content';
|
||||
import { useMapStore } from '../stores/mapState';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
|
||||
import ModaleHeader from './components/ModaleHeader.vue';
|
||||
import ModaleFooter from './components/ModaleFooter.vue';
|
||||
@@ -62,132 +64,95 @@ import ModaleEntretien from './components/parties/ModaleEntretien.vue';
|
||||
import ModaleExergue from './components/parties/ModaleExergue.vue';
|
||||
import ModaleVideos from './components/parties/ModaleVideos.vue';
|
||||
|
||||
import { useUtils } from './composables/useUtils';
|
||||
const { isObjectEmpty, scrollTop } = useUtils();
|
||||
|
||||
const router = useRouter();
|
||||
const store = useContentStore();
|
||||
const mapState = useMapStore();
|
||||
const route = useRoute();
|
||||
|
||||
const { loading, error, href, map, etape, page } = storeToRefs(store);
|
||||
const { duration } = storeToRefs(mapState);
|
||||
const {
|
||||
contentType,
|
||||
content,
|
||||
loading,
|
||||
error,
|
||||
} = storeToRefs(store);
|
||||
|
||||
const isEtapeValid = computed(() => !error.value && !loading.value && etape.value && !isObjectEmpty(etape.value));
|
||||
const isPageValid = computed(() => !error.value && !loading.value && page.value && !isObjectEmpty(page.value));
|
||||
const { map, duration } = storeToRefs(mapState);
|
||||
|
||||
let isModaleEtape, wasModaleEtape;
|
||||
|
||||
const brandColor = "#80c8bf";
|
||||
|
||||
let isProgrammaticNavigation = false;
|
||||
|
||||
const handleRouteChange = () => {
|
||||
watch(
|
||||
() => route.params.id,
|
||||
(newId) => {
|
||||
if (isProgrammaticNavigation) {
|
||||
isProgrammaticNavigation = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newId) {
|
||||
store.emptyAll(map.value);
|
||||
} else {
|
||||
store.fetchEtapeData(newId, map.value);
|
||||
if (!etape.value?.data) {
|
||||
store.fetchStaticData(newId, map.value);
|
||||
}
|
||||
scrollTop();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
};
|
||||
|
||||
const handleColorChange = () => {
|
||||
watch(
|
||||
() => href.value,
|
||||
() => {
|
||||
document.documentElement.style.setProperty('--etape-couleur', etape.value.couleur || brandColor);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleHrefChange = () => {
|
||||
watch(
|
||||
() => href.value,
|
||||
(newHref) => {
|
||||
const relativePath = newHref.split('.fr')[1];
|
||||
isProgrammaticNavigation = true;
|
||||
if (newHref == '') {
|
||||
router.push('/');
|
||||
mapState.unlockMap(map.value)
|
||||
} else {
|
||||
if (relativePath && relativePath !== '' && relativePath !== '/') {
|
||||
mapState.lockMap(map.value);
|
||||
router.push(relativePath);
|
||||
scrollTop();
|
||||
}
|
||||
}
|
||||
() => content.value.couleur,
|
||||
() => {
|
||||
if (contentType.value === 'etape' && content.value.couleur) {
|
||||
document.documentElement.style.setProperty('--etape-couleur', content.value.couleur || brandColor);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const handleMapMovement = () => {
|
||||
watch(
|
||||
() => href.value,
|
||||
() => loading.value,
|
||||
() => {
|
||||
isModaleEtape = !isObjectEmpty(etape.value);
|
||||
|
||||
if (!wasModaleEtape && isModaleEtape) {
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', `${duration.value}s`);
|
||||
mapState.zoomToPlace(map.value, etape.value.coordinates.lat, etape.value.coordinates.lon);
|
||||
|
||||
} else if (wasModaleEtape && isModaleEtape) {
|
||||
document.documentElement.style.setProperty('--modale-leave-delay', 0);
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', `${duration.value * 2}s`);
|
||||
mapState.resetMap(map.value);
|
||||
setTimeout(() => {
|
||||
mapState.zoomToPlace(map.value, etape.value.coordinates.lat, etape.value.coordinates.lon);
|
||||
}, duration.value * 1000);
|
||||
|
||||
} else if (wasModaleEtape && !isModaleEtape) {
|
||||
document.documentElement.style.setProperty('--modale-leave-delay', 0);
|
||||
mapState.resetMap(map.value);
|
||||
}
|
||||
|
||||
wasModaleEtape = isModaleEtape;
|
||||
if (!loading.value) {
|
||||
isModaleEtape = contentType.value === 'etape';
|
||||
|
||||
if (!wasModaleEtape && isModaleEtape) {
|
||||
// national -> détail
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', `${duration.value}s`);
|
||||
mapState.zoomToPlace(content.value.coordinates.lat, content.value.coordinates.lon);
|
||||
} else if (wasModaleEtape && isModaleEtape) {
|
||||
// détail -> détail
|
||||
document.documentElement.style.setProperty('--modale-leave-delay', 0);
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', `${duration.value * 2}s`);
|
||||
mapState.resetMap(map.value);
|
||||
setTimeout(() => {
|
||||
mapState.zoomToPlace(content.value.coordinates.lat, content.value.coordinates.lon);
|
||||
}, duration.value * 1000);
|
||||
|
||||
} else if (wasModaleEtape && !isModaleEtape) {
|
||||
// détail -> national
|
||||
document.documentElement.style.setProperty('--modale-leave-delay', 0);
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', `${duration.value}s`);
|
||||
mapState.resetMap();
|
||||
} else if (!wasModaleEtape && !isModaleEtape) {
|
||||
// national -> national
|
||||
console.log('national -> national');
|
||||
document.documentElement.style.setProperty('--modale-leave-delay', 0);
|
||||
document.documentElement.style.setProperty('--modale-enter-delay', '0.5s');
|
||||
}
|
||||
|
||||
wasModaleEtape = isModaleEtape;
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
isModaleEtape = !isObjectEmpty(etape.value);
|
||||
wasModaleEtape = isModaleEtape;
|
||||
handleRouteChange();
|
||||
handleColorChange();
|
||||
handleHrefChange();
|
||||
handleMapMovement();
|
||||
isModaleEtape = contentType.value === 'etape';
|
||||
wasModaleEtape = isModaleEtape;
|
||||
handleColorChange();
|
||||
handleMapMovement();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scss>
|
||||
<style scoped scss>
|
||||
.v-enter-active {
|
||||
transition: all 0.5s linear var(--modale-enter-delay);
|
||||
transition: margin-top 0.5s ease-out var(--modale-enter-delay);
|
||||
}
|
||||
|
||||
.v-leave-active {
|
||||
transition: all 0.5s linear var(--modale-leave-delay);
|
||||
transition: margin-top 0.5s ease-in var(--modale-leave-delay);
|
||||
}
|
||||
|
||||
.v-enter-from,
|
||||
.v-leave-to {
|
||||
transform: translateY(20vh);
|
||||
margin-top: 150vh;
|
||||
}
|
||||
|
||||
.v-enter-to,
|
||||
.v-leave-from {
|
||||
transform: translateY(0vh);
|
||||
margin-top: 0vh;
|
||||
}
|
||||
</style>
|
||||
@@ -4,8 +4,8 @@
|
||||
<div class="pattern"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="content.previous || content.next" class="related-etape-links">
|
||||
<div v-if="content.previous" class="card previous" @click="store.fetchEtapeData(content.previous.nid, map)">
|
||||
<div v-if="contentType === 'etape' && (content.previous || content.next)" class="related-etape-links">
|
||||
<div v-if="content.previous" class="card previous" @click="displayRelatedElement(content.previous.url)">
|
||||
<div class="icon">
|
||||
<div :style="{ backgroundColor: content.previous.couleur }"></div>
|
||||
<div :style="{ backgroundColor: content.previous.couleur }"></div>
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="content.next" class="card next" @click="store.fetchEtapeData(content.next.nid, map)">
|
||||
<div v-if="content.next" class="card next" @click="displayRelatedElement(content.next.url)">
|
||||
<div class="icon">
|
||||
<div :style="{ backgroundColor: content.next.couleur }"></div>
|
||||
<div :style="{ backgroundColor: content.next.couleur }"></div>
|
||||
@@ -42,14 +42,25 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import router from '../../router/router.js';
|
||||
import { useContentStore } from '../../stores/content';
|
||||
|
||||
const brandColor = "#80c8bf";
|
||||
|
||||
const store = useContentStore();
|
||||
const props = defineProps({
|
||||
contentType: String,
|
||||
content: Object,
|
||||
couleur: String,
|
||||
map: Object,
|
||||
});
|
||||
|
||||
async function displayRelatedElement(href) {
|
||||
const baseUrl = window.location.protocol + "//" + window.location.host;
|
||||
if (href.startsWith(baseUrl)) href = href.replace(baseUrl, '');
|
||||
|
||||
router.push(href);
|
||||
await store.fetchContentData(baseUrl + href);
|
||||
document.title = store.pageTitle;
|
||||
}
|
||||
</script>
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<header :style="content.vignette ? '' : { marginTop: '20vh' }">
|
||||
<div class="cover">
|
||||
<img v-if="content.vignette" :src="content.vignette.url" :alt="content.vignette.alt">
|
||||
<img v-if="content.vignette" :src="content.vignette.url" :alt="content.vignette.alt">
|
||||
</div>
|
||||
<div v-if="content.dates" class="cartouche" :style="{ backgroundColor: couleur }">
|
||||
<div v-if="contentType === 'etape' && content.dates" class="cartouche" :style="{ backgroundColor: couleur }">
|
||||
<p>Étape n°{{content.etape_number}}</p>
|
||||
<p>Du {{content.dates.start.d}} {{content.dates.start.m}} au {{ content.dates.end.d }} {{ content.dates.end.m }} {{ content.dates.end.y }}</p>
|
||||
</div>
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="locality">
|
||||
<div class="top-triangle"></div>
|
||||
<div class="locality-title">
|
||||
<h1>{{content.title}} <em v-if="content.adresse">({{ content.adresse.postal_code.slice(0, 2) }})</em></h1>
|
||||
<h1>{{content.contentTitle}} <em v-if="content.adresse">({{ content.adresse.postal_code.slice(0, 2) }})</em></h1>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
contentType: String,
|
||||
content: Object,
|
||||
couleur: String,
|
||||
});
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
export function useUtils() {
|
||||
const isObjectEmpty = (obj) => {
|
||||
if (!obj || typeof obj !== 'object') return true;
|
||||
|
||||
return !Object.keys(obj).some((key) => {
|
||||
const value = obj[key];
|
||||
if (Array.isArray(value)) return value.length > 0;
|
||||
if (typeof value === 'object') return !isObjectEmpty(value);
|
||||
return value !== null && value !== undefined && value !== '';
|
||||
});
|
||||
};
|
||||
|
||||
const scrollTop = () => {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
};
|
||||
|
||||
return {
|
||||
isObjectEmpty,
|
||||
scrollTop,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user