Compare commits

..

1 Commits

Author SHA1 Message Date
4d3eacffb1 feat: Changement de librairie
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-03 16:10:44 +02:00
18 changed files with 4059 additions and 6712 deletions

View File

@ -34,42 +34,6 @@ kind: secret
name: PRODUCTION_AWS_SECRET_ACCESS_KEY name: PRODUCTION_AWS_SECRET_ACCESS_KEY
data: JX44CwSuvFmYhJCW+vxC4GmUKbO83VyYeImCvIgtkdeC1cRtNEgCA6gWoclT4vSBrk6AW6iQnh3MSpIhOERSn/prcWiTwbBn6YqdUaQ18B9/Dp3Qk1RtOkS2wKI= data: JX44CwSuvFmYhJCW+vxC4GmUKbO83VyYeImCvIgtkdeC1cRtNEgCA6gWoclT4vSBrk6AW6iQnh3MSpIhOERSn/prcWiTwbBn6YqdUaQ18B9/Dp3Qk1RtOkS2wKI=
---
# drone encrypt Weko/ceiba-scores $AWS_ACCESS_KEY_ID
kind: secret
name: TEST_AWS_ACCESS_KEY_ID
data: Bf6VZlmdGQGAOQtwtiOzRCqhnFaW310rw9LqMFVoaQBHiCbso23Zrt6G1N3J0nYGI/oLMhM3
---
# drone encrypt Weko/ceiba-scores $AWS_SECRET_ACCESS_KEY
kind: secret
name: TEST_AWS_SECRET_ACCESS_KEY
data: kIq0RuZPg2gSamnbei121OHNtupioEYyVay8CnNxNz+u0fEh0c1qnAKM506h+XbwMr+HDyQEUNDM09fqzM14xmRxz8EZtqg6hXVPUcfEIG9nXI9VtnCKMwoKTMQ=
---
# drone encrypt Weko/ceiba-scores $AWS_ACCESS_KEY_ID
kind: secret
name: DMH_AWS_ACCESS_KEY_ID
data: ZJi1IozPCoLgmwBnQy9OkOe7ByerC/b94aTNivtkAYh1K9A4WR+eXGNrbyXZci06HYjV8pBU
---
# drone encrypt Weko/ceiba-scores $AWS_SECRET_ACCESS_KEY
kind: secret
name: DMH_AWS_SECRET_ACCESS_KEY
data: sLiY4plTjS73Dzw0qHaAuSR4PiHGIhb6H2i1KyP2GpjvIDyaxbR2gjsjzn3E8e0gAtCiIM10nbvvAMvGmPoh1dLuYlmHj2YdOQA8wbjkA9jSqe9owbfxfrcEuDA=
---
# drone encrypt Weko/ceiba-scores $AWS_ACCESS_KEY_ID
kind: secret
name: FOURCHE_AWS_ACCESS_KEY_ID
data: GgpM5vSzE4N4ldcs+Db+sjG/siXmO+sYvw9DJYr0puAIv3jejlzwa3zJGcwGb2fmwCqyxied
---
# drone encrypt Weko/ceiba-scores $AWS_SECRET_ACCESS_KEY
kind: secret
name: FOURCHE_AWS_SECRET_ACCESS_KEY
data: rEE5ttbao6dla92YOw1vh1VE1sBWAjen+jfP/ZdUSDnFlkZKY56ms+V0jOReGulhwbVRxQijp1fTS43TW/vJbq3XSeTVUwDGTHLZFQ+yGObvr+4DKOVIRqp/rJE=
--- ---
kind: pipeline kind: pipeline
type: docker type: docker
@ -77,14 +41,14 @@ name: prod
steps: steps:
- name: install npm - name: install npm
image: node:20.12.2-alpine image: node:current-alpine
volumes: volumes:
- name: node_modules - name: node_modules
path: /drone/src/node_modules path: /drone/src/node_modules
commands: commands:
- npm i --include dev - npm i
- npm run fetchData - npm run fetchData
#- npm run lint - npm run lint
- npm run build - npm run build
environment: environment:
NODE_ENV: 'production' NODE_ENV: 'production'
@ -123,14 +87,14 @@ name: staging
steps: steps:
- name: install npm - name: install npm
image: node:20.12.2-alpine image: node:current-alpine
volumes: volumes:
- name: node_modules - name: node_modules
path: /drone/src/node_modules path: /drone/src/node_modules
commands: commands:
- npm i - npm i
- npm run fetchData - npm run fetchData
#- npm run lint - npm run lint
- npm run build - npm run build
environment: environment:
NODE_ENV: 'staging' NODE_ENV: 'staging'
@ -160,142 +124,4 @@ steps:
volumes: volumes:
- name: node_modules - name: node_modules
host: host:
path: /tmp/drone/cache/weko/staging.scores.ceiba-conseil.com/node_modules path: /tmp/drone/cache/weko/scores.ceiba-conseil.com/node_modules
---
kind: pipeline
type: docker
name: test
steps:
- name: install npm
image: node:20.12.2-alpine
volumes:
- name: node_modules
path: /drone/src/node_modules
commands:
- npm i
- npm run fetchData
#- npm run lint
- npm run build
environment:
NODE_ENV: 'test'
- name: deploy on s3
image: minio/mc
environment:
AWS_ACCESS_KEY_ID:
from_secret: TEST_AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: TEST_AWS_SECRET_ACCESS_KEY
commands:
- mc alias set garage https://s3.garage.resilien.cloud $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY --api S3v4
- mc mirror --overwrite /drone/src/dist garage/test.scores.ceiba-conseil.com
- name: notify
image: plugins/matrix@sha256:f1affb31b0c86963c97c6f976fa0dcb3cc84272057fd8558d609d28b3064bd7f
settings:
homeserver: https://converser.eu
roomid: "QwOITmkKxRJJyCSDOZ:converser.eu"
userid: "resilien:converser.eu"
accesstoken:
from_secret: MATRIX_ACCESSTOKEN
when:
status: [ failure ]
volumes:
- name: node_modules
host:
path: /tmp/drone/cache/weko/test.scores.ceiba-conseil.com/node_modules
---
kind: pipeline
type: docker
name: DMH
steps:
- name: install npm
image: node:20.12.2-alpine
volumes:
- name: node_modules
path: /drone/src/node_modules
commands:
- npm i
- npm run fetchData
#- npm run lint
- apk add --no-cache jq
- echo $(cat src/data.json | jq -c '[.[4]]') > src/data.json
- npm run build
- name: deploy on s3
image: minio/mc
environment:
AWS_ACCESS_KEY_ID:
from_secret: DMH_AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: DMH_AWS_SECRET_ACCESS_KEY
commands:
- mc alias set garage https://s3.garage.resilien.cloud $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY --api S3v4
- mc mirror --overwrite /drone/src/dist garage/dmh.ceiba-conseil.com
- name: notify
image: plugins/matrix@sha256:f1affb31b0c86963c97c6f976fa0dcb3cc84272057fd8558d609d28b3064bd7f
settings:
homeserver: https://converser.eu
roomid: "QwOITmkKxRJJyCSDOZ:converser.eu"
userid: "resilien:converser.eu"
accesstoken:
from_secret: MATRIX_ACCESSTOKEN
when:
status: [ failure ]
volumes:
- name: node_modules
host:
path: /tmp/drone/cache/weko/dmh.ceiba-conseil.com/node_modules
---
kind: pipeline
type: docker
name: FOURCHE
steps:
- name: install npm
image: node:20.12.2-alpine
volumes:
- name: node_modules
path: /drone/src/node_modules
commands:
- npm i
- npm run fetchData
#- npm run lint
- apk add --no-cache jq
- echo $(jq '[.[] | select(.id == 7 or .id == 11)]' src/data.json) > src/data.json
- npm run build
- name: deploy on s3
image: minio/mc
environment:
AWS_ACCESS_KEY_ID:
from_secret: FOURCHE_AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY:
from_secret: FOURCHE_AWS_SECRET_ACCESS_KEY
commands:
- mc alias set garage https://s3.garage.resilien.cloud $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY --api S3v4
- mc mirror --overwrite /drone/src/dist garage/fourche.ceiba-conseil.com
- name: notify
image: plugins/matrix@sha256:f1affb31b0c86963c97c6f976fa0dcb3cc84272057fd8558d609d28b3064bd7f
settings:
homeserver: https://converser.eu
roomid: "QwOITmkKxRJJyCSDOZ:converser.eu"
userid: "resilien:converser.eu"
accesstoken:
from_secret: MATRIX_ACCESSTOKEN
when:
status: [ failure ]
volumes:
- name: node_modules
host:
path: /tmp/drone/cache/weko/fourche.ceiba-conseil.com/node_modules

