This commit is contained in:
Simon 2023-04-27 22:31:59 +02:00
parent 58a6da1d94
commit 77cab4fbd3
15 changed files with 551 additions and 39 deletions

3
.gitignore vendored
View File

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

View File

@ -4,36 +4,53 @@ Vous trouverez ici le code source de l'application de Scores de [Ceiba Conseil](
## 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 ont été pris depuis le site https://twemoji-cheatsheet.vercel.app/ et sont libres de droit proposé par Twitter
## Recommended IDE Setup
## Développement
L'application a été développé 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.
### Recommendation pour votre environnement de 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).
## Customize configuration
Une configuration spécifique à Vite peut être mise en place, voir [la référence](https://vitejs.dev/config/).
See [Vite Configuration Reference](https://vitejs.dev/config/).
### Commandes
## Project Setup
Installation des dépendances
```sh
npm install
```
### Compile and Hot-Reload for Development
Compilation avec du Hot-Reload (Rechargement à chaud) pour le développement
```sh
npm run dev
```
### Compile and Minify for Production
Compilation and minification pour la production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
Les règles de mise en forme sont assuré par [ESLint](https://eslint.org/)
```sh
npm run lint
```
## Logiciels utilisés
RésiLien met en place des outils open source eprouvé dans le temps et dont les communautés sont assez grande pour permettre une perenité de ses projets.
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/)
- [Directus](https://directus.io/) pour l'administration
- [Drone](https://drone.io) pour la compilation automatique du projet

View File

@ -2,7 +2,22 @@
<html lang="fr">
<head>
<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" />
<title>Scores Ceiba</title>
</head>

83
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0",
"dependencies": {
"@splidejs/vue-splide": "^0.5.18",
"html2canvas": "^1.4.1",
"pinia": "^2.0.11",
"pinia-plugin-persist": "^1.0.0",
"sass": "^1.49.9",
@ -542,6 +543,14 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"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": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -844,6 +853,14 @@
"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": {
"version": "2.6.20",
"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",
"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": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -3059,6 +3088,14 @@
"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": {
"version": "0.2.0",
"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",
"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": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
@ -3814,6 +3859,11 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"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": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
@ -4019,6 +4069,14 @@
"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": {
"version": "2.6.20",
"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",
"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": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@ -5490,6 +5557,14 @@
"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": {
"version": "0.2.0",
"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",
"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": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",

View File

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

Binary file not shown.

Before

(image error) 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);
}
async function fetchData() {
async function fetchScoresData() {
const fields = [
"*",
"translations.*",
@ -72,18 +72,7 @@ async function fetchData() {
for (const answer of question.questions_id.answers) {
const uuid = answer.answers_id.image;
if (uuid) {
console.log(`${folder}/${uuid}`);
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);
}
await downloadImage(uuid, `${folder}/${uuid}.webp`, { height: 200 });
}
}
}
@ -92,4 +81,231 @@ async function fetchData() {
// 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();

Binary file not shown.

Before

(image error) Size: 626 KiB

View File

@ -8,6 +8,7 @@
--header-size-small: 64px;
--header-size-big: 128px;
--header-size: var(--header-size-small);
}
/* semantic color variables for this project */
@ -19,7 +20,6 @@
--color-highlight-background: var(--color-green);
--color-highlight-text: var(--color-white);
--color-highlight-text-invert: var(--color-black);
--header-size: var(--header-size-small)
}
body.theme-dark {
@ -44,7 +44,7 @@ body.theme-dark {
}
}
@media (min-width: 1024px) {
@media (min-height: 800px) {
:root {
--header-size: var(--header-size-big);
}

View File

@ -93,6 +93,7 @@ function slideMove(splide, newIndex) {
width: 1.6rem
.splide__pagination
bottom: -1.5em
display: none
.splide__pagination__page
width: .7rem
height: .7rem
@ -108,7 +109,7 @@ legend
text-align: center
font-size: 1.4rem
line-height: 2rem
margin: 1rem
font-weight: bold
.choices
list-style-type: none
@ -116,12 +117,15 @@ legend
display: inline-block
padding-left: 0
label
cursor: pointer
input[type=radio]
display: none
& + label
position: relative
padding-left: 2rem
padding: .2rem .2rem .2rem 2rem
& + label::before,
& + label::after
display: block
@ -130,20 +134,22 @@ legend
content:''
border-radius: 1rem
& + label::before
bottom: 0
bottom: .3rem
left: 0
background-color: var(--color-green)
width: 1rem
height: 1rem
& + label::after
bottom: 3px
bottom: calc(3px + .3rem)
left: 3px
width: calc(1rem - 6px)
height: calc(1rem - 6px)
&:checked + label
text-shadow: -0.06ex 0 0 currentColor, 0.06ex 0 0 currentColor
&:checked + label::before
background-color: white
&:checked + label::after
background-color: var(--color-green)
&:checked + label::after
background-color: white
.main
height: 100%
@ -163,6 +169,9 @@ legend
max-width: 100%
min-width: 280px
@media (max-height: 600px)
margin: 1rem auto
h2
font-size: 2rem

View File

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

View File

@ -123,6 +123,7 @@ function getTranslation(translations, key) {
</ul>
</header>
<main>
<img src="/homepage.webp" class="homeImage" />
<div class="container" v-if="scores">
<ul>
<template v-for="(score, index) in scores" :key="score.id">
@ -177,14 +178,27 @@ header
main
width: 100%
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: calc(100% + 2rem)
padding: 0
max-width: 600px
object-fit: cover
margin-left: -1rem
margin: 0 auto
.container
display: flex
justify-content: center
align-items: center
overflow: hidden
background-color: var(--color-background)
padding: 1rem
.container
ul
margin: 0
padding: 0
@ -193,6 +207,7 @@ main
flex-wrap: wrap
justify-content: center
max-width: 404px
border: 1px solid var(--color-green)
li
height: 202px
@ -206,6 +221,7 @@ main
a
font-size: 2rem
line-height: 2rem
color: var(--color-green)
display: block
width: 100%
@ -215,4 +231,5 @@ main
justify-content: center
text-align: center
padding: 1rem
text-decoration: none
</style>