pull/84/head
jimmys-box 2 years ago
commit e95a5684ba

@ -1,35 +0,0 @@
{
"env": {
"browser": true,
"es6": true,
"node": true,
"commonjs": true
},
"parser": "babel-eslint",
"extends": [
"eslint:recommended",
"plugin:react/recommended"
],
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": [
"react"
],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"no-console": "off"
}
}

@ -0,0 +1,3 @@
{
"extends": "next"
}

@ -1,166 +1,163 @@
import React from 'react';
import plotly from 'plotly.js/dist/plotly';
import createPlotComponent from 'react-plotly.js/factory';
import LoadingScreen from "./LoadingScreen";
// import Plot from 'react-plotly.js';
function Bulles (props) {
function Bulles(props) {
// récupération des résultats de l'élection et stockage en tableau
const votesBrut = (Object.values(props))[0];
// récupération des résultats de l'élection et stockage en tableau
const votesBrut = (Object.values(props))[0];
// déclaration et initialisation des mentions et couleurs
const mentionsBrut = ['Passable', 'Assez bien', 'Bien', 'Très bien', 'Excellent'];
const couleursBrut = ['#BB9C42', '#AABA44', '#DCDF44', '#B3D849', '#61AD45'];
// déclaration et initialisation des mentions et couleurs
const mentionsBrut = ['Passable', 'Assez bien', 'Bien', 'Très bien', 'Excellent'];
const couleursBrut = ['#BB9C42', '#AABA44', '#DCDF44', '#B3D849', '#61AD45'];
//----------- Traitement des données -----------//
//----------- Traitement des données -----------//
// fonction d'inversement des éléments de tableau
function inverse(obj){
// fonction d'inversement des éléments de tableau
function inverse(obj) {
var retobj = {};
for(var key in obj){
for (var key in obj) {
retobj[obj[key]] = key;
}
return retobj;
}
// fonction de réduction d'amplitude permettant de conserver une représentation ordinale du nombre de votes sans décalage visuel trop important
/*
Pattern de calcul :
Soient Ai, Bi, Ci, Di, Ei les nombres de votes initiaux fournis dans le tableau classé par ordre mélioratif de mention (de Passable à Excellent). Il vient :
A = 1
B = <{[1 + (Bi/Ai)] / 40} * A>
C = <{[1 + (Ci/Bi)] / 40} * B>
D = <{[1 + (Di/Ci)] / 40} * C>
E = <{[1 + (Ei/Di)] / 40} * D>
*/
function redAmpli(tab) {
// fonction de réduction d'amplitude permettant de conserver une représentation ordinale du nombre de votes sans décalage visuel trop important
/*
Pattern de calcul :
Soient Ai, Bi, Ci, Di, Ei les nombres de votes initiaux fournis dans le tableau classé par ordre mélioratif de mention (de Passable à Excellent). Il vient :
A = 1
B = <{[1 + (Bi/Ai)] / 40} * A>
C = <{[1 + (Ci/Bi)] / 40} * B>
D = <{[1 + (Di/Ci)] / 40} * C>
E = <{[1 + (Ei/Di)] / 40} * D>
*/
function redAmpli(tab) {
var nvTab = [];
nvTab[0] = 100;
for(i = 1; i < tab.length; i++) {
nvTab[i] = ( (1 + ((tab[i]/tab[(i-1)]) / 40 ) ) * nvTab[(i-1)]);
for (i = 1; i < tab.length; i++) {
nvTab[i] = ((1 + ((tab[i] / tab[(i - 1)]) / 40)) * nvTab[(i - 1)]);
}
return nvTab;
}
}
// déclaration de l'objet votes-mention et votes-couleur
var votesMentionNonOrdonnes = {};
var votesCouleurNonOrdonnes = {};
// déclaration de l'objet votes-mention et votes-couleur
var votesMentionNonOrdonnes = {};
var votesCouleurNonOrdonnes = {};
// initialisation votes-mention ordonnés croissants
for (var i = 0; i < mentionsBrut.length; i++) {
votesMentionNonOrdonnes[votesBrut[i]] = mentionsBrut[i];
votesCouleurNonOrdonnes[votesBrut[i]] = couleursBrut[i];
}
// initialisation votes-mention ordonnés croissants
for (var i = 0; i < mentionsBrut.length; i++) {
votesMentionNonOrdonnes[votesBrut[i]] = mentionsBrut[i];
votesCouleurNonOrdonnes[votesBrut[i]] = couleursBrut[i];
}
// déclaration des mentions-votes par ordre croissant
var votesMentionOrdonnes = inverse(votesMentionNonOrdonnes);
var votesCouleurOrdonnes = inverse(votesCouleurNonOrdonnes);
// déclaration des mentions-votes par ordre croissant
var votesMentionOrdonnes = inverse(votesMentionNonOrdonnes);
var votesCouleurOrdonnes = inverse(votesCouleurNonOrdonnes);
// vérification du nombre de votes classés par ordre croissant et passés initialement en propriétés au composant
console.log("Les données transmises au composant concernant le nombre de votes par mention sont : ");
console.log(votesBrut);
// vérification du nombre de votes classés par ordre croissant et passés initialement en propriétés au composant
console.log("Les données transmises au composant concernant le nombre de votes par mention sont : ");
console.log(votesBrut);
// vérification des mentions destinées à être associées aux votes et ordonnées initialement par ordre mélioratif
console.log("Les mentions des votes sont classées initialement par ordre mélioratif de la façon suivante :");
console.log(mentionsBrut);
// vérification des mentions destinées à être associées aux votes et ordonnées initialement par ordre mélioratif
console.log("Les mentions des votes sont classées initialement par ordre mélioratif de la façon suivante :");
console.log(mentionsBrut);
// vérification du nombre de votes classés par ordre croissant
console.log("Les mentions-votes classées par ordre croissant de votes sont : ");
console.log(votesMentionOrdonnes);
// vérification du nombre de votes classés par ordre croissant
console.log("Les mentions-votes classées par ordre croissant de votes sont : ");
console.log(votesMentionOrdonnes);
// séparation des mentions et des votes
const mentions = Object.keys(votesMentionOrdonnes);
const votes = Object.values(votesMentionOrdonnes);
const couleurs = Object.keys(votesCouleurOrdonnes);
// séparation des mentions et des votes
const mentions = Object.keys(votesMentionOrdonnes);
const votes = Object.values(votesMentionOrdonnes);
const couleurs = Object.keys(votesCouleurOrdonnes);
// vérification des mentions et des votes prêts à être traités pour la représentation graphique
console.log('La liste des mentions issue du classement par ordre croissant de votes est :');
console.log(mentions);
console.log('La liste du nombre de votes correspondant, classée par ordre croissant, est :');
console.log(votes);
// vérification des mentions et des votes prêts à être traités pour la représentation graphique
console.log('La liste des mentions issue du classement par ordre croissant de votes est :');
console.log(mentions);
console.log('La liste du nombre de votes correspondant, classée par ordre croissant, est :');
console.log(votes);
// déclaration et initialisation des rayons de bulle pour la représentation graphique
var rayons = [];
rayons = redAmpli(votes)
// déclaration et initialisation des rayons de bulle pour la représentation graphique
var rayons = [];
rayons = redAmpli(votes)
// vérification des rayons
console.log('La liste des rayons à représenter graphiquement est la suivante :');
console.log(rayons);
// vérification des rayons
console.log('La liste des rayons à représenter graphiquement est la suivante :');
console.log(rayons);
// déclaration et initialisation des textes des bulles
const texteBulle1 = (mentions[0] + "<br>" + votes[0] + " votes").toString();
const texteBulle2 = (mentions[1] + "<br>" + votes[1] + " votes").toString();
const texteBulle3 = (mentions[2] + "<br>" + votes[2] + " votes").toString();
const texteBulle4 = (mentions[3] + "<br>" + votes[3] + " votes").toString();
const texteBulle5 = (mentions[4] + "<br>" + votes[4] + " votes").toString();
// déclaration et initialisation des textes des bulles
const texteBulle1 = (mentions[0] + "<br>" + votes[0] + " votes").toString();
const texteBulle2 = (mentions[1] + "<br>" + votes[1] + " votes").toString();
const texteBulle3 = (mentions[2] + "<br>" + votes[2] + " votes").toString();
const texteBulle4 = (mentions[3] + "<br>" + votes[3] + " votes").toString();
const texteBulle5 = (mentions[4] + "<br>" + votes[4] + " votes").toString();
// déclaration et initialisation d'une instance de graphique en bulles
// const Plot = createPlotComponent(plotly);
const Plot = require('react-plotly.js').default;
//---------------------------------------------//
//---------------------------------------------//
//----------- Affichage des données -----------//
const [loading, setLoading] = React.useState(true);
React.useEffect(() =>{
setTimeout(() => setLoading(false), 3000);
//----------- Affichage des données -----------//
const [loading, setLoading] = React.useState(true);
React.useEffect(() => {
setTimeout(() => setLoading(false), 3000);
})
return (
// <div>
// {!loading ? (
// <React.Fragment>
<Plot
data={[
{
x: [0.7, 0.6, 0.5, 0.6, 0.7],
y: [0.3, 0.4, 0.5, 0.6, 0.5],
hovertemplate:
'<b>%{text}</b>' +
'<extra></extra>',
text: [texteBulle1, texteBulle2, texteBulle3, texteBulle4, texteBulle5],
showlegend: false,
mode: 'markers',
marker: {
color: [couleurs[0], couleurs[1], couleurs[2], couleurs[3], couleurs[4]],
size: rayons
}
}
]}
layout={ {
width: 600,
height: 600,
title: 'Nombre de voix par candidat',
xaxis: {
showgrid: false,
showticklabels: false,
showline: false,
zeroline: false,
range: [0, 1]
},
yaxis: {
showgrid: false,
showticklabels: false,
showline: false,
zeroline: false,
range: [0, 1]
}
} }
config={{
displayModeBar: false // this is the line that hides the bar.
}}
/>
// </React.Fragment>
// ) : (
// <LoadingScreen />
// )}
// </div>
)
return (
<div>TBD</div>
// <div>
// {!loading ? (
// <React.Fragment>
// <Plot
// data={[
// {
// x: [0.7, 0.6, 0.5, 0.6, 0.7],
// y: [0.3, 0.4, 0.5, 0.6, 0.5],
// hovertemplate:
// '<b>%{text}</b>' +
// '<extra></extra>',
// text: [texteBulle1, texteBulle2, texteBulle3, texteBulle4, texteBulle5],
// showlegend: false,
// mode: 'markers',
// marker: {
// color: [couleurs[0], couleurs[1], couleurs[2], couleurs[3], couleurs[4]],
// size: rayons
// }
// }
// ]}
// layout={{
// width: 600,
// height: 600,
// title: 'Nombre de voix par candidat',
// xaxis: {
// showgrid: false,
// showticklabels: false,
// showline: false,
// zeroline: false,
// range: [0, 1]
// },
// yaxis: {
// showgrid: false,
// showticklabels: false,
// showline: false,
// zeroline: false,
// range: [0, 1]
// }
// }}
// config={{
// displayModeBar: false // this is the line that hides the bar.
// }}
// />
// </React.Fragment>
// ) : (
// <LoadingScreen />
// )}
// </div>
)
}
export default Bulles;
export default Bulles;

@ -1,53 +1,54 @@
import React, { useEffect, useRef, useState } from "react";
import React, {useEffect, useRef, useState} from "react";
import ReactDOM from "react-dom";
import styled from "styled-components";
const Modal = ({ show, onClose, children, title }) => {
const handleCloseClick = (e) => {
e.preventDefault();
onClose();
};
const modalContent = show ? (
<StyledModalOverlay>
<StyledModal>
<StyledModalHeader>
<a href="#" onClick={handleCloseClick}>
x
</a>
</StyledModalHeader>
{title && <StyledModalTitle>{title}</StyledModalTitle>}
<StyledModalBody>{children}</StyledModalBody>
</StyledModal>
</StyledModalOverlay>
) : null;
return (
modalContent
);
const Modal = ({show, onClose, children, title}) => {
const handleCloseClick = (e) => {
e.preventDefault();
onClose();
};
const StyledModalBody = styled.div`
const modalContent = show ? (
<StyledModalOverlay>
<StyledModal>
<StyledModalHeader>
<a href="#" onClick={handleCloseClick}>
x
</a>
</StyledModalHeader>
{title && <StyledModalTitle>{title}</StyledModalTitle>}
<StyledModalBody>{children}</StyledModalBody>
</StyledModal>
</StyledModalOverlay>
) : null;
return (
modalContent
);
};
const StyledModalBody = styled.div`
padding-top: 10px;
`;
const StyledModalHeader = styled.div`
const StyledModalHeader = styled.div`
display: flex;
justify-content: flex-end;
font-size: 25px;
`;
const StyledModal = styled.div`
const StyledModal = styled.div`
background: white;
width: 500px;
height: 600px;
border-radius: 15px;
padding: 15px;
`;
const StyledModalOverlay = styled.div`
const StyledModalTitle = styled.div
const StyledModalOverlay = styled.div`
position: absolute;
top: 0;
left: 0;
@ -58,5 +59,5 @@ const Modal = ({ show, onClose, children, title }) => {
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
`;
export default Modal;
export default Modal;

@ -1,37 +1,37 @@
import { useState } from "react";
import {useState} from "react";
export default function AddPicture(props) {
const [image, setImage] = useState(null);
const [createObjectURL, setCreateObjectURL] = useState(null);
const uploadToClient = (event) => {
if (event.target.files && event.target.files[0]) {
const i = event.target.files[0];
setImage(i);
setCreateObjectURL(URL.createObjectURL(i));
}
};
return (
<div className="ajout-avatar">
<div>
<div className="avatar-placeholer">
<img src={createObjectURL} />
</div>
</div>
<div className="avatar-text">
<h4>Photo <span> (facultatif)</span></h4>
<p>Importer une photo.<br />format : jpg, png, pdf</p>
<div className="btn-ajout-avatar">
<input type="file" name="myImage" id="myImage" onChange={uploadToClient} />
<label className="inputfile" for="myImage">Importer une photo</label>
</div>
</div>
const [image, setImage] = useState(null);
const [createObjectURL, setCreateObjectURL] = useState(null);
const uploadToClient = (event) => {
if (event.target.files && event.target.files[0]) {
const i = event.target.files[0];
setImage(i);
setCreateObjectURL(URL.createObjectURL(i));
}
};
return (
<div className="ajout-avatar">
<div>
<div className="avatar-placeholer">
<img src={createObjectURL} />
</div>
</div>
<div className="avatar-text">
<h4>Photo <span> (facultatif)</span></h4>
<p>Importer une photo.<br />format : jpg, png, pdf</p>
<div className="btn-ajout-avatar">
<input type="file" name="myImage" id="myImage" onChange={uploadToClient} />
<label className="inputfile" htmlFor="myImage">Importer une photo</label>ddpi
</div>
</div>
</div>
);
}
);
}

@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'
import {useState, useEffect} from 'react'
import ButtonWithConfirm from "./ButtonWithConfirm";
import TrashButton from "./TrashButton";
import {
@ -10,7 +10,7 @@ import {
InputGroupAddon,
Button, Modal, ModalHeader, ModalBody, ModalFooter
} from "reactstrap";
import { useTranslation } from "react-i18next";
import {useTranslation} from "react-i18next";
import {
sortableHandle
} from "react-sortable-hoc";
@ -19,29 +19,30 @@ import AddPicture from "@components/form/AddPicture";
import {
faPlus, faCogs, faCheck, faTrash
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const DragHandle = sortableHandle(({ children }) => (
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
const DragHandle = sortableHandle(({children}) => (
<span className="input-group-text indexNumber">{children}</span>
));
const CandidateField = ({ avatar, label, description, candIndex, onDelete, onAdd, ...inputProps }) => {
const { t } = useTranslation();
const CandidateField = ({avatar, label, description, candIndex, onDelete, onAdd, ...inputProps}) => {
const {t} = useTranslation();
const [visibled, setVisibility] = useState(false);
const toggle = () => setVisibility(!visibled)
const [selected, setSelectedState] = useState(false);
const [className , setClassName] = useState("none");
const [trashIcon , setTrashIcon] = useState("none");
const [plusIcon , setPlusIcon] = useState("none");
const [className, setClassName] = useState("none");
const [trashIcon, setTrashIcon] = useState("none");
const [plusIcon, setPlusIcon] = useState("none");
const addCandidate = () => {
toggle();
onAdd();
onAdd();
}
useEffect(() => {
setClassName("candidateButton " + (selected ? "candidateAdded" : ""))
<<<<<<< HEAD
}, [selected] );
useEffect(() => {
setPlusIcon("mr-2 cursorPointer " + (selected ? "trashIcon" : ""))
@ -68,18 +69,51 @@ const deleteFunction = () => {
setCreateObjectURL(URL.createObjectURL(i));
}
};
=======
}, [selected]);
useEffect(() => {
setPlusIcon("mr-2 cursorPointer " + (selected ? "trashIcon" : ""))
}, [selected]);
useEffect(() => {
setTrashIcon("trashIcon " + (selected ? "displayTrash" : ""))
}, [selected]);
const addFunction = () => {
addCandidate();
setSelectedState(!selected);
}
const [image, setImage] = useState(null);
const [createObjectURL, setCreateObjectURL] = useState(null);
const uploadToClient = (event) => {
if (event.target.files && event.target.files[0]) {
const i = event.target.files[0];
setImage(i);
setCreateObjectURL(URL.createObjectURL(i));
>>>>>>> 102b62636454308245aa839e42a8387359101d1d
}
};
return (
<Row className="rowNoMargin">
<div className={className}>
<div className="avatarThumb">
<img src={createObjectURL} alt="" />
<input placeholder="Ajouter un candidat" className="candidate-placeholder ml-2" value={label}/>
</div>
<FontAwesomeIcon onClick={toggle} icon={faPlus} className={plusIcon} />
<div className={trashIcon}><TrashButton label={label} onDelete={onDelete}/></div>
<input placeholder="Ajouter un candidat" className="candidate-placeholder ml-2" value={label} />
</div>
<FontAwesomeIcon onClick={toggle} icon={faPlus} className={plusIcon} />
<div className={trashIcon}><TrashButton label={label} onDelete={onDelete} /></div>
</div>
<Modal
@ -108,21 +142,21 @@ const deleteFunction = () => {
<h6>Ajouter un participant</h6>
<p>Ajoutez une photo, le nom et une description au candidat.</p>
<div className="ajout-avatar">
<div>
<div className="avatar-placeholer">
<img src={createObjectURL} />
</div>
</div>
<div className="avatar-text">
<h4>Photo <span> (facultatif)</span></h4>
<p>Importer une photo.<br />format : jpg, png, pdf</p>
<div className="btn-ajout-avatar">
<input type="file" name="myImage" id="myImage" value={avatar} onChange={uploadToClient} />
<label className="inputfile" for="myImage">Importer une photo</label>
</div>
</div>
</div>
<div>
<div className="avatar-placeholer">
<img src={createObjectURL} />
</div>
</div>
<div className="avatar-text">
<h4>Photo <span> (facultatif)</span></h4>
<p>Importer une photo.<br />format : jpg, png, pdf</p>
<div className="btn-ajout-avatar">
<input type="file" name="myImage" id="myImage" value={avatar} onChange={uploadToClient} />
<label className="inputfile" htmlFor="myImage">Importer une photo</label>
</div>
</div>
</div>
<img src="/avatar.svg" />
</DragHandle>
</InputGroupAddon>
@ -148,8 +182,13 @@ const deleteFunction = () => {
autoFocus
/>
<Row className="removeAddButtons">
<<<<<<< HEAD
<ButtonWithConfirm className="removeButton" label={label} onDelete={deleteFunction}/>
=======
<ButtonWithConfirm className="removeButton" label={label} onDelete={onDelete, toggle} />
>>>>>>> 102b62636454308245aa839e42a8387359101d1d
<Button className="addButton" label={label} onClick={addFunction}>
<FontAwesomeIcon icon={faPlus} />
<span>Ajouter</span>

@ -1,18 +1,18 @@
import React from 'react';
import plotly from 'plotly.js/dist/plotly';
import createPlotComponent from 'react-plotly.js/factory';
// import Plot from 'react-plotly.js';
// const Plot = createPlotComponent(plotly);
const Plot = require('react-plotly.js').default;
export default () => (
<Plot
data={[
{
type: 'bar',
x: ['Taubira', 'Hidalgo', 'Mélenchon'],
y: [29,150,85]
}
]}
layout={ { width: 1000, height: 500, title: 'Nombre de voix par candidat' } }
/>
const plot = () => (
<div></div>
// <Plot
// data={[
// {
// type: 'bar',
// x: ['Taubira', 'Hidalgo', 'Mélenchon'],
// y: [29, 150, 85]
// }
// ]}
// layout={{width: 1000, height: 500, title: 'Nombre de voix par candidat'}}
// />
)
export default plot;

@ -1,9 +1,10 @@
module.exports = {
i18n: {
defaultLocale: "fr",
locales: ["en", "fr", "de", "es", "ru"],
ns: ["resource", "common", "error"],
defaultNS: "resource",
fallbackNS: ["common", "error"],
},
};
i18n: {
defaultLocale: "fr",
locales: ["en", "fr"],
},
react: {
useSuspense: false,
wait: true
}
};

5540
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -4,8 +4,9 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build && next export",
"build": "next build",
"start": "next start",
"lint": "next lint",
"export": "next export"
},
"dependencies": {
@ -17,6 +18,7 @@
"@svgr/webpack": "^6.2.1",
"@weknow/react-bubble-chart-d3": "^1.0.12",
"array-move": "^3.0.1",
"babel-eslint": "^10.1.0",
"bootstrap": "^4.6.0",
"bootstrap-scss": "^4.6.0",
"clipboard": "^2.0.10",
@ -41,8 +43,6 @@
"mailgun.js": "^3.3.2",
"next": "^12.1.0",
"next-i18next": "^8.2.0",
"plotly.js": "^2.8.3",
"plotly.js-dist": "^2.8.3",
"query-string": "^7.0.0",
"ramda": "^0.27.2",
"react": "^17.0.2",
@ -62,5 +62,10 @@
"reactstrap": "^8.9.0",
"sass": "^1.32.13",
"styled-components": "^5.3.3"
},
"devDependencies": {
"eslint": "^8.11.0",
"eslint-config-next": "12.1.0",
"eslint-plugin-react": "^7.29.3"
}
}

@ -1,15 +1,15 @@
import { useState } from "react";
import {useState} from "react";
import Head from "next/head";
import Link from "next/link";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useTranslation } from "next-i18next";
import { Container, Row, Col, Button, Input } from "reactstrap";
import {serverSideTranslations} from "next-i18next/serverSideTranslations";
import {useTranslation} from "next-i18next";
import {Container, Row, Col, Button, Input} from "reactstrap";
import config from "../next-i18next.config.js";
import Footer from '@components/layouts/Footer';
import VoteBallot from './vote/[pid]/[[...tid]]';
import CandidatesField from '../components/form/CandidatesField';
export const getStaticProps = async ({ locale }) => ({
export const getStaticProps = async ({locale}) => ({
props: {
...(await serverSideTranslations(locale, [], config)),
},
@ -17,9 +17,9 @@ export const getStaticProps = async ({ locale }) => ({
const Home = () => {
const [title, setTitle] = useState(null);
const { t } = useTranslation();
const {t} = useTranslation();
return (
<Container className="homePage">
<section>
<form className="sectionOneHomeForm" autoComplete="off">
@ -55,6 +55,7 @@ const Home = () => {
</Row>
<Row>
<<<<<<< HEAD
<Link href={{ pathname: "/new/", query: { title: title } }}>
<Button
type="submit"
@ -63,6 +64,16 @@ const Home = () => {
{t("resource.start")}
<img src="/arrow-white.svg" className="m-2" />
</Button>
=======
<Link href={{pathname: "/new/", query: {title: title}}}>
<Button
type="submit"
className="btn btn-block btn-secondary mt-2"
>
{t("resource.start")}
<img src="/arrow-white.svg" className="mr-2" />
</Button>
>>>>>>> 102b62636454308245aa839e42a8387359101d1d
</Link>
</Row>
<Row className="noAds">
@ -75,7 +86,7 @@ const Home = () => {
</Row>
</form>
</section>
</section>
<section className="sectionTwoHome">
<Row className="sectionTwoRowOne">
<Col className="sectionTwoRowOneCol">
@ -96,7 +107,7 @@ const Home = () => {
className="d-block mx-auto"
/>
<h4>Gratuit</h4>
<p>Envoyez des invitations par courriel sans limite d'envoi</p>
<p>Envoyez des invitations par courriel sans limite d`&apos;`envoi</p>
</Col>
<Col className="sectionTwoRowOneCol">
<img
@ -110,9 +121,9 @@ const Home = () => {
</Col>
</Row>
<Row className="sectionTwoRowTwo">
<Row className="sectionTwoHomeImage">
<Row className="sectionTwoHomeImage">
<img src="/vote.svg" />
</Row>
</Row>
<Row className="sectionTwoRowTwoCol">
<h3 className="col-md-7">Une expérience de vote démocratique et intuitive</h3>
</Row>
@ -131,7 +142,7 @@ const Home = () => {
className="btn btn-block btn-secondary btn-sectionTwoHome"
>
Découvrez le jugement majoritaire
<img src="/arrow-white.svg" className="mr-2" />
<img src="/arrow-white.svg" className="mr-2" />
</Button>
</Row>
</Row>
@ -139,7 +150,7 @@ const Home = () => {
<p>Partagez lapplication Mieux voter</p>
<Link href="https://www.facebook.com/mieuxvoter.fr/"><img src="/facebook.svg" className="mr-2" /></Link>
<Link href="https://twitter.com/mieux_voter"><img src="/twitter.svg" className="mr-2" /></Link>
</Row>
</Row>
</section>
<Footer />
</Container>

@ -1,8 +1,8 @@
import { useState, useEffect } from "react";
import {useState, useEffect} from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import {useRouter} from "next/router";
import {useTranslation} from "next-i18next";
import {serverSideTranslations} from "next-i18next/serverSideTranslations";
import {
Collapse,
Container,
@ -17,12 +17,12 @@ import {
CardBody,
Modal, ModalHeader, ModalBody, ModalFooter, CustomInput
} from "reactstrap";
import { ReactMultiEmail, isEmail } from "react-multi-email";
import {ReactMultiEmail, isEmail} from "react-multi-email";
import "react-multi-email/style.css";
import { toast, ToastContainer } from "react-toastify";
import {toast, ToastContainer} from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import queryString from "query-string";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {
faPlus,
faTrashAlt,
@ -32,14 +32,14 @@ import {
faArrowLeft,
faExclamationCircle
} from "@fortawesome/free-solid-svg-icons";
import { useAppContext } from "@services/context";
import { createElection } from "@services/api";
import { translateGrades } from "@services/grades";
import {useAppContext} from "@services/context";
import {createElection} from "@services/api";
import {translateGrades} from "@services/grades";
import HelpButton from "@components/form/HelpButton";
import Loader from "@components/wait";
import CandidatesField from "@components/form/CandidatesField";
import ConfirmModal from "@components/form/ConfirmModal";
import config from "../../next-i18next.config.js";
// import config from "../../next-i18next.config.js";
// Error messages
@ -80,19 +80,19 @@ const displayClockOptions = () =>
</option>
));
export const getStaticProps = async ({ locale }) => ({
export const getStaticProps = async ({locale}) => ({
props: {
...(await serverSideTranslations(locale, [], config)),
...(await serverSideTranslations(locale, [])),
},
});
const CreateElection = (props) => {
const { t } = useTranslation();
const {t} = useTranslation();
// default value : start at the last hour
const now = new Date();
const [title, setTitle] = useState("");
const [candidates, setCandidates] = useState([{ label: "" }, { description: "" }]);
const [candidates, setCandidates] = useState([{label: ""}, {description: ""}]);
const [numGrades, setNumGrades] = useState(5);
const [waiting, setWaiting] = useState(false);
const [isAdvancedOptionsOpen, setAdvancedOptionsOpen] = useState(false);
@ -113,7 +113,7 @@ const CreateElection = (props) => {
useEffect(() => {
if (!router.isReady) return;
const { title: urlTitle } = router.query;
const {title: urlTitle} = router.query;
setTitle(urlTitle || "");
}, [router.isReady]);
@ -138,14 +138,14 @@ const CreateElection = (props) => {
const addCandidate = () => {
if (candidates.length < 1000) {
candidates.push({ label: "" });
candidates.push({label: ""});
setCandidates(candidates);
}
};
const checkFields = () => {
if (!candidates) {
return { ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR };
return {ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR};
}
let numCandidates = 0;
@ -153,14 +153,14 @@ const CreateElection = (props) => {
if (c.label !== "") numCandidates += 1;
});
if (numCandidates < 2) {
return { ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR };
return {ok: false, msg: AT_LEAST_2_CANDIDATES_ERROR};
}
if (!title || title === "") {
return { ok: false, msg: NO_TITLE_ERROR };
return {ok: false, msg: NO_TITLE_ERROR};
}
return { ok: true, msg: "OK" };
return {ok: true, msg: "OK"};
};
const handleSubmit = () => {
@ -472,8 +472,8 @@ const CreateElection = (props) => {
)}
</div></form>
</Container >
);
};

@ -1,29 +1,28 @@
import dynamic from 'next/dynamic';
import plotly from 'plotly.js/dist/plotly';
import createPlotComponent from 'react-plotly.js/factory';
import React, { Component } from 'react';
//import Plot from 'react-plotly.js';
// import Plot from 'react-plotly.js';
import React, {Component} from 'react';
class BarChart extends Component {
render() {
return (
<div>
<Plot
data={[
{
type: 'bar',
x: ['Taubira', 'Hidalgo', 'Mélenchon'],
y: [29,150,85]
}
]}
layout={ { width: 1000, height: 500, title: 'Nombre de voix par candidat' } }
config={{
displayModeBar: false // this is the line that hides the bar.
}}
/>
</div>
)
};
render() {
return (
<div>
</div>
)
};
}
export default BarChart;
export default BarChart;
// <Plot
// data={[
// {
// type: 'bar',
// x: ['Taubira', 'Hidalgo', 'Mélenchon'],
// y: [29, 150, 85]
// }
// ]}
// layout={{width: 1000, height: 500, title: 'Nombre de voix par candidat'}}
// config={{
// displayModeBar: false // this is the line that hides the bar.
// }}
// />

@ -1,29 +1,29 @@
import Head from "next/head";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faChevronRight } from "@fortawesome/free-solid-svg-icons";
import { Col, Container, Row, Button } from "reactstrap";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faChevronRight} from "@fortawesome/free-solid-svg-icons";
import {Col, Container, Row, Button} from "reactstrap";
import Link from "next/link";
import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import PaypalNoLogo from "@components/banner/PaypalNoLogo";
import {useTranslation} from "next-i18next";
import {serverSideTranslations} from "next-i18next/serverSideTranslations";
// import PaypalNoLogo from "@components/banner/PaypalNoLogo";
import Gform from "@components/banner/Gform";
import Error from "@components/Error";
import { getDetails, apiErrors } from "@services/api";
import {getDetails, apiErrors} from "@services/api";
import config from "../../../next-i18next.config.js";
import { motion } from 'framer-motion/dist/framer-motion';
import {motion} from 'framer-motion';
export async function getServerSideProps({ query: { pid }, locale }) {
export async function getServerSideProps({query: {pid}, locale}) {
const [details, translations] = await Promise.all([
getDetails(pid),
serverSideTranslations(locale, [], config),
]);
if (typeof details === "string" || details instanceof String) {
return { props: { err: res.slice(1, -1), ...translations } };
return {props: {err: res.slice(1, -1), ...translations}};
}
if (!details.candidates || !Array.isArray(details.candidates)) {
return { props: { err: "Unknown error", ...translations } };
return {props: {err: "Unknown error", ...translations}};
}
return {
@ -31,7 +31,7 @@ export async function getServerSideProps({ query: { pid }, locale }) {
...translations,
invitationOnly: details.on_invitation_only,
restrictResults: details.restrict_results,
candidates: details.candidates.map((name, i) => ({ id: i, label: name })),
candidates: details.candidates.map((name, i) => ({id: i, label: name})),
title: details.title,
numGrades: details.num_grades,
pid: pid,
@ -39,8 +39,8 @@ export async function getServerSideProps({ query: { pid }, locale }) {
};
}
const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
const { t } = useTranslation();
const VoteSuccess = ({title, invitationOnly, pid, err}) => {
const {t} = useTranslation();
if (err && err !== "") {
return <Error value={apiErrors(err, t)} />;
}
@ -60,8 +60,8 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
<motion.div
className="mx-auto"
initial={{ scale: 1, paddingBottom: '200px' }}
animate={{ scale: 0.5, paddingBottom: '0px' }}
initial={{scale: 1, paddingBottom: '200px'}}
animate={{scale: 0.5, paddingBottom: '0px'}}
transition={{
type: "spring",
damping: 100,
@ -71,8 +71,8 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
<Row>
<motion.div
className="main-animation"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
initial={{opacity: 0}}
animate={{opacity: 1}}
transition={{
type: "spring",
damping: 20,
@ -82,8 +82,8 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
<motion.div
className="vote-animation"
initial={{ scale: 0, y: 50 }}
animate={{ scale: 1, y: 0 }}
initial={{scale: 0, y: 50}}
animate={{scale: 1, y: 0}}
transition={{
type: "spring",
stiffness: 260,
@ -95,8 +95,8 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
</motion.div>
<motion.div
className="star-animation"
initial={{ scale: 0 }}
animate={{ scale: 1 }}
initial={{scale: 0}}
animate={{scale: 1}}
transition={{
type: "spring",
damping: 20,
@ -112,8 +112,8 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
<motion.div
className=""
initial={{ scale: 0, opacity: 0, y: 100 }}
animate={{ scale: 1, opacity: 1, y: -70 }}
initial={{scale: 0, opacity: 0, y: 100}}
animate={{scale: 1, opacity: 1, y: -70}}
transition={{
type: "spring",
damping: 100,
@ -150,7 +150,6 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
</Col>
</Row>
<p className="pt-4">{t("Mieux Voter est une association transpartisane et sans but lucratif. En adhérant à lassociation, vous contribuez à financer son fonctionnement et ses activités. ")}</p>
<PaypalNoLogo />
</Col>
</Row>
@ -158,20 +157,20 @@ const VoteSuccess = ({ title, invitationOnly, pid, err }) => {
<Col className="text-center col-md-3 mx-auto my-5 thanksVote">
<h4>{t("resource.thanks")}</h4>
<p>{t("Aidez nous à améliorer lapplication en cliquant ci-dessous")}</p>
<Gform className="btn btn-secondary mt-3 mx-auto" />
<Gform className="btn btn-secondary mt-3 mx-auto" />
</Col>
</Row>
<div className="mx-auto my-5">
<Row className="justify-content-center">
<Link href="https://www.facebook.com/mieuxvoter.fr/"><img src="/facebook.svg" className="mr-2" /></Link>
<p className="m-0">{t("Faites découvrir lapplication a vos amis")}</p>
</Row>
</div>
<div className="mx-auto my-5">
<Row className="justify-content-center">
<Link href="https://www.facebook.com/mieuxvoter.fr/"><img src="/facebook.svg" className="mr-2" /></Link>
<p className="m-0">{t("Faites découvrir lapplication a vos amis")}</p>
</Row>
</div>
</motion.div>

Loading…
Cancel
Save