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(), }; } handleErrors = response => { if (!response.ok) { response.json().then(response => { console.log(response); const {t} = this.props; toast.error(errorMessage(response, t)); // this.setState(state => ({ // redirectTo: "/unknown-election/" + encodeURIComponent(response) // })); }); 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(state => ({ 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, electionGrades: i18nGrades().slice(0, numGrades), })); 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(result => this.setState({redirectTo: '/vote-success/' + electionSlug}), ) .catch(error => error); }; render() { const {t} = this.props; const {redirectTo, candidates, electionGrades} = this.state; const offsetGrade = i18nGrades().length-this.state.numGrades; if (redirectTo) { return ; } return (

{this.state.title}

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

{this.state.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);