View File

@ -10,6 +10,5 @@ module.exports = {
], ],
env: { env: {
"vue/setup-compiler-macros": true, "vue/setup-compiler-macros": true,
node: true,
}, },
}; };

2
.gitignore vendored
View File

@ -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

View File

@ -31,12 +31,10 @@ Une configuration spécifique à _Vite_ peut être mise en place, voir [la réf
## Logiciels utilisés ## Logiciels utilisés
_RésiLien_ met en place des outils open source eprouvés dans le temps et dont les communautés sont assez grandes pour permettre une perenité de ses projets. _RésiLien_ met en place des outils open source eprouvé dans le temps et dont les communautés sont assez grandes pour permettre une perenité de ses projets.
Voici les différentes briques utilisé autour du projet : Voici les différentes briques utilisé autour du projet :
- _[Garage](https://garagehq.deuxfleurs.fr/)_ pour l'hébergement développé par l'association [Deuxfleurs](https://deuxfleurs.fr/) - _[Garage](https://garagehq.deuxfleurs.fr/)_ pour l'hébergement développé par l'association [Deuxfleurs](https://deuxfleurs.fr/)
- _[Directus](https://directus.io/)_ pour l'administration - _[Directus](https://directus.io/)_ pour l'administration
- _[Drone](https://drone.io)_ pour la compilation automatique du projet - _[Drone](https://drone.io)_ pour la compilation automatique du projet
- _[Matrix](https://fr.wikipedia.org/wiki/Matrix_(protocole))_ est un protocole ouvert pour de la communication en temps réel - _[Matrix](https://fr.wikipedia.org/wiki/Matrix_(protocole))_ est un protocole ouvert pour de la communication en temps réel
Icon : https://www.svgrepo.com/collection/solar-linear-icons/

View File

@ -15,16 +15,11 @@
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png"> <link rel="icon" type="image/png" sizes="96x96" href="/favicon/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png">
<link rel="manifest" href="/favicon/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff"> <meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png"> <meta name="msapplication-TileImage" content="/favicon/ms-icon-144x144.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Scores Ceiba</title> <title>Scores Ceiba</title>
<meta name="description" content="L'application Scores de Ceiba">
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
<meta name="theme-color" content="#ffffff">
<link rel="icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

9547
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,24 +10,24 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore" "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
}, },
"dependencies": { "dependencies": {
"@splidejs/vue-splide": "^0.6.12", "@splidejs/vue-splide": "^0.5.18",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"pinia": "^2.1.7", "html2canvas": "^1.4.1",
"pinia": "^2.0.11",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persist": "^1.0.0",
"sass": "^1.75.0", "sass": "^1.49.9",
"sass-loader": "^14.2.1", "sass-loader": "^12.6.0",
"sharp": "^0.33.3", "sharp": "^0.30.3",
"vite-plugin-pwa": "^0.19.8", "vue": "^3.2.31",
"vue": "^3.4.26", "vue-router": "^4.0.12"
"vue-router": "^4.3.2"
}, },
"devDependencies": { "devDependencies": {
"@rushstack/eslint-patch": "^1.10.2", "@rushstack/eslint-patch": "^1.1.0",
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^2.2.2",
"@vue/eslint-config-prettier": "^9.0.0", "@vue/eslint-config-prettier": "^7.0.0",
"eslint": "^8.5.0", "eslint": "^8.5.0",
"eslint-plugin-vue": "^8.2.0", "eslint-plugin-vue": "^8.2.0",
"prettier": "^3.2.5", "prettier": "^2.5.1",
"vite": "^5.2.10" "vite": "^2.8.4"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

View File

@ -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 = [
"*", "*",
@ -73,14 +47,7 @@ async function fetchScoresData() {
const url = `/items/scores?${fields const url = `/items/scores?${fields
.map((item) => `fields[]=${item}`) .map((item) => `fields[]=${item}`)
.join("&")}`; .join("&")}`;
let scores = (await fetchJSONApi(url)).data; const scores = (await fetchJSONApi(url)).data;
if (process.env.NODE_ENV == "production") {
console.log("Suppresion des scores avec le mode brouillon en production");
scores = scores.filter((score) => !score.draft);
} else if (process.env.NODE_ENV == "test") {
console.log("Suppresion des scores sans l'environnement test");
scores = scores.filter((score) => score.env_test);
}
await fs.writeFile("./src/data.json", JSON.stringify(scores), "utf8"); await fs.writeFile("./src/data.json", JSON.stringify(scores), "utf8");
const folder = "public/answers"; const folder = "public/answers";
@ -95,7 +62,7 @@ async function fetchScoresData() {
await streamPipeline( await streamPipeline(
response.body, response.body,
thumbnail, thumbnail,
createWriteStream(`${folder}/${uuid_score}.webp`), createWriteStream(`${folder}/${uuid_score}.webp`)
); );
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@ -338,8 +305,6 @@ async function fetchHomepageData() {
async function fetchData() { async function fetchData() {
await fetchHomepageData(); await fetchHomepageData();
await fetchCertitudesData();
await fetchCertitudesResultsData();
await fetchScoresData(); await fetchScoresData();
} }

View File

@ -6,16 +6,9 @@
--color-black: #000000; --color-black: #000000;
--color-green: rgb(118, 148, 67); --color-green: rgb(118, 148, 67);
--header-size-small: 48px; --header-size-small: 64px;
--header-size-big: 128px; --header-size-big: 128px;
--header-size: var(--header-size-small); --header-size: var(--header-size-small);
--footer-size: 48px;
--color-red: #c82606;
--color-orange: #df6a0f;
--color-light-green: #70bf41;
--color-dark-green: #00882b;
} }
/* semantic color variables for this project */ /* semantic color variables for this project */
@ -51,7 +44,7 @@ body.theme-dark {
} }
} }
@media (min-height: 1000px) { @media (min-height: 800px) {
:root { :root {
--header-size: var(--header-size-big); --header-size: var(--header-size-big);
} }
@ -113,27 +106,4 @@ body.print {
border: none; border: none;
box-shadow: 0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12); box-shadow: 0 3px 5px -1px rgba(0,0,0,.2),0 6px 10px 0 rgba(0,0,0,.14),0 1px 18px 0 rgba(0,0,0,.12);
cursor: pointer; cursor: pointer;
background: white;
} }
.btn svg {
width: 100%;
height: 100%;
}
header svg.color-text [stroke] {
stroke: var(--color-header-text);
}
header svg.color-text [fill]:not([fill=none]) {
fill: var(--color-header-text)
}
strong {
font-weight: bold;
}
.bg-red { background: var(--color-red); }
.bg-orange { background: var(--color-orange); }
.bg-light-green { background: var(--color-light-green); }
.bg-dark-green { background: var(--color-dark-green); }

View File

@ -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
&:not(:checked) + label > div::before
background-color: var(--color-green)
&:not(: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>

View File

@ -17,7 +17,7 @@ const answerWeight = ref(props.question.weight);
function selectAnswer(answer) { function selectAnswer(answer) {
const answerIndex = props.question.answers.findIndex( const answerIndex = props.question.answers.findIndex(
(a) => a.id === answer.id, (a) => a.id === answer.id
); );
slides.value.splide.go(answerIndex); slides.value.splide.go(answerIndex);
} }
@ -47,17 +47,13 @@ function validatePopup() {
return true; return true;
} }
}); });
const answer = document.querySelector( document.querySelector(
"input[id=" + "input[id=" + `question_${props.question.id}_answer_${answerIndex.id}` + "]"
`question_${props.question.id}_answer_${answerIndex.id}` + ).checked = true;
"]",
);
answer.checked = true;
answer.dispatchEvent(new Event("change"));
showHidePopup(); showHidePopup();
} }
const h = ref(); const h = ref(1);
const d = ref(); const d = ref(1);
</script> </script>
<template> <template>
@ -98,9 +94,7 @@ const d = ref();
@click="nextQuestion" @click="nextQuestion"
/> />
<label :for="`question_${question.id}_answer_${answer.id}`"> <label :for="`question_${question.id}_answer_${answer.id}`">
<div>
{{ answer.title }} {{ answer.title }}
</div>
</label> </label>
</li> </li>
</ul> </ul>
@ -140,8 +134,7 @@ const d = ref();
<input v-model="h" type="number" name="H" /> <input v-model="h" type="number" name="H" />
<label for="D">D (cm)</label> <label for="D">D (cm)</label>
<input v-model="d" type="number" name="D" /> <input v-model="d" type="number" name="D" />
<p v-if="d && d != 0"> {{ Math.round((h * 100) / d) }}</p> <p>({{ h }} * 100) / {{ d }} {{ Math.round((h * 100) / d) }}</p>
<p v-if="!d || d == 0" class="no-visible"></p>
<button class="btn equal" @click="validatePopup"> <button class="btn equal" @click="validatePopup">
<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
@ -181,10 +174,6 @@ const d = ref();
padding: 1rem padding: 1rem
margin: 1rem margin: 1rem
border: 1px solid var(--color-highlight-text) border: 1px solid var(--color-highlight-text)
font-size: 2rem
&.no-visible
border: 1px solid transparent
svg path svg path
fill: var(--color-highlight-background) fill: var(--color-highlight-background)
@ -206,8 +195,8 @@ const d = ref();
background: var(--color-highlight-background) background: var(--color-highlight-background)
bottom: 1rem bottom: 1rem
left: 1rem left: 1rem
width: 4rem width: 3rem
height: 4rem height: 3rem
img img
width: 80% width: 80%
@ -260,7 +249,6 @@ legend
font-size: 1.4rem font-size: 1.4rem
line-height: 2rem line-height: 2rem
font-weight: bold font-weight: bold
width: 100%
.choices .choices
list-style-type: none list-style-type: none
@ -270,37 +258,36 @@ legend
label label
cursor: pointer cursor: pointer
display: block
input[type=radio] input[type=radio]
display: none display: none
& + label > div & + label
position: relative position: relative
padding: .2rem .2rem .2rem 2rem padding: .2rem .2rem .2rem 2rem
& + label > div::before, & + label::before,
& + label > div::after & + label::after
display: block display: block
position: absolute position: absolute
box-sizing: border-box box-sizing: border-box
content:'' content:''
border-radius: 1rem border-radius: 1rem
& + label > div::before & + label::before
top: .5rem bottom: .3rem
left: 0 left: 0
background-color: var(--color-green) background-color: var(--color-green)
width: 1rem width: 1rem
height: 1rem height: 1rem
& + label > div::after & + label::after
top: calc(3px + .5rem) bottom: calc(3px + .3rem)
left: 3px left: 3px
width: calc(1rem - 6px) width: calc(1rem - 6px)
height: calc(1rem - 6px) height: calc(1rem - 6px)
&:checked + label > div &:checked + label
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
&:not(:checked) + label > div::before &:checked + label::before
background-color: var(--color-green) background-color: var(--color-green)
&:not(:checked) + label > div::after &:checked + label::after
background-color: white background-color: white
.main .main

View File

@ -1,18 +1,16 @@
<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 html2canvas from "html2canvas";
import { toPng } from 'html-to-image';
const props = defineProps({ const props = defineProps({
id: { id: {
@ -32,7 +30,7 @@ function formatAnswers(answers) {
.map((answer) => answer.answers_id) .map((answer) => answer.answers_id)
.map((answer) => { .map((answer) => {
const translation = answer.translations.filter( const translation = answer.translations.filter(
(item) => item.languages_code == language, (item) => item.languages_code == language
); );
return { return {
id: answer.id, id: answer.id,
@ -48,7 +46,7 @@ function formatScore(score) {
.map((question) => question.questions_id) .map((question) => question.questions_id)
.map((question) => { .map((question) => {
const translation = question.translations.filter( const translation = question.translations.filter(
(item) => item.languages_code == language, (item) => item.languages_code == language
); );
const answers = formatAnswers(question.answers); const answers = formatAnswers(question.answers);
return { return {
@ -61,12 +59,8 @@ function formatScore(score) {
}; };
}); });
} }
function getTranslation(translations, key) {
return translations.find((translation) => translation[key] == store.language); const title = score ? score.title : "";
}
const trad = getTranslation(score.translations, "languages_id");
const title = score ? trad.title : "";
const link = score ? trad.link : "";
const questions = ref(formatScore(score)); const questions = ref(formatScore(score));
const scoreSum = computed(() => { const scoreSum = computed(() => {
@ -75,14 +69,14 @@ const scoreSum = computed(() => {
.reduce((value, currentValue) => value + currentValue, 0); .reduce((value, currentValue) => value + currentValue, 0);
}); });
const displayScoreResult = computed( const displayScoreResult = computed(
() => !questions.value.filter((q) => q.weight == null).length, () => !questions.value.filter((q) => q.weight == null).length
); );
function getResultsFromScore(score) { function getResultsFromScore(score) {
return score.results return score.results
.map((result) => result.results_id) .map((result) => result.results_id)
.map((result) => { .map((result) => {
const translation = result.translations.filter( const translation = result.translations.filter(
(item) => item.languages_code == language, (item) => item.languages_code == language
); );
return { return {
id: result.id, id: result.id,
@ -92,10 +86,8 @@ function getResultsFromScore(score) {
effets: translation.length > 0 ? translation[0].effets : "", effets: translation.length > 0 ? translation[0].effets : "",
facteur: translation.length > 0 ? translation[0].facteur : "", facteur: translation.length > 0 ? translation[0].facteur : "",
pde: translation.length > 0 ? translation[0].pde : "", pde: translation.length > 0 ? translation[0].pde : "",
title: translation.length > 0 ? translation[0].title : "",
}; };
}) });
.reverse();
} }
const results = ref(getResultsFromScore(score)); const results = ref(getResultsFromScore(score));
const result = computed(() => const result = computed(() =>
@ -103,12 +95,12 @@ const result = computed(() =>
? results.value ? results.value
.filter((r) => !r.min || r.min <= scoreSum.value) .filter((r) => !r.min || r.min <= scoreSum.value)
.filter((r) => !r.max || r.max >= scoreSum.value)[0] .filter((r) => !r.max || r.max >= scoreSum.value)[0]
: null, : null
); );
function goQuestionSlide(question) { function goQuestionSlide(question) {
console.log(slides.value); console.log(slides.value);
slides.value.go( slides.value.go(
questions.value.findIndex((element) => element.id === question.id), questions.value.findIndex((element) => element.id === question.id)
); );
} }
function answerSelected(question, answerWeight) { function answerSelected(question, answerWeight) {
@ -118,86 +110,50 @@ 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()
// URL.revokeObjectURL(elem.href); }
// elem.remove();
// };
// const sharing = ref(false); const sharing = ref(false);
// async function share() { async function share() {
// sharing.value = true; sharing.value = true
// const filter = (node) => { // const canvas = await html2canvas(document.querySelector("html"));
// const exclusionClasses = ["btn"]; // let anchor = document.createElement("a");
// return !exclusionClasses.some((classname) => // anchor.download = "download.png";
// node.classList?.contains(classname), // anchor.href = canvas.toDataURL("image/png");
// ); // anchor.click();
// }; // anchor.remove();
// const body = document.querySelector("body"); const body = document.querySelector("body")
// body.classList.add("print"); body.classList.add("print")
// const dataUrl = await toPng(body, { filter: filter }); const dataUrl = await toPng(body)
// body.classList.remove("print"); body.classList.remove("print")
// const fileName = new Date() saveAs(dataUrl, 'my-node.png')
// .toISOString() sharing.value = false
// .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() {
const certitude = certitudesResults.find(
(result) =>
result.weight_min <= weightAllCertitudes.value &&
result.weight_max >= weightAllCertitudes.value,
);
const certitudeTrad = certitude?.translations.find(
(translation) => translation.languages_code == language,
);
return { ...certitudeTrad, color: certitude.color };
} }
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>
<ScoreHeader v-if="title" :title="title" :link="link" /> <ScoreHeader v-if="title" :title="title" />
<Splide <Splide
ref="slides" ref="slides"
class="questions" class="questions"
@ -219,54 +175,38 @@ 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>
<h2 class="center">{{ trad.result_title }}</h2> <h2 class="center">Probabilité d'échec</h2>
<h2 class="center">{{ result.title }}</h2> <h2 class="center">{{ result.pde_qtra }}</h2>
<div :class="'gradient size-' + results.length"> <div class="gradient">
<div <div
v-for="item in results" v-for="(item, index) in [...Array(7).keys()]"
:class="{ active: result && result.pde_qtra === item.pde_qtra }" :class="{ active: result && result.pde_qtra === index + 1 }"
:key="item" :key="item"
:data-title="trad.result_sigle"
> >
{{ item.title }} {{ index + 1 }}
</div> </div>
</div> </div>
<div class="details"> <div class="details">
<p>{{ trad.result_params }} :</p> <p>Rappel des paramètres choisis :</p>
<br />
<ul> <ul>
<li v-for="question in questions" :key="question.id"> <li v-for="question in questions" :key="question.id">
{{ question.title }} : {{ question.title }} :
{{ {{
question.answers.find( question.answers.find(
(answer) => answer.weight === question.weight, (answer) => answer.weight === question.weight
).title ).title
}} }}
</li> </li>
</ul> </ul>
</div> </div>
<div class="certitude_result">
Niveau de certitude
<button <button
@click="displayCertitudeQuestions" class="btn download no-print"
:class="'bg-' + certitudeResult.color" @click="() => share()"
v-if="!sharing"
> >
<span>{{ certitudeResult?.niveau }} </span>
</button>
</div>
<!--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
fill="#D99E82" fill="#D99E82"
@ -285,10 +225,10 @@ watch(weightAllCertitudes, () => {
d="M26.716 8h-4.783V2c0-1.105-.896-2-2-2h-4.001c-1.104 0-1.999.896-1.999 2v6H9.148c-1.223 0-1.516.623-.651 1.489l7.863 7.863c.865.865 2.28.865 3.146 0l7.863-7.863C28.232 8.623 27.94 8 26.716 8z" d="M26.716 8h-4.783V2c0-1.105-.896-2-2-2h-4.001c-1.104 0-1.999.896-1.999 2v6H9.148c-1.223 0-1.516.623-.651 1.489l7.863 7.863c.865.865 2.28.865 3.146 0l7.863-7.863C28.232 8.623 27.94 8 26.716 8z"
/> />
</svg> </svg>
</button--> </button>
<!-- <button class="btn spin" v-if="sharing"> <button class="btn spin no-print" v-if="sharing">
<img src="/spin.svg" /> <img src="/spin.svg">
</button> --> </button>
</div> </div>
</template> </template>
<template v-else> <template v-else>
@ -321,27 +261,6 @@ watch(weightAllCertitudes, () => {
</template> </template>
<style lang="sass" scoped> <style lang="sass" scoped>
.certitude_result
padding-top: 1rem
font-size: 1.1rem
text-align: center
color: var(--color-highlight-text)
& *
font-weight: 800
button
display: flex
width: 100%
color: var(--color-highlight-text)
justify-content: center
flex-direction: row
align-items: center
margin: .2rem auto 0
border-radius: 0
border: none
font-weight: 900 !important
font-size: 1.1rem
padding: .3rem
.spin .spin
bottom: 1.5rem bottom: 1.5rem
right: 1.5rem right: 1.5rem
@ -423,11 +342,10 @@ label
justify-content: center justify-content: center
h2 h2
font-size: 1.5rem font-size: 2rem
font-weight: bold font-weight: bold
line-height: 2.4rem
& + h2 & + h2
line-height: 3rem line-height: 2rem
font-size: 2.6rem font-size: 2.6rem
@media (max-height: 600px) @media (max-height: 600px)
@ -442,40 +360,27 @@ label
.details .details
text-align: left !important text-align: left !important
font-size: 1.1rem font-family: serif
font-size: .9rem
line-height: normal line-height: normal
background: var(--color-highlight-background) background: var(--color-highlight-background)
border: 1px solid var(--color-highlight-text) border: 1px solid var(--color-highlight-text)
padding: 1rem padding: 1rem
background: rgba(0,0,0,0.2)
li
line-height: 1.5rem
.gradient .gradient
padding: 0 1rem padding: 0 1rem
height: 2.5rem height: 3rem
background-image: linear-gradient(to right, red, red, rgb(255, 255, 0), rgb(255, 255, 0), green, green) background-image: linear-gradient(to right, red, red, rgb(255, 255, 0), rgb(255, 255, 0), green, green)
display: flex display: flex
margin: 1.5rem auto margin: 2.5rem auto
align-items: center align-items: center
border-radius: 3px border-radius: 3px
max-width: 30rem max-width: 30rem
text-shadow: 1px 1px 4px var(--color-highlight-text-invert),-1px -1px 4px var(--color-highlight-text-invert), -1px 1px 4px var(--color-highlight-text-invert), 1px -1px 4px var(--color-highlight-text-invert) text-shadow: 1px 1px 4px var(--color-highlight-text-invert),-1px -1px 4px var(--color-highlight-text-invert), -1px 1px 4px var(--color-highlight-text-invert), 1px -1px 4px var(--color-highlight-text-invert)
color: var(--color-highlight-text) color: var(--color-highlight-text)
&.size-3 div
width: calc(100%/3)
&.size-4 div
width: calc(100%/4)
&.size-5 div
width: calc(100%/5)
&.size-6 div
width: calc(100%/6)
&.size-7 div
width: calc(100%/7)
div div
width: calc(100%/7)
text-align: center text-align: center
align-self: center align-self: center
font-weight: bold font-weight: bold
@ -487,8 +392,8 @@ label
content: "" content: ""
border: 1px solid var(--color-highlight-text) border: 1px solid var(--color-highlight-text)
border-radius: 3px border-radius: 3px
top: -1rem top: -2.8rem
bottom: -1rem bottom: -1.5rem
position: absolute position: absolute
width: 100% width: 100%
font-weight: bold font-weight: bold
@ -497,7 +402,7 @@ label
justify-content: center justify-content: center
&::after &::after
content: "" content: "PdE"
position: absolute position: absolute
font-size: 1rem font-size: 1rem
top: -2rem top: -2rem

View File

@ -4,91 +4,48 @@ defineProps({
type: String, type: String,
required: true, required: true,
}, },
link: {
type: String,
},
}); });
</script> </script>
<template> <template>
<header> <header>
<router-link :to="{ name: 'home' }"> <router-link :to="{ name: 'home' }">
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
class="color-text"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path <path
d="M22 22L2 22" fill="#5C913B"
stroke="white" d="M36 33.5c0 .828-.672 1.5-1.5 1.5h-33C.672 35 0 34.328 0 33.5S.672 32 1.5 32h33c.828 0 1.5.672 1.5 1.5z"
stroke-width="1.5"
stroke-linecap="round"
/> />
<path <path
d="M2 11L10.1259 4.49931C11.2216 3.62279 12.7784 3.62279 13.8741 4.49931L22 11" fill="#A0041E"
stroke="white" d="M12.344 14.702h-2c-.276 0-.5-.224-.5-.5v-7c0-.276.224-.5.5-.5h2c.276 0 .5.224.5.5v7c0 .276-.224.5-.5.5z"
stroke-width="1.5"
stroke-linecap="round"
/> />
<path <path
d="M15.5 5.5V3.5C15.5 3.22386 15.7239 3 16 3H18.5C18.7761 3 19 3.22386 19 3.5V8.5" fill="#FFCC4D"
stroke="white" d="M5.942 32c-.137-4.657-.506-8-.942-8-.435 0-.804 3.343-.941 8h1.883z"
stroke-width="1.5"
stroke-linecap="round"
/> />
<path <path
d="M4 22V9.5" fill="#77B255"
stroke="white" d="M10 18.731C10 24.306 7.762 26 5 26c-2.761 0-5-1.694-5-7.269C0 13.154 4 5 5 5s5 8.154 5 13.731z"
stroke-width="1.5" />
stroke-linecap="round" <path fill="#FFE8B6" d="M8 16L21 3l13 13v16H8z" />
<path fill="#FFCC4D" d="M21 16h1v16h-1z" />
<path
fill="#66757F"
d="M34 17c-.256 0-.512-.098-.707-.293L21 4.414 8.707 16.707c-.391.391-1.023.391-1.414 0s-.391-1.023 0-1.414l13-13c.391-.391 1.023-.391 1.414 0l13 13c.391.391.391 1.023 0 1.414-.195.195-.451.293-.707.293z"
/> />
<path <path
d="M20 22V9.5" fill="#66757F"
stroke="white" d="M21 17c-.256 0-.512-.098-.707-.293-.391-.391-.391-1.023 0-1.414l6.5-6.5c.391-.391 1.023-.391 1.414 0s.391 1.023 0 1.414l-6.5 6.5c-.195.195-.451.293-.707.293z"
stroke-width="1.5"
stroke-linecap="round"
/> />
<path fill="#C1694F" d="M13 26h4v6h-4z" />
<path fill="#55ACEE" d="M13 17h4v4h-4zm12.5 0h4v4h-4zm0 9h4v4h-4z" />
<path <path
d="M15 22V17C15 15.5858 15 14.8787 14.5607 14.4393C14.1213 14 13.4142 14 12 14C10.5858 14 9.87868 14 9.43934 14.4393C9 14.8787 9 15.5858 9 17V22" fill="#77B255"
stroke="white" d="M10.625 29.991c0 1.613-.858 2.103-1.917 2.103-1.058 0-1.917-.49-1.917-2.103 0-1.613 1.533-3.973 1.917-3.973s1.917 2.359 1.917 3.973zm25.25 0c0 1.613-.858 2.103-1.917 2.103-1.058 0-1.917-.49-1.917-2.103 0-1.613 1.533-3.973 1.917-3.973.384 0 1.917 2.359 1.917 3.973z"
stroke-width="1.5"
/>
<path
d="M14 9.5C14 10.6046 13.1046 11.5 12 11.5C10.8954 11.5 10 10.6046 10 9.5C10 8.39543 10.8954 7.5 12 7.5C13.1046 7.5 14 8.39543 14 9.5Z"
stroke="white"
stroke-width="1.5"
/> />
</svg> </svg>
</router-link> </router-link>
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
<a v-if="link" :href="link">
<svg
class="color-text"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 17V11"
stroke="white"
stroke-width="1.5"
stroke-linecap="round"
/>
<circle
cx="1"
cy="1"
r="1"
transform="matrix(1 0 0 -1 11 9)"
fill="white"
/>
<path
stroke="white"
stroke-width="1.5"
d="M2 12C2 7.28595 2 4.92893 3.46447 3.46447C4.92893 2 7.28595 2 12 2C16.714 2 19.0711 2 20.5355 3.46447C22 4.92893 22 7.28595 22 12C22 16.714 22 19.0711 20.5355 20.5355C19.0711 22 16.714 22 12 22C7.28595 22 4.92893 22 3.46447 20.5355C2 19.0711 2 16.714 2 12Z"
/>
</svg>
</a>
</header> </header>
</template> </template>
@ -106,14 +63,6 @@ header
align-items: center align-items: center
align-content: center align-content: center
a:first-child
border-right: 1px solid var(--color-header-text)
a:last-child
border-left: 1px solid var(--color-header-text)
a:hover svg, a:focus svg, a:active svg
transform: scale(1.1)
a a
height: 100% height: 100%
width: var(--header-size) width: var(--header-size)
@ -123,6 +72,7 @@ a
align-items: center align-items: center
text-align: center text-align: center
align-content: center align-content: center
border-right: 1px solid var(--color-header-text)
text-decoration: none text-decoration: none
p p
@ -136,13 +86,12 @@ h1
flex: 1 flex: 1
font-size: 1.2rem font-size: 1.2rem
font-weight: bold font-weight: bold
text-align: center
svg svg
width: 2rem width: 2rem
margin: 0 auto margin: 0 auto
@media (min-height: 1000px) @media (min-height: 800px)
p p
font-size: 4rem font-size: 4rem

View File

@ -8,7 +8,7 @@ const translationKey = "languages_id";
const scores = data.filter((score) => { const scores = data.filter((score) => {
return ( return (
!!score.translations.find( !!score.translations.find(
(translation) => translation[translationKey] == store.language, (translation) => translation[translationKey] == store.language
) && ) &&
score.results.length && score.results.length &&
score.questions.length score.questions.length
@ -27,82 +27,24 @@ function getTranslation(translations, key) {
@click="store.switchTheme" @click="store.switchTheme"
title="Thème de votre système" title="Thème de votre système"
> >
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
class="color-text" <path
version="1.1" fill="#FFD983"
id="Icons" d="M18 0v36c9.941 0 18-8.059 18-18S27.941 0 18 0z"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 32 32"
xml:space="preserve"
>
<line
fill="none"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
x1="16"
y1="3"
x2="16"
y2="29"
/> />
<path <path
fill="none" fill="#66757F"
stroke="#000000" d="M0 18c0 9.941 8.059 18 18 18V0C8.059 0 0 8.059 0 18z"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
d="M16,23c-3.87,0-7-3.13-7-7s3.13-7,7-7"
/>
<line
fill="none"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
x1="6.81"
y1="6.81"
x2="8.93"
y2="8.93"
/>
<line
fill="none"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
x1="3"
y1="16"
x2="6"
y2="16"
/>
<line
fill="none"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
x1="6.81"
y1="25.19"
x2="8.93"
y2="23.07"
/>
<path
fill="none"
stroke="#000000"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
stroke-miterlimit="10"
d="M16,12.55C17.2,10.43,19.48,9,22.09,9c0.16,0,0.31,0.01,0.47,0.02c-1.67,0.88-2.8,2.63-2.8,4.64
c0,2.9,2.35,5.25,5.25,5.25c1.6,0,3.03-0.72,3.99-1.85C28.48,20.43,25.59,23,22.09,23c-2.61,0-4.89-1.43-6.09-3.55"
/> />
<circle fill="#FFCC4D" cx="25.5" cy="8.5" r="3.5" />
<circle fill="#5B6876" cx="12" cy="16" r="3" />
<circle fill="#5B6876" cx="13.5" cy="27.5" r="3.5" />
<circle fill="#5B6876" cx="15" cy="6" r="2" />
<circle fill="#FFCC4D" cx="33" cy="18" r="1" />
<circle fill="#5B6876" cx="6" cy="9" r="1" />
<circle fill="#FFCC4D" cx="21" cy="31" r="1" />
<circle fill="#5B6876" cx="4" cy="19" r="2" />
<circle fill="#FFCC4D" cx="26" cy="23" r="2" />
</svg> </svg>
</li> </li>
<li <li
@ -110,16 +52,19 @@ function getTranslation(translations, key) {
@click="store.switchTheme" @click="store.switchTheme"
title="Thème sombre" title="Thème sombre"
> >
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
class="color-text" <circle fill="#66757F" cx="18" cy="18" r="18" />
viewBox="0 0 24 24" <g fill="#5B6876">
fill="none" <circle cx="10.5" cy="8.5" r="3.5" />
xmlns="http://www.w3.org/2000/svg" <circle cx="20" cy="16" r="3" />
> <circle cx="21.5" cy="27.5" r="3.5" />
<path <circle cx="21" cy="6" r="2" />
fill="white" <circle cx="3" cy="18" r="1" />
d="M21.0672 11.8568L20.4253 11.469L21.0672 11.8568ZM12.1432 2.93276L11.7553 2.29085V2.29085L12.1432 2.93276ZM21.25 12C21.25 17.1086 17.1086 21.25 12 21.25V22.75C17.9371 22.75 22.75 17.9371 22.75 12H21.25ZM12 21.25C6.89137 21.25 2.75 17.1086 2.75 12H1.25C1.25 17.9371 6.06294 22.75 12 22.75V21.25ZM2.75 12C2.75 6.89137 6.89137 2.75 12 2.75V1.25C6.06294 1.25 1.25 6.06294 1.25 12H2.75ZM15.5 14.25C12.3244 14.25 9.75 11.6756 9.75 8.5H8.25C8.25 12.5041 11.4959 15.75 15.5 15.75V14.25ZM20.4253 11.469C19.4172 13.1373 17.5882 14.25 15.5 14.25V15.75C18.1349 15.75 20.4407 14.3439 21.7092 12.2447L20.4253 11.469ZM9.75 8.5C9.75 6.41182 10.8627 4.5828 12.531 3.57467L11.7553 2.29085C9.65609 3.5593 8.25 5.86509 8.25 8.5H9.75ZM12 2.75C11.9115 2.75 11.8077 2.71008 11.7324 2.63168C11.6686 2.56527 11.6538 2.50244 11.6503 2.47703C11.6461 2.44587 11.6482 2.35557 11.7553 2.29085L12.531 3.57467C13.0342 3.27065 13.196 2.71398 13.1368 2.27627C13.0754 1.82126 12.7166 1.25 12 1.25V2.75ZM21.7092 12.2447C21.6444 12.3518 21.5541 12.3539 21.523 12.3497C21.4976 12.3462 21.4347 12.3314 21.3683 12.2676C21.2899 12.1923 21.25 12.0885 21.25 12H22.75C22.75 11.2834 22.1787 10.9246 21.7237 10.8632C21.286 10.804 20.7293 10.9658 20.4253 11.469L21.7092 12.2447Z" <circle cx="30" cy="9" r="1" />
/> <circle cx="15" cy="31" r="1" />
<circle cx="32" cy="19" r="2" />
<circle cx="10" cy="23" r="2" />
</g>
</svg> </svg>
</li> </li>
<li <li
@ -127,94 +72,52 @@ function getTranslation(translations, key) {
@click="store.switchTheme" @click="store.switchTheme"
title="Thème clair" title="Thème clair"
> >
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
class="color-text" <circle fill="#FFD983" cx="18" cy="18" r="18" />
viewBox="0 0 24 24" <g fill="#FFCC4D">
fill="none" <circle cx="10.5" cy="8.5" r="3.5" />
xmlns="http://www.w3.org/2000/svg" <circle cx="20" cy="17" r="3" />
> <circle cx="24.5" cy="28.5" r="3.5" />
<circle cx="12" cy="12" r="5" stroke="#1C274C" stroke-width="1.5" /> <circle cx="22" cy="5" r="2" />
<path <circle cx="3" cy="18" r="1" />
d="M12 2V4" <circle cx="30" cy="9" r="1" />
stroke="#1C274C" <circle cx="15" cy="31" r="1" />
stroke-width="1.5" <circle cx="32" cy="19" r="2" />
stroke-linecap="round" <circle cx="10" cy="23" r="2" />
/> </g>
<path
d="M12 20V22"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M4 12L2 12"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M22 12L20 12"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M19.7778 4.22266L17.5558 6.25424"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M4.22217 4.22266L6.44418 6.25424"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M6.44434 17.5557L4.22211 19.7779"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
d="M19.7778 19.7773L17.5558 17.5551"
stroke="#1C274C"
stroke-width="1.5"
stroke-linecap="round"
/>
</svg> </svg>
</li> </li>
</ul> </ul>
<h1>Scores Ceiba</h1> <h1>Scores Ceiba</h1>
<ul> <ul>
<li v-if="store.language == 'fr-FR'" @click="store.switchLanguage"> <li v-if="store.language == 'fr-FR'" @click="store.switchLanguage">
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
xmlns="http://www.w3.org/2000/svg" <path
id="flag-icons-fr" fill="#ED2939"
viewBox="0 0 640 480" d="M36 27c0 2.209-1.791 4-4 4h-8V5h8c2.209 0 4 1.791 4 4v18z"
> />
<path fill="#fff" d="M0 0h640v480H0z" /> <path
<path fill="#000091" d="M0 0h213.3v480H0z" /> fill="#002495"
<path fill="#e1000f" d="M426.7 0H640v480H426.7z" /> d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"
/>
<path fill="#EEE" d="M12 5h12v26H12z" />
</svg> </svg>
</li> </li>
<li v-if="store.language == 'en-US'" @click="store.switchLanguage"> <li v-if="store.language == 'en-US'" @click="store.switchLanguage">
<svg <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
xmlns="http://www.w3.org/2000/svg" <path
id="flag-icons-gb" fill="#B22334"
viewBox="0 0 640 480" d="M35.445 7C34.752 5.809 33.477 5 32 5H18v2h17.445zM0 25h36v2H0zm18-8h18v2H18zm0-4h18v2H18zM0 21h36v2H0zm4 10h28c1.477 0 2.752-.809 3.445-2H.555c.693 1.191 1.968 2 3.445 2zM18 9h18v2H18z"
> />
<path fill="#012169" d="M0 0h640v480H0z" /> <path
fill="#EEE"
d="M.068 27.679c.017.093.036.186.059.277.026.101.058.198.092.296.089.259.197.509.333.743L.555 29h34.89l.002-.004c.135-.233.243-.483.332-.741.034-.099.067-.198.093-.301.023-.09.042-.182.059-.275.041-.22.069-.446.069-.679H0c0 .233.028.458.068.679zM0 23h36v2H0zm0-4v2h36v-2H18zm18-4h18v2H18zm0-4h18v2H18zM0 9c0-.233.03-.457.068-.679C.028 8.542 0 8.767 0 9zm.555-2l-.003.005L.555 7zM.128 8.044c.025-.102.06-.199.092-.297-.034.098-.066.196-.092.297zM18 9h18c0-.233-.028-.459-.069-.68-.017-.092-.035-.184-.059-.274-.027-.103-.059-.203-.094-.302-.089-.258-.197-.507-.332-.74.001-.001 0-.003-.001-.004H18v2z"
/>
<path fill="#3C3B6E" d="M18 5H4C1.791 5 0 6.791 0 9v10h18V5z" />
<path <path
fill="#FFF" fill="#FFF"
d="m75 0 244 181L562 0h78v62L400 241l240 178v61h-80L320 301 81 480H0v-60l239-178L0 64V0z" d="M2.001 7.726l.618.449-.236.725L3 8.452l.618.448-.236-.725L4 7.726h-.764L3 7l-.235.726zm2 2l.618.449-.236.725.617-.448.618.448-.236-.725L6 9.726h-.764L5 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 9l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 9l-.235.726zm-8 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L5 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L9 13l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L13 13l-.235.726zm-6-6l.618.449-.236.725L7 8.452l.618.448-.236-.725L8 7.726h-.764L7 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 7l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 7l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 11l-.235.726zM6.383 12.9L7 12.452l.618.448-.236-.725.618-.449h-.764L7 11l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 11l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 11l-.235.726zm-12 4l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L3 15l-.235.726zM6.383 16.9L7 16.452l.618.448-.236-.725.618-.449h-.764L7 15l-.235.726h-.764l.618.449zm3.618-1.174l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L11 15l-.235.726zm4 0l.618.449-.236.725.617-.448.618.448-.236-.725.618-.449h-.764L15 15l-.235.726z"
/> />
<path
fill="#C8102E"
d="m424 281 216 159v40L369 281zm-184 20 6 35L54 480H0zM640 0v3L391 191l2-44L590 0zM0 0l239 176h-60L0 42z"
/>
<path fill="#FFF" d="M241 0v480h160V0zM0 160v160h640V160z" />
<path fill="#C8102E" d="M0 193v96h640v-96zM273 0v480h96V0z" />
</svg> </svg>
</li> </li>
</ul> </ul>
@ -224,51 +127,24 @@ function getTranslation(translations, key) {
<div class="container" v-if="scores"> <div class="container" v-if="scores">
<ul> <ul>
<template v-for="(score, index) in scores" :key="score.id"> <template v-for="(score, index) in scores" :key="score.id">
<li class="white" v-if="index % 2 === 0"> <li v-if="index % 2 === 0">
<router-link :to="{ name: 'score', params: { id: score.id } }">
<img height="200" :src="`/answers/${score.image}.webp`" /> <img height="200" :src="`/answers/${score.image}.webp`" />
</router-link>
</li> </li>
<li> <li>
<router-link <router-link :to="{ name: 'score', params: { id: score.id } }">{{
:to="{ name: 'score', params: { id: score.id } }"
class="link"
>{{
getTranslation(score.translations, "languages_id").title getTranslation(score.translations, "languages_id").title
}}</router-link }}</router-link>
>
</li> </li>
<li class="white" v-if="index % 2 !== 0"> <li v-if="index % 2 !== 0">
<router-link :to="{ name: 'score', params: { id: score.id } }">
<img height="200" :src="`/answers/${score.image}.webp`" /> <img height="200" :src="`/answers/${score.image}.webp`" />
</router-link>
</li> </li>
</template> </template>
</ul> </ul>
</div> </div>
</main> </main>
<footer>
<p v-if="store.language == 'fr-FR'">
Scores & Appli par <a href="https://ceiba-conseil.com">Ceiba</a>
</p>
<p v-if="store.language == 'en-US'">
Scores & App by <a href="https://ceiba-conseil.com">Ceiba</a>
</p>
</footer>
</template> </template>
<style lang="sass" scoped> <style lang="sass" scoped>
footer
background: var(--color-header-background)
text-align: center
padding: 1rem
color: var(--color-header-text)
height: var(--footer-size)
display: flex
justify-content: space-around
align-items: center
a
color: var(--color-header-text)
header header
height: var(--header-size) height: var(--header-size)
overflow: hidden overflow: hidden
@ -298,27 +174,21 @@ header
.hidden .hidden
display: none display: none
svg
height: 32px
width: 32px
main main
width: 100% width: 100%
min-height: calc(100% - var(--header-size) - var(--footer-size)) height: calc(100% - var(--header-size))
background-color: var(--color-background) background-color: var(--color-background)
overflow-x: hidden overflow-x: hidden
overflow-y: auto overflow-y: auto
text-align: center text-align: center
display: flex
flex-direction: column
justify-content: space-evenly
.homeImage .homeImage
height: 30vh height: 30vh
width: 100% width: 100%
max-width: 600px max-width: 600px
object-fit: contain object-fit: contain
margin: 1rem auto 0 margin: 0 auto
.container .container
display: flex display: flex
@ -344,13 +214,10 @@ main
border: 1px solid var(--color-green) border: 1px solid var(--color-green)
img img
border: 2px solid var(--color-background)
max-width: 100% max-width: 100%
object-fit: contain
.white a
background: white
a.link
font-size: 2rem font-size: 2rem
line-height: 2rem line-height: 2rem
color: var(--color-green) color: var(--color-green)

View File

@ -1,16 +1,10 @@
import { createApp } from "vue"; import { createApp } from "vue";
import { createPinia } from "pinia"; import { createPinia } from "pinia";
import piniaPersist from "pinia-plugin-persist"; import piniaPersist from "pinia-plugin-persist";
import { registerSW } from "virtual:pwa-register";
import App from "@/App.vue"; import App from "@/App.vue";
import router from "@/router"; import router from "@/router";
if ("serviceWorker" in navigator) {
// && !/localhost/.test(window.location)) {
registerSW();
}
const app = createApp(App); const app = createApp(App);
const pinia = createPinia(); const pinia = createPinia();
pinia.use(piniaPersist); pinia.use(piniaPersist);

View File

@ -1,55 +1,11 @@
import { fileURLToPath, URL } from "url"; import { fileURLToPath, URL } from "url";
import { VitePWA } from "vite-plugin-pwa";
import { defineConfig } from "vite"; import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue"; import vue from "@vitejs/plugin-vue";
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
// publicDir: 'public', plugins: [vue()],
// includeAssets: ['public/answers/*.web'],
plugins: [
vue(),
VitePWA({
name: "My First Progressive Web app",
short_name: "First PWA",
theme_color: "#eb5252",
background_color: "#000000",
registerType: "autoUpdate",
injectRegister: "auto",
// add this to cache all the imports
workbox: {
globPatterns: ["**/*"],
},
// add this to cache all the
// static assets in the public folder
includeAssets: ["**/*"],
useCredentials: true,
manifest: {
theme_color: "#eb5252",
orientation: "portrait",
display: "fullscreen",
scope: "/",
icons: [
{
src: "/images/pwa-icon-256.png",
sizes: "192x192",
type: "image/png",
purpose: "any maskable",
},
{
src: "/images/pwa-icon-512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable",
},
],
},
devOptions: {
enabled: true,
},
}),
],
resolve: { resolve: {
alias: { alias: {
"@": fileURLToPath(new URL("./src", import.meta.url)), "@": fileURLToPath(new URL("./src", import.meta.url)),