2024-07-31 00:33:21 +02:00
|
|
|
<template>
|
2024-07-31 02:13:40 +02:00
|
|
|
<Transition>
|
2024-08-05 21:08:09 +02:00
|
|
|
<div v-if="isEtapeValid">
|
2024-07-31 02:13:40 +02:00
|
|
|
<header>
|
2024-09-11 19:53:18 +02:00
|
|
|
<div class="cover">
|
|
|
|
<img :src="etape.vignette.url" :alt="etape.vignette.alt">
|
|
|
|
</div>
|
|
|
|
<div class="cartouche" :style="{ backgroundColor: etape.couleur }">
|
2024-07-31 02:13:40 +02:00
|
|
|
<p>Étape n°{{etape.etape_number}}</p>
|
2024-09-11 19:53:18 +02:00
|
|
|
<p>Du {{etape.dates.start.d}} {{etape.dates.start.m}} au {{ etape.dates.end.d }} {{ etape.dates.end.m }} {{ etape.dates.end.y }}</p>
|
|
|
|
</div>
|
|
|
|
<div class="brand-pattern" :style="{ backgroundColor: etape.couleur }">
|
|
|
|
<div class="pattern"></div>
|
|
|
|
</div>
|
|
|
|
<div class="locality">
|
|
|
|
<div class="top-triangle"></div>
|
|
|
|
<div class="locality-title">
|
|
|
|
<h1>{{etape.title}} <em>({{ etape.adresse.postal_code }})</em></h1>
|
|
|
|
</div>
|
2024-07-31 02:13:40 +02:00
|
|
|
</div>
|
|
|
|
</header>
|
|
|
|
<main>
|
2024-09-11 19:53:18 +02:00
|
|
|
<div v-for="partie in etape.parties" class="partie">
|
|
|
|
<div class="partie-title">
|
|
|
|
<h3>
|
|
|
|
<div class="underline" :style="{ backgroundColor: etape.couleur }"></div>
|
|
|
|
<p v-html="partie.title"></p>
|
|
|
|
</h3>
|
|
|
|
</div>
|
2024-07-31 02:13:40 +02:00
|
|
|
<p v-html="partie.text"></p>
|
|
|
|
</div>
|
|
|
|
</main>
|
2024-08-05 21:08:09 +02:00
|
|
|
|
2024-07-31 02:13:40 +02:00
|
|
|
<!--
|
|
|
|
<div v-if="loading">Loading...</div>
|
|
|
|
<div v-if="error">{{ error }}</div>
|
2024-09-11 19:53:18 +02:00
|
|
|
{{etape.adresse.locality}}
|
2024-07-31 02:13:40 +02:00
|
|
|
-->
|
|
|
|
|
|
|
|
<div><pre>{{href}}</pre></div>
|
|
|
|
|
|
|
|
|
|
|
|
<div><pre><b>GEOFIELD</b>{{etape.geofield}}</pre></div>
|
2024-08-09 17:04:53 +02:00
|
|
|
<div><pre><b>VIGNETTE</b>{{etape.vignette}}</pre></div>
|
2024-07-31 02:13:40 +02:00
|
|
|
<div><pre><b>GALERIES</b>{{etape.galeries}}</pre></div>
|
|
|
|
<div><pre><b>PARTIES</b>{{etape.parties}}</pre></div>
|
|
|
|
<div><pre><b>SAISON</b>{{etape.saison}}</pre></div>
|
|
|
|
<div><pre><b>THEMATIQUES</b>{{etape.thematiques}}</pre></div>
|
|
|
|
|
|
|
|
|
2024-07-31 00:33:21 +02:00
|
|
|
<div>
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-07-31 02:13:40 +02:00
|
|
|
</Transition>
|
|
|
|
<Transition>
|
2024-08-05 21:08:09 +02:00
|
|
|
<div v-if="isPageValid">
|
2024-07-31 02:13:40 +02:00
|
|
|
<header>
|
|
|
|
<h1>{{ page.title }}</h1>
|
|
|
|
</header>
|
|
|
|
<main>
|
|
|
|
<div v-html="page.text"></div>
|
|
|
|
</main>
|
|
|
|
</div>
|
|
|
|
</Transition>
|
2024-07-31 00:33:21 +02:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
2024-08-05 21:08:09 +02:00
|
|
|
import { ref, computed, watch } from 'vue';
|
|
|
|
import { storeToRefs } from 'pinia';
|
|
|
|
import { useContentStore } from '../stores/content';
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const store = useContentStore();
|
|
|
|
const route = useRoute();
|
2024-07-31 00:33:21 +02:00
|
|
|
|
2024-08-05 21:08:09 +02:00
|
|
|
const { loading, error, href, etape, page } = storeToRefs(store);
|
2024-07-31 00:33:21 +02:00
|
|
|
|
2024-08-05 21:08:09 +02:00
|
|
|
watch(() => route.params.id, (newId) => {
|
2024-08-09 17:04:53 +02:00
|
|
|
if (!newId) {
|
|
|
|
store.emptyAll();
|
|
|
|
} else {
|
|
|
|
store.fetchEtapeData(newId);
|
|
|
|
if (!etape.value.data) {
|
|
|
|
store.fetchStaticData(newId);
|
|
|
|
}
|
|
|
|
window.scrollTo({top: 0, behavior: 'smooth'});
|
2024-08-05 21:08:09 +02:00
|
|
|
}
|
|
|
|
});
|
2024-07-31 00:33:21 +02:00
|
|
|
|
2024-08-05 21:08:09 +02:00
|
|
|
watch(() => href.value, (newHref) => {
|
|
|
|
const relativePath = newHref.split('.fr')[1];
|
|
|
|
if (relativePath && (relativePath !== '' || relativePath !== '/')) {
|
|
|
|
router.push(relativePath);
|
|
|
|
}
|
|
|
|
});
|
2024-07-31 02:13:40 +02:00
|
|
|
|
2024-08-05 21:08:09 +02:00
|
|
|
const isEtapeValid = computed(() => {
|
|
|
|
return etape.value && !isObjectEmpty(etape.value);
|
|
|
|
});
|
|
|
|
|
|
|
|
const isPageValid = computed(() => {
|
|
|
|
return page.value && !isObjectEmpty(page.value);
|
|
|
|
});
|
|
|
|
|
|
|
|
// Utility function to check if an object and its children are empty
|
|
|
|
function isObjectEmpty(obj) {
|
|
|
|
if (obj === null || obj === undefined || typeof obj !== 'object') {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
for (const key in obj) {
|
|
|
|
if (Object.hasOwnProperty.call(obj, key)) {
|
|
|
|
const value = obj[key];
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
if (value.length > 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (typeof value === 'object') {
|
|
|
|
if (!isObjectEmpty(value)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (value !== null && value !== undefined && value !== '') {
|
|
|
|
return false;
|
|
|
|
}
|
2024-07-31 02:13:40 +02:00
|
|
|
}
|
2024-08-05 21:08:09 +02:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-07-31 02:13:40 +02:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.v-enter-active,
|
|
|
|
.v-leave-active {
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
}
|
|
|
|
|
|
|
|
.v-enter-from,
|
|
|
|
.v-leave-to {
|
|
|
|
transform: translateY(100%);
|
|
|
|
opacity: 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
.v-leave-from {
|
|
|
|
transform: translateY(0%);
|
|
|
|
opacity: 1;
|
|
|
|
}
|
|
|
|
</style>
|