Compare commits
No commits in common. "575cc287179f31b6008d6827866620f55a741561" and "6e42e8c8000a9d568073fd073a23509f033335fb" have entirely different histories.
575cc28717
...
6e42e8c800
|
@ -28,7 +28,7 @@ coverage
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
# app
|
# app
|
||||||
src/*.json
|
src/data.json
|
||||||
public/answers
|
public/answers
|
||||||
public/homepage.webp
|
public/homepage.webp
|
||||||
public/logo.png
|
public/logo.png
|
||||||
|
|
|
@ -30,32 +30,6 @@ async function fetchAsset(uuid) {
|
||||||
return fetch(url);
|
return fetch(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchCertitudesData() {
|
|
||||||
const fields = ["*", "translations.*"];
|
|
||||||
const url = `/items/certitudes?${fields
|
|
||||||
.map((item) => `fields[]=${item}`)
|
|
||||||
.join("&")}`;
|
|
||||||
let certitudes = (await fetchJSONApi(url)).data;
|
|
||||||
await fs.writeFile(
|
|
||||||
"./src/certitudes.json",
|
|
||||||
JSON.stringify(certitudes),
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchCertitudesResultsData() {
|
|
||||||
const fields = ["*", "translations.*"];
|
|
||||||
const url = `/items/certitudes_results?${fields
|
|
||||||
.map((item) => `fields[]=${item}`)
|
|
||||||
.join("&")}`;
|
|
||||||
let certitudes = (await fetchJSONApi(url)).data;
|
|
||||||
await fs.writeFile(
|
|
||||||
"./src/certitudesResults.json",
|
|
||||||
JSON.stringify(certitudes),
|
|
||||||
"utf8",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function fetchScoresData() {
|
async function fetchScoresData() {
|
||||||
const fields = [
|
const fields = [
|
||||||
"*",
|
"*",
|
||||||
|
@ -338,8 +312,6 @@ async function fetchHomepageData() {
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
await fetchHomepageData();
|
await fetchHomepageData();
|
||||||
await fetchCertitudesData();
|
|
||||||
await fetchCertitudesResultsData();
|
|
||||||
await fetchScoresData();
|
await fetchScoresData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,3 @@ header svg.color-text [stroke] {
|
||||||
header svg.color-text [fill]:not([fill=none]) {
|
header svg.color-text [fill]:not([fill=none]) {
|
||||||
fill: var(--color-header-text)
|
fill: var(--color-header-text)
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,191 +0,0 @@
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watchEffect } from "vue";
|
|
||||||
import { useStore } from "@/stores"; // adapte le chemin si besoin
|
|
||||||
|
|
||||||
const store = useStore();
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
certitude: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const emits = defineEmits(["answerSelected", "nextQuestion"]);
|
|
||||||
|
|
||||||
const selectedWeight = ref(null);
|
|
||||||
|
|
||||||
// Utilise la langue du store
|
|
||||||
const language = computed(() => store.language || "fr-FR");
|
|
||||||
|
|
||||||
// Recherche la bonne traduction selon la langue courante
|
|
||||||
const translation = computed(() => {
|
|
||||||
return (
|
|
||||||
props.certitude.translations.find(
|
|
||||||
(t) => t.languages_code === language.value,
|
|
||||||
) ||
|
|
||||||
// Fallback en français
|
|
||||||
props.certitude.translations.find((t) => t.languages_code === "fr-FR") ||
|
|
||||||
// Fallback générique
|
|
||||||
props.certitude.translations[0]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Regroupe les réponses avec leurs poids
|
|
||||||
const answers = computed(() => {
|
|
||||||
return [1, 2, 3].map((i) => ({
|
|
||||||
id: i,
|
|
||||||
title: translation.value[`answer${i}`],
|
|
||||||
weight: props.certitude[`weight${i}`],
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
function selectAnswer(answer) {
|
|
||||||
selectedWeight.value = answer.weight;
|
|
||||||
emits("answerSelected", props.certitude, selectedWeight.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
if (answers.value.length && selectedWeight.value === null) {
|
|
||||||
selectAnswer(answers.value[0]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div class="main">
|
|
||||||
<div class="center">
|
|
||||||
<legend>{{ translation.title }}</legend>
|
|
||||||
<div class="description" v-html="translation.description"></div>
|
|
||||||
|
|
||||||
<ul class="choices">
|
|
||||||
<li class="choice" v-for="answer in answers" :key="answer.id">
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
:id="`certitude_${certitude.id}_answer_${answer.id}`"
|
|
||||||
:name="`certitude_${certitude.id}`"
|
|
||||||
:value="answer.weight"
|
|
||||||
v-model="selectedWeight"
|
|
||||||
@change="selectAnswer(answer)"
|
|
||||||
@click="$emit('nextQuestion')"
|
|
||||||
/>
|
|
||||||
<label :for="`certitude_${certitude.id}_answer_${answer.id}`">
|
|
||||||
<div>{{ answer.title }}</div>
|
|
||||||
</label>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="btns">
|
|
||||||
<button class="btn next" @click="$emit('nextQuestion')">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 40 40"
|
|
||||||
width="40"
|
|
||||||
height="40"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="m15.5 0.932-4.3 4.38 14.5 14.6-14.5 14.5 4.3 4.4 14.6-14.6 4.4-4.3-4.4-4.4-14.6-14.6z"
|
|
||||||
></path>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped lang="sass">
|
|
||||||
legend
|
|
||||||
text-align: center
|
|
||||||
font-size: 1.4rem
|
|
||||||
line-height: 2rem
|
|
||||||
font-weight: bold
|
|
||||||
width: 100%
|
|
||||||
|
|
||||||
.description
|
|
||||||
text-align: center
|
|
||||||
padding: 1rem
|
|
||||||
font-size: 1rem
|
|
||||||
|
|
||||||
.choices
|
|
||||||
list-style-type: none
|
|
||||||
text-align: left
|
|
||||||
display: inline-block
|
|
||||||
padding-left: 0
|
|
||||||
|
|
||||||
label
|
|
||||||
cursor: pointer
|
|
||||||
display: block
|
|
||||||
|
|
||||||
input[type=radio]
|
|
||||||
display: none
|
|
||||||
|
|
||||||
& + label > div
|
|
||||||
position: relative
|
|
||||||
padding: .2rem .2rem .2rem 2rem
|
|
||||||
|
|
||||||
& + label > div::before,
|
|
||||||
& + label > div::after
|
|
||||||
display: block
|
|
||||||
position: absolute
|
|
||||||
box-sizing: border-box
|
|
||||||
content:''
|
|
||||||
border-radius: 1rem
|
|
||||||
|
|
||||||
& + label > div::before
|
|
||||||
top: .5rem
|
|
||||||
left: 0
|
|
||||||
background-color: var(--color-green)
|
|
||||||
width: 1rem
|
|
||||||
height: 1rem
|
|
||||||
|
|
||||||
& + label > div::after
|
|
||||||
top: calc(3px + .5rem)
|
|
||||||
left: 3px
|
|
||||||
width: calc(1rem - 6px)
|
|
||||||
height: calc(1rem - 6px)
|
|
||||||
|
|
||||||
&:checked + label > div
|
|
||||||
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
|
|
||||||
|
|
||||||
&:checked + label > div::before
|
|
||||||
background-color: var(--color-green)
|
|
||||||
|
|
||||||
&:checked + label > div::after
|
|
||||||
background-color: white
|
|
||||||
|
|
||||||
.main
|
|
||||||
height: 100%
|
|
||||||
max-width: 100%
|
|
||||||
display: flex
|
|
||||||
flex-direction: column
|
|
||||||
justify-content: space-around
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
.center
|
|
||||||
width: 100%
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
.btns
|
|
||||||
width: 400px
|
|
||||||
max-width: 100%
|
|
||||||
min-width: 280px
|
|
||||||
position: relative
|
|
||||||
margin: 0 auto
|
|
||||||
|
|
||||||
.next
|
|
||||||
background: var(--color-highlight-background)
|
|
||||||
bottom: 1rem
|
|
||||||
right: 1rem
|
|
||||||
width: 3rem
|
|
||||||
height: 3rem
|
|
||||||
opacity: .8
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
opacity: 1
|
|
||||||
|
|
||||||
svg
|
|
||||||
width: 80%
|
|
||||||
height: 80%
|
|
||||||
transform: rotate(90deg)
|
|
||||||
fill: var(--color-highlight-text)
|
|
||||||
</style>
|
|
|
@ -298,9 +298,9 @@ legend
|
||||||
height: calc(1rem - 6px)
|
height: calc(1rem - 6px)
|
||||||
&:checked + label > div
|
&:checked + label > div
|
||||||
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
|
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
|
||||||
&:checked + label > div::before
|
&:not(:checked) + label > div::before
|
||||||
background-color: var(--color-green)
|
background-color: var(--color-green)
|
||||||
&:checked + label > div::after
|
&:not(:checked) + label > div::after
|
||||||
background-color: white
|
background-color: white
|
||||||
|
|
||||||
.main
|
.main
|
||||||
|
|
|
@ -1,18 +1,15 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import data from "@/data.json";
|
import data from "@/data.json";
|
||||||
import certitudes from "@/certitudes.json";
|
|
||||||
import certitudesResults from "@/certitudesResults.json";
|
|
||||||
|
|
||||||
import { ref, computed, watch } from "vue";
|
import { ref, computed } from "vue";
|
||||||
|
|
||||||
import { useStore } from "@/stores";
|
import { useStore } from "@/stores";
|
||||||
|
|
||||||
import { Splide, SplideSlide } from "@splidejs/vue-splide";
|
import { Splide, SplideSlide } from "@splidejs/vue-splide";
|
||||||
import Question from "./Question.vue";
|
import Question from "./Question.vue";
|
||||||
import Certitude from "./Certitude.vue";
|
|
||||||
import "@splidejs/splide/dist/css/splide.min.css";
|
import "@splidejs/splide/dist/css/splide.min.css";
|
||||||
import ScoreHeader from "./ScoreHeader.vue";
|
import ScoreHeader from "./ScoreHeader.vue";
|
||||||
// import { toPng } from "html-to-image";
|
import { toPng } from "html-to-image";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -118,82 +115,53 @@ function answerSelected(question, answerWeight) {
|
||||||
function nextQuestion() {
|
function nextQuestion() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
slides.value.go(">");
|
slides.value.go(">");
|
||||||
// console.log(slides);
|
console.log(slides);
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const saveAs = (blob, fileName) => {
|
const saveAs = (blob, fileName) => {
|
||||||
// var elem = window.document.createElement("a");
|
var elem = window.document.createElement("a");
|
||||||
// elem.href = blob;
|
elem.href = blob;
|
||||||
// elem.download = fileName;
|
elem.download = fileName;
|
||||||
// elem.style = "display:none;";
|
elem.style = "display:none;";
|
||||||
// (document.body || document.documentElement).appendChild(elem);
|
(document.body || document.documentElement).appendChild(elem);
|
||||||
// if (typeof elem.click === "function") {
|
if (typeof elem.click === "function") {
|
||||||
// elem.click();
|
elem.click();
|
||||||
// } else {
|
} else {
|
||||||
// elem.target = "_blank";
|
elem.target = "_blank";
|
||||||
// elem.dispatchEvent(
|
elem.dispatchEvent(
|
||||||
// new MouseEvent("click", {
|
new MouseEvent("click", {
|
||||||
// view: window,
|
view: window,
|
||||||
// bubbles: true,
|
bubbles: true,
|
||||||
// cancelable: true,
|
cancelable: true,
|
||||||
// }),
|
}),
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// URL.revokeObjectURL(elem.href);
|
|
||||||
// elem.remove();
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const sharing = ref(false);
|
|
||||||
// async function share() {
|
|
||||||
// sharing.value = true;
|
|
||||||
// const filter = (node) => {
|
|
||||||
// const exclusionClasses = ["btn"];
|
|
||||||
// return !exclusionClasses.some((classname) =>
|
|
||||||
// node.classList?.contains(classname),
|
|
||||||
// );
|
|
||||||
// };
|
|
||||||
// const body = document.querySelector("body");
|
|
||||||
// body.classList.add("print");
|
|
||||||
// const dataUrl = await toPng(body, { filter: filter });
|
|
||||||
// body.classList.remove("print");
|
|
||||||
// const fileName = new Date()
|
|
||||||
// .toISOString()
|
|
||||||
// .replace(/T/, "_")
|
|
||||||
// .replace(/\..+/, "")
|
|
||||||
// .replaceAll(":", "-");
|
|
||||||
// saveAs(dataUrl, `Ceiba-score-${fileName}.png`);
|
|
||||||
// sharing.value = false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
const displayCertitude = ref(false);
|
|
||||||
const weightCertitudes = ref(new Array(certitudes.length).fill(0));
|
|
||||||
const weightAllCertitudes = ref(0);
|
|
||||||
const certitudeResult = ref(selectCertitudeResult());
|
|
||||||
function selectCertitudeResult() {
|
|
||||||
return certitudesResults
|
|
||||||
.find(
|
|
||||||
(result) =>
|
|
||||||
result.weight_min <= weightAllCertitudes.value &&
|
|
||||||
result.weight_max >= weightAllCertitudes.value,
|
|
||||||
)
|
|
||||||
?.translations.find(
|
|
||||||
(translation) => translation.languages_code == language,
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
URL.revokeObjectURL(elem.href);
|
||||||
|
elem.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
const sharing = ref(false);
|
||||||
|
async function share() {
|
||||||
|
sharing.value = true;
|
||||||
|
const filter = (node) => {
|
||||||
|
const exclusionClasses = ["btn"];
|
||||||
|
return !exclusionClasses.some((classname) =>
|
||||||
|
node.classList?.contains(classname),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
const body = document.querySelector("body");
|
||||||
|
body.classList.add("print");
|
||||||
|
const dataUrl = await toPng(body, { filter: filter });
|
||||||
|
body.classList.remove("print");
|
||||||
|
const fileName = new Date()
|
||||||
|
.toISOString()
|
||||||
|
.replace(/T/, "_")
|
||||||
|
.replace(/\..+/, "")
|
||||||
|
.replaceAll(":", "-");
|
||||||
|
saveAs(dataUrl, `Ceiba-score-${fileName}.png`);
|
||||||
|
sharing.value = false;
|
||||||
}
|
}
|
||||||
function displayCertitudeQuestions() {
|
|
||||||
displayCertitude.value = !displayCertitude.value;
|
|
||||||
}
|
|
||||||
function answerSelectedCertitude(question, answerWeight) {
|
|
||||||
weightCertitudes.value[question.sort - 1] = answerWeight;
|
|
||||||
weightAllCertitudes.value = weightCertitudes.value.reduce(
|
|
||||||
(accumulator, curr) => accumulator + curr,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
watch(weightAllCertitudes, () => {
|
|
||||||
certitudeResult.value = selectCertitudeResult();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -219,15 +187,6 @@ watch(weightAllCertitudes, () => {
|
||||||
@nextQuestion="nextQuestion"
|
@nextQuestion="nextQuestion"
|
||||||
/>
|
/>
|
||||||
</SplideSlide>
|
</SplideSlide>
|
||||||
<template v-if="displayCertitude">
|
|
||||||
<SplideSlide v-for="certitude in certitudes" :key="certitude.id">
|
|
||||||
<Certitude
|
|
||||||
:certitude="certitude"
|
|
||||||
@answerSelected="answerSelectedCertitude"
|
|
||||||
@nextQuestion="nextQuestion"
|
|
||||||
/>
|
|
||||||
</SplideSlide>
|
|
||||||
</template>
|
|
||||||
<SplideSlide class="latest">
|
<SplideSlide class="latest">
|
||||||
<template v-if="displayScoreResult && result">
|
<template v-if="displayScoreResult && result">
|
||||||
<div>
|
<div>
|
||||||
|
@ -257,20 +216,6 @@ watch(weightAllCertitudes, () => {
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="displayCertitude" class="certitude_result">
|
|
||||||
<button @click="displayCertitudeQuestions">
|
|
||||||
<span
|
|
||||||
>Niveau de certitude : {{ certitudeResult?.niveau }}<br />
|
|
||||||
<span v-html="certitudeResult?.description"></span>
|
|
||||||
</span>
|
|
||||||
<span class="cross">✖️</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div v-else class="certitude_result">
|
|
||||||
<button @click="displayCertitudeQuestions">
|
|
||||||
➕ Ajout un niveau de certitude
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!--button class="btn download" @click="() => share()" v-if="!sharing">
|
<!--button class="btn download" @click="() => share()" v-if="!sharing">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
|
||||||
<path
|
<path
|
||||||
|
@ -291,9 +236,9 @@ watch(weightAllCertitudes, () => {
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</button-->
|
</button-->
|
||||||
<!-- <button class="btn spin" v-if="sharing">
|
<button class="btn spin" v-if="sharing">
|
||||||
<img src="/spin.svg" />
|
<img src="/spin.svg" />
|
||||||
</button> -->
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
@ -326,17 +271,6 @@ watch(weightAllCertitudes, () => {
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="sass" scoped>
|
<style lang="sass" scoped>
|
||||||
.certitude_result
|
|
||||||
text-align: center
|
|
||||||
button
|
|
||||||
display: flex
|
|
||||||
justify-content: center
|
|
||||||
flex-direction: row
|
|
||||||
align-items: center
|
|
||||||
margin: 1rem auto 0
|
|
||||||
padding: .3rem
|
|
||||||
.cross
|
|
||||||
margin-left: .5rem
|
|
||||||
.spin
|
.spin
|
||||||
bottom: 1.5rem
|
bottom: 1.5rem
|
||||||
right: 1.5rem
|
right: 1.5rem
|
||||||
|
|
|
@ -23,7 +23,9 @@ export default defineConfig({
|
||||||
},
|
},
|
||||||
// add this to cache all the
|
// add this to cache all the
|
||||||
// static assets in the public folder
|
// static assets in the public folder
|
||||||
includeAssets: ["**/*"],
|
includeAssets: [
|
||||||
|
"**/*",
|
||||||
|
],
|
||||||
useCredentials: true,
|
useCredentials: true,
|
||||||
manifest: {
|
manifest: {
|
||||||
theme_color: "#eb5252",
|
theme_color: "#eb5252",
|
||||||
|
@ -32,16 +34,16 @@ export default defineConfig({
|
||||||
scope: "/",
|
scope: "/",
|
||||||
icons: [
|
icons: [
|
||||||
{
|
{
|
||||||
src: "/images/pwa-icon-256.png",
|
"src": "/images/pwa-icon-256.png",
|
||||||
sizes: "192x192",
|
"sizes": "192x192",
|
||||||
type: "image/png",
|
"type": "image/png",
|
||||||
purpose: "any maskable",
|
"purpose": "any maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
src: "/images/pwa-icon-512.png",
|
"src": "/images/pwa-icon-512.png",
|
||||||
sizes: "512x512",
|
"sizes": "512x512",
|
||||||
type: "image/png",
|
"type": "image/png",
|
||||||
purpose: "any maskable",
|
"purpose": "any maskable"
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue