feat: Mise à jour du design de l'application
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Simon 2023-04-27 22:31:59 +02:00
parent 58a6da1d94
commit 9d3e144748
16 changed files with 675 additions and 104 deletions

3
.gitignore vendored
View File

@ -30,3 +30,6 @@ coverage
# app # app
src/data.json src/data.json
public/answers public/answers
public/homepage.webp
public/logo.png
public/favicon/*.png

View File

@ -2,38 +2,39 @@
Vous trouverez ici le code source de l'application de Scores de [Ceiba Conseil](https://www.ceiba-conseil.com/). Vous trouverez ici le code source de l'application de Scores de [Ceiba Conseil](https://www.ceiba-conseil.com/).
## Information ## Information
- Les emojis ont été pris depuis le site https://twemoji-cheatsheet.vercel.app/ - Le projet est développé par _[Weko](https://weko.io)_ et hébergé par _[RésiLien](https://resilien.fr)_
- L'application utilise [un script](./scripts/fetchData.js) permettant d'importer des contenus depuis [une interface d'administration](https://admin.ceiba-conseil.com)
- [Un outil automatique](https://ci.resilien.fr/Weko/ceiba-scores) permet une compilation automatique du projet lorsqu'un changement est effectué coté administration
- [Les emojis](https://twemoji-cheatsheet.vercel.app/) sont libres de droit proposé par _Twitter_
- _RésiLien_ reçoit des notifications automatiques lorsqu'un problème arrive lors de la compilation sur le canal _Matrix_ suivant https://matrix.to/#/#resilien-monitoring:converser.eu
## Recommended IDE Setup ## Développement
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin). L'application a été développée avec le framework Javascript _[Vue.js](https://vuejs.org/)_ et l'outil _[Vite](https://vitejs.dev/)_.
Il utilise _[NPM](https://www.npmjs.com/)_ pour la gestion des dépendances Javascript.
## Customize configuration ### Recommandation pour votre environnement de développement
See [Vite Configuration Reference](https://vitejs.dev/config/). _[VSCode](https://code.visualstudio.com/)_ + _[Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)_ (et désactiver _Vetur_) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.vscode-typescript-vue-plugin).
## Project Setup Une configuration spécifique à _Vite_ peut être mise en place, voir [la référence](https://vitejs.dev/config/).
```sh ### Commandes
npm install
```
### Compile and Hot-Reload for Development - Installation des dépendances : `npm install`
- Import des données de l'administration : `npm run fetchData`
- Compilation avec du _Hot-Reload_ (Rechargement à chaud) pour le développement : `npm run dev`
- Compilation et minification pour la production : `npm run build`
- Les règles de mise en forme sont assurées par _[ESLint](https://eslint.org/)_ : `npm run lint`
```sh ## Logiciels utilisés
npm run dev
```
### Compile and Minify for Production _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.
```sh Voici les différentes briques utilisé autour du projet :
npm run build - _[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
- _[Drone](https://drone.io)_ pour la compilation automatique du projet
### Lint with [ESLint](https://eslint.org/) - _[Matrix](https://fr.wikipedia.org/wiki/Matrix_(protocole))_ est un protocole ouvert pour de la communication en temps réel
```sh
npm run lint
```

View File

@ -2,7 +2,22 @@
<html lang="fr"> <html lang="fr">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" /> <link rel="apple-touch-icon" sizes="57x57" href="/favicon/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/favicon/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/favicon/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/favicon/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/favicon/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/favicon/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/favicon/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/favicon/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/favicon/android-icon-192x192.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="16x16" href="/favicon/favicon-16x16.png">
<link rel="manifest" href="/favicon/manifest.json">
<meta name="msapplication-TileColor" content="#ffffff">
<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>
</head> </head>

83
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@splidejs/vue-splide": "^0.5.18", "@splidejs/vue-splide": "^0.5.18",
"html2canvas": "^1.4.1",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persist": "^1.0.0",
"sass": "^1.49.9", "sass": "^1.49.9",
@ -542,6 +543,14 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true "dev": true
}, },
"node_modules/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
"engines": {
"node": ">= 0.6.0"
}
},
"node_modules/base64-js": { "node_modules/base64-js": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -844,6 +853,14 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/csstype": { "node_modules/csstype": {
"version": "2.6.20", "version": "2.6.20",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
@ -1779,6 +1796,18 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
}, },
"node_modules/html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"dependencies": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/ieee754": { "node_modules/ieee754": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -3059,6 +3088,14 @@
"node": ">= 8" "node": ">= 8"
} }
}, },
"node_modules/text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"dependencies": {
"utrie": "^1.0.2"
}
},
"node_modules/text-table": { "node_modules/text-table": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -3124,6 +3161,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}, },
"node_modules/utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"dependencies": {
"base64-arraybuffer": "^1.0.2"
}
},
"node_modules/v8-compile-cache": { "node_modules/v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
@ -3814,6 +3859,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true "dev": true
}, },
"base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ=="
},
"base64-js": { "base64-js": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -4019,6 +4069,14 @@
"which": "^2.0.1" "which": "^2.0.1"
} }
}, },
"css-line-break": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz",
"integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==",
"requires": {
"utrie": "^1.0.2"
}
},
"csstype": { "csstype": {
"version": "2.6.20", "version": "2.6.20",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz",
@ -4622,6 +4680,15 @@
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
}, },
"html2canvas": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz",
"integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==",
"requires": {
"css-line-break": "^2.1.0",
"text-segmentation": "^1.0.3"
}
},
"ieee754": { "ieee754": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -5490,6 +5557,14 @@
"terser": "^5.7.2" "terser": "^5.7.2"
} }
}, },
"text-segmentation": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz",
"integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==",
"requires": {
"utrie": "^1.0.2"
}
},
"text-table": { "text-table": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@ -5540,6 +5615,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}, },
"utrie": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz",
"integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==",
"requires": {
"base64-arraybuffer": "^1.0.2"
}
},
"v8-compile-cache": { "v8-compile-cache": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",

View File

@ -11,6 +11,7 @@
}, },
"dependencies": { "dependencies": {
"@splidejs/vue-splide": "^0.5.18", "@splidejs/vue-splide": "^0.5.18",
"html2canvas": "^1.4.1",
"pinia": "^2.0.11", "pinia": "^2.0.11",
"pinia-plugin-persist": "^1.0.0", "pinia-plugin-persist": "^1.0.0",
"sass": "^1.49.9", "sass": "^1.49.9",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig><msapplication><tile><square70x70logo src="/favicon/ms-icon-70x70.png"/><square150x150logo src="/favicon/ms-icon-150x150.png"/><square310x310logo src="/favicon/ms-icon-310x310.png"/><TileColor>#ffffff</TileColor></tile></msapplication></browserconfig>

View File

@ -0,0 +1,41 @@
{
"name": "App",
"icons": [
{
"src": "\/favicon\/android-icon-36x36.png",
"sizes": "36x36",
"type": "image\/png",
"density": "0.75"
},
{
"src": "\/favicon\/android-icon-48x48.png",
"sizes": "48x48",
"type": "image\/png",
"density": "1.0"
},
{
"src": "\/favicon\/android-icon-72x72.png",
"sizes": "72x72",
"type": "image\/png",
"density": "1.5"
},
{
"src": "\/favicon\/android-icon-96x96.png",
"sizes": "96x96",
"type": "image\/png",
"density": "2.0"
},
{
"src": "\/favicon\/android-icon-144x144.png",
"sizes": "144x144",
"type": "image\/png",
"density": "3.0"
},
{
"src": "\/favicon\/android-icon-192x192.png",
"sizes": "192x192",
"type": "image\/png",
"density": "4.0"
}
]
}

91
public/test.html Normal file
View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="robots" content="noindex, nofollow">
<style>
body {
padding: 0;
margin: 0;
}
svg:not(:root) {
display: block;
}
.playable-code {
background-color: #f4f7f8;
border: none;
border-left: 6px solid #558abb;
border-width: medium medium medium 6px;
color: #4d4e53;
height: 100px;
width: 90%;
padding: 10px 10px 0;
}
.playable-canvas {
border: 1px solid #4d4e53;
border-radius: 2px;
}
.playable-buttons {
text-align: right;
width: 90%;
padding: 5px 10px 5px 26px;
}
</style>
<title>Navigator: share() method - sharing_files - code sample</title>
</head>
<body>
<div>
<label for="files">Select images to share:</label>
<input id="files" type="file" accept="image/*" multiple />
</div>
<button id="share" type="button">Share your images!</button>
<output id="output"></output>
<script>
const input = document.getElementById("files");
const output = document.getElementById("output");
document.getElementById("share").addEventListener("click", async () => {
const files = input.files;
if (files.length === 0) {
output.textContent = "No files selected.";
return;
}
// feature detecting navigator.canShare() also implies
// the same for the navigator.share()
if (!navigator.canShare) {
output.textContent = `Your browser doesn't support the Web Share API.`;
return;
}
if (navigator.canShare({ files })) {
try {
await navigator.share({
files,
title: "Images",
text: "Beautiful images",
});
output.textContent = "Shared!";
} catch (error) {
output.textContent = `Error: ${error.message}`;
}
} else {
output.textContent = `Your system doesn't support sharing these files.`;
}
});
</script>
</body>
</html>

View File

@ -30,7 +30,7 @@ async function fetchAsset(uuid) {
return fetch(url); return fetch(url);
} }
async function fetchData() { async function fetchScoresData() {
const fields = [ const fields = [
"*", "*",
"translations.*", "translations.*",
@ -72,18 +72,7 @@ async function fetchData() {
for (const answer of question.questions_id.answers) { for (const answer of question.questions_id.answers) {
const uuid = answer.answers_id.image; const uuid = answer.answers_id.image;
if (uuid) { if (uuid) {
console.log(`${folder}/${uuid}`); await downloadImage(uuid, `${folder}/${uuid}.webp`, { height: 200 });
const response = await fetchAsset(uuid);
try {
const thumbnail = sharp().resize({ height: 200 }).webp();
await streamPipeline(
response.body,
thumbnail,
createWriteStream(`${folder}/${uuid}.webp`)
);
} catch (err) {
console.log(err);
}
} }
} }
} }
@ -92,4 +81,231 @@ async function fetchData() {
// await sharp('src/assets/arbre.png').resize({ width: 440, height: 690 }).webp().toFile('public/arbre.webp') // await sharp('src/assets/arbre.png').resize({ width: 440, height: 690 }).webp().toFile('public/arbre.webp')
} }
async function transformImage(response, path, options, format = "webp") {
try {
let thumbnail;
console.log(path);
if (format == "webp") {
thumbnail = sharp().resize(options).webp();
} else {
thumbnail = sharp().resize(options).toFormat("png");
}
const stream = createWriteStream(path);
await streamPipeline(response.body, thumbnail, stream);
await stream;
} catch (err) {
console.log(err);
}
}
async function downloadImage(uuid, path, options, format = "webp") {
const response = await fetchAsset(uuid);
await transformImage(response, path, options, format);
}
async function fetchHomepageData() {
const fields = ["*"];
const url = `/items/homepage?${fields
.map((item) => `fields[]=${item}`)
.join("&")}`;
const homepage = (await fetchJSONApi(url)).data;
await downloadImage(homepage.image, `public/homepage.webp`, {
width: 1280,
height: 720,
fit: sharp.fit.cover,
});
const favicons = [
{
path: `public/favicon/android-icon-192x192.png`,
options: {
width: 192,
height: 192,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-57x57.png`,
options: {
width: 57,
height: 57,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-60x60.png`,
options: {
width: 60,
height: 60,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-72x72.png`,
options: {
width: 72,
height: 72,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-76x76.png`,
options: {
width: 76,
height: 76,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-114x114.png`,
options: {
width: 114,
height: 114,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-120x120.png`,
options: {
width: 120,
height: 120,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-144x144.png`,
options: {
width: 144,
height: 144,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-152x152.png`,
options: {
width: 152,
height: 152,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/apple-icon-180x180.png`,
options: {
width: 180,
height: 180,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/favicon-16x16.png`,
options: {
width: 16,
height: 16,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/favicon-32x32.png`,
options: {
width: 32,
height: 32,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/favicon-96x96.png`,
options: {
width: 96,
height: 96,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/favicon-256x256.png`,
options: {
width: 256,
height: 256,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/ms-icon-70x70.png`,
options: {
width: 70,
height: 70,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/ms-icon-144x144.png`,
options: {
width: 144,
height: 144,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/ms-icon-150x150.png`,
options: {
width: 150,
height: 150,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
{
path: `public/favicon/ms-icon-310x310.png`,
options: {
width: 310,
height: 310,
fit: sharp.fit.contain,
background: { r: 255, g: 255, b: 255, alpha: 0 },
},
format: "png",
},
];
for (const favicon of favicons) {
downloadImage(homepage.logo, favicon.path, favicon.options, favicon.format);
}
}
async function fetchData() {
await fetchHomepageData();
await fetchScoresData();
}
fetchData(); fetchData();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 626 KiB

View File

@ -8,6 +8,7 @@
--header-size-small: 64px; --header-size-small: 64px;
--header-size-big: 128px; --header-size-big: 128px;
--header-size: var(--header-size-small);
} }
/* semantic color variables for this project */ /* semantic color variables for this project */
@ -19,7 +20,6 @@
--color-highlight-background: var(--color-green); --color-highlight-background: var(--color-green);
--color-highlight-text: var(--color-white); --color-highlight-text: var(--color-white);
--color-highlight-text-invert: var(--color-black); --color-highlight-text-invert: var(--color-black);
--header-size: var(--header-size-small)
} }
body.theme-dark { body.theme-dark {
@ -44,7 +44,7 @@ body.theme-dark {
} }
} }
@media (min-width: 1024px) { @media (min-height: 800px) {
:root { :root {
--header-size: var(--header-size-big); --header-size: var(--header-size-big);
} }
@ -80,3 +80,17 @@ body {
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.btn {
width: 3rem;
height: 3rem;
padding: .5rem;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
border-radius: 100%;
position: absolute;
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);
}

View File

@ -41,11 +41,7 @@ function slideMove(splide, newIndex) {
:id="`question_${question.id}`" :id="`question_${question.id}`"
ref="slides" ref="slides"
> >
<SplideSlide <SplideSlide v-for="answer in question.answers" :key="answer.id">
v-for="answer in question.answers"
:key="answer.id"
@click="$emit('nextQuestion')"
>
<img height="200" :src="`/answers/${answer.image}.webp`" /> <img height="200" :src="`/answers/${answer.image}.webp`" />
</SplideSlide> </SplideSlide>
</Splide> </Splide>
@ -77,9 +73,39 @@ function slideMove(splide, newIndex) {
</template> </template>
</div> </div>
</div> </div>
<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>
</template> </template>
<style lang="sass"> <style lang="sass">
.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)
.splide__arrow .splide__arrow
background: transparent background: transparent
border: 3px solid var(--color-green) border: 3px solid var(--color-green)
@ -93,6 +119,7 @@ function slideMove(splide, newIndex) {
width: 1.6rem width: 1.6rem
.splide__pagination .splide__pagination
bottom: -1.5em bottom: -1.5em
display: none
.splide__pagination__page .splide__pagination__page
width: .7rem width: .7rem
height: .7rem height: .7rem
@ -108,7 +135,7 @@ legend
text-align: center text-align: center
font-size: 1.4rem font-size: 1.4rem
line-height: 2rem line-height: 2rem
margin: 1rem font-weight: bold
.choices .choices
list-style-type: none list-style-type: none
@ -116,12 +143,15 @@ legend
display: inline-block display: inline-block
padding-left: 0 padding-left: 0
label
cursor: pointer
input[type=radio] input[type=radio]
display: none display: none
& + label & + label
position: relative position: relative
padding-left: 2rem padding: .2rem .2rem .2rem 2rem
& + label::before, & + label::before,
& + label::after & + label::after
display: block display: block
@ -130,20 +160,22 @@ legend
content:'' content:''
border-radius: 1rem border-radius: 1rem
& + label::before & + label::before
bottom: 0 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::after & + label::after
bottom: 3px 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
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
&:checked + label::before &:checked + label::before
background-color: white
&:checked + label::after
background-color: var(--color-green) background-color: var(--color-green)
&:checked + label::after
background-color: white
.main .main
height: 100% height: 100%
@ -163,6 +195,9 @@ legend
max-width: 100% max-width: 100%
min-width: 280px min-width: 280px
@media (max-height: 600px)
margin: 1rem auto
h2 h2
font-size: 2rem font-size: 2rem

View File

@ -9,6 +9,7 @@ import { Splide, SplideSlide } from "@splidejs/vue-splide";
import Question from "./Question.vue"; import Question from "./Question.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 html2canvas from "html2canvas";
const props = defineProps({ const props = defineProps({
id: { id: {
@ -110,6 +111,16 @@ function nextQuestion() {
console.log(slides); console.log(slides);
}, 100); }, 100);
} }
async function share() {
console.log(document.querySelector(".latest"));
const canvas = await html2canvas(document.querySelector("html"));
let anchor = document.createElement("a");
anchor.download = "download.png";
anchor.href = canvas.toDataURL("image/png");
anchor.click();
anchor.remove();
}
</script> </script>
<template> <template>
@ -135,7 +146,7 @@ function nextQuestion() {
@nextQuestion="nextQuestion" @nextQuestion="nextQuestion"
/> />
</SplideSlide> </SplideSlide>
<SplideSlide class="latest" id="details"> <SplideSlide class="latest">
<template v-if="displayScoreResult && result"> <template v-if="displayScoreResult && result">
<div> <div>
<h2 class="center">Probabilité d'échec</h2> <h2 class="center">Probabilité d'échec</h2>
@ -162,7 +173,7 @@ function nextQuestion() {
</li> </li>
</ul> </ul>
</div> </div>
<button>Partager</button> <button @click="() => share()">Partager</button>
</div> </div>
</template> </template>
<template v-else> <template v-else>
@ -251,17 +262,23 @@ label
line-height: 2rem line-height: 2rem
font-size: 2.6rem font-size: 2.6rem
@media (max-height: 600px)
font-size: 1.5rem
& + h2
font-size: 2rem
ul ul
text-align: left text-align: left
padding-left: 1.5rem padding-left: 1.5rem
list-style-type: disc list-style-type: disc
.details .details
text-align: left text-align: left !important
font-size: 1.1rem font-family: serif
font-size: .9rem
line-height: normal
background: var(--color-highlight-background)
border: 1px solid var(--color-highlight-text) border: 1px solid var(--color-highlight-text)
background: var(--color-text)
margin: 1rem
padding: 1rem padding: 1rem
.gradient .gradient

View File

@ -10,57 +10,94 @@ defineProps({
<template> <template>
<header> <header>
<router-link :to="{ name: 'home' }"> <router-link :to="{ name: 'home' }">
<p></p> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36">
<path
fill="#5C913B"
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"
/>
<path
fill="#A0041E"
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"
/>
<path
fill="#FFCC4D"
d="M5.942 32c-.137-4.657-.506-8-.942-8-.435 0-.804 3.343-.941 8h1.883z"
/>
<path
fill="#77B255"
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"
/>
<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
fill="#66757F"
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"
/>
<path fill="#C1694F" d="M13 26h4v6h-4z" />
<path fill="#55ACEE" d="M13 17h4v4h-4zm12.5 0h4v4h-4zm0 9h4v4h-4z" />
<path
fill="#77B255"
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"
/>
</svg>
</router-link> </router-link>
<h1>{{ title }}</h1> <h1>{{ title }}</h1>
</header> </header>
</template> </template>
<style scoped> <style lang="sass" scoped>
header { header
height: var(--header-size); height: var(--header-size)
position: fixed; position: fixed
background: var(--color-header-background); background: var(--color-header-background)
color: var(--color-header-text); color: var(--color-header-text)
width: 100%; width: 100%
z-index: 1; z-index: 1
top: 0; top: 0
border-bottom: 1px solid var(--color-header-text); border-bottom: 1px solid var(--color-header-text)
display: flex; display: flex
align-items: center; align-items: center
align-content: center; align-content: center
}
a { a
height: 100%; height: 100%
width: var(--header-size); width: var(--header-size)
min-width: var(--header-size); min-width: var(--header-size)
margin: 0; margin: 0
display: flex; display: flex
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); border-right: 1px solid var(--color-header-text)
text-decoration: none; text-decoration: none
}
p { p
margin: 0 auto; margin: 0 auto
font-size: 2rem; font-size: 2rem
color: var(--color-header-text); color: var(--color-header-text)
}
h1 { h1
margin: 0 1rem; margin: 0 1rem
line-height: 0.9; line-height: 0.9
flex: 1; flex: 1
font-size: 1.2rem; font-size: 1.2rem
font-weight: bold; font-weight: bold
}
@media (min-width: 1024px) { svg
p { width: 2rem
font-size: 4rem; margin: 0 auto
}
} @media (min-height: 800px)
p
font-size: 4rem
h1
font-size: 2rem
svg
width: 4rem
</style> </style>

View File

@ -123,6 +123,7 @@ function getTranslation(translations, key) {
</ul> </ul>
</header> </header>
<main> <main>
<img src="/homepage.webp" class="homeImage" />
<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">
@ -177,14 +178,25 @@ header
main main
width: 100% width: 100%
height: calc(100% - var(--header-size)) height: calc(100% - var(--header-size))
padding: 1rem background-color: var(--color-background)
overflow-x: hidden
overflow-y: auto
text-align: center
.homeImage
height: 30vh
width: 100%
max-width: 600px
object-fit: contain
margin: 0 auto
.container
display: flex display: flex
justify-content: center justify-content: center
align-items: center align-items: center
overflow: hidden overflow: hidden
background-color: var(--color-background) padding: 1rem
.container
ul ul
margin: 0 margin: 0
padding: 0 padding: 0
@ -193,6 +205,7 @@ main
flex-wrap: wrap flex-wrap: wrap
justify-content: center justify-content: center
max-width: 404px max-width: 404px
border: 1px solid var(--color-green)
li li
height: 202px height: 202px
@ -206,6 +219,7 @@ main
a a
font-size: 2rem font-size: 2rem
line-height: 2rem
color: var(--color-green) color: var(--color-green)
display: block display: block
width: 100% width: 100%
@ -215,4 +229,5 @@ main
justify-content: center justify-content: center
text-align: center text-align: center
padding: 1rem padding: 1rem
text-decoration: none
</style> </style>