/* eslint react/prop-types: 0 */ import React, { Component } from "react"; import { Redirect } from "react-router-dom"; import { withTranslation } from "react-i18next"; import { Button, Col, Container, Row } from "reactstrap"; import { toast, ToastContainer } from "react-toastify"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faCheck } from "@fortawesome/free-solid-svg-icons"; import { resolve } from "url"; import { i18nGrades } from "../../Util"; import { AppContext } from "../../AppContext"; import { errorMessage } from "../../Errors"; const shuffle = array => array.sort(() => Math.random() - 0.5); class Vote extends Component { static contextType = AppContext; constructor(props) { super(props); this.state = { candidates: [], title: null, numGrades: 0, ratedCandidates: [], colSizeCandidateLg: 4, colSizeCandidateMd: 6, colSizeCandidateXs: 12, colSizeGradeLg: 1, colSizeGradeMd: 1, colSizeGradeXs: 1, redirectTo: null, electionGrades: i18nGrades(), errorMsg: "" }; } handleErrors = response => { if (!response.ok) { response.json().then(response => { console.log(response); const { t } = this.props; this.setState(() => ({ errorMsg: errorMessage(response, t) })); }); throw Error(response); } return response; }; detailsToState = response => { const numGrades = response.num_grades; const candidates = response.candidates.map((c, i) => ({ id: i, label: c })); shuffle(candidates); const colSizeGradeLg = Math.floor( (12 - this.state.colSizeCandidateLg) / numGrades ); const colSizeGradeMd = Math.floor( (12 - this.state.colSizeCandidateMd) / numGrades ); const colSizeGradeXs = Math.floor( (12 - this.state.colSizeCandidateXs) / numGrades ); this.setState(() => ({ title: response.title, candidates: candidates, numGrades: numGrades, colSizeGradeLg: colSizeGradeLg, colSizeGradeMd: colSizeGradeMd, colSizeGradeXs: colSizeGradeXs, colSizeCandidateLg: 12 - colSizeGradeLg * numGrades > 0 ? 12 - colSizeGradeLg * numGrades : 12, colSizeCandidateMd: 12 - colSizeGradeMd * numGrades > 0 ? 12 - colSizeGradeMd * numGrades : 12, colSizeCandidateXs: 12 - colSizeGradeXs * numGrades > 0 ? 12 - colSizeGradeXs * numGrades : 12 })); return response; }; componentDidMount() { // FIXME we should better handling logs const electionSlug = this.props.match.params.slug; const detailsEndpoint = resolve( this.context.urlServer, this.context.routesServer.getElection.replace( new RegExp(":slug", "g"), electionSlug ) ); fetch(detailsEndpoint) .then(this.handleErrors) .then(response => response.json()) .then(this.detailsToState) .catch(error => console.log(error)); } handleGradeClick = event => { let data = { id: parseInt(event.currentTarget.getAttribute("data-id")), value: parseInt(event.currentTarget.value) }; //remove candidate let ratedCandidates = this.state.ratedCandidates.filter( ratedCandidate => ratedCandidate.id !== data.id ); ratedCandidates.push(data); this.setState({ ratedCandidates }); }; handleSubmitWithoutAllRate = () => { const { t } = this.props; toast.error(t("You have to judge every candidate/proposal!"), { position: toast.POSITION.TOP_CENTER }); }; handleSubmit = event => { event.preventDefault(); const { ratedCandidates } = this.state; const electionSlug = this.props.match.params.slug; const token = this.props.location.search.substr(7); const endpoint = resolve( this.context.urlServer, this.context.routesServer.voteElection ); const gradesById = {}; ratedCandidates.forEach(c => { gradesById[c.id] = c.value; }); const gradesByCandidate = []; Object.keys(gradesById).forEach(id => { gradesByCandidate.push(gradesById[id]); }); const payload = { election: electionSlug, grades_by_candidate: gradesByCandidate }; if (token !== "") { payload["token"] = token; } fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }) .then(this.handleErrors) .then(() => this.setState({ redirectTo: "/vote-success/" + electionSlug }) ) .catch(error => error); }; render() { const { t } = this.props; const { candidates, errorMsg, redirectTo } = this.state; const grades = i18nGrades(); const offsetGrade = grades.length - this.state.numGrades; const electionGrades = grades.slice(0, this.state.numGrades); if (redirectTo) { return ; } if (errorMsg !== "") { return (

{errorMsg}

); } return (

{this.state.title}

 
{electionGrades.map((grade, gradeId) => { return gradeId < this.state.numGrades ? ( {grade.label} ) : null; })}
{candidates.map((candidate, candidateId) => { return (
{candidate.label}

{electionGrades.map((grade, gradeId) => { console.assert(gradeId < this.state.numGrades); const gradeValue = grade.value - offsetGrade; return ( ); })}
); })} {this.state.ratedCandidates.length !== this.state.candidates.length ? ( ) : ( )}
); } } export default withTranslation()(Vote);