import React, { Component } from "react";
import { Redirect } from "react-router-dom";
import {
Collapse,
Container,
Row,
Col,
Input,
Label,
InputGroup,
InputGroupAddon,
Button,
Card,
CardBody
} from "reactstrap";
import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { resolve } from "url";
import HelpButton from "../form/HelpButton";
import {
arrayMove,
sortableContainer,
sortableElement,
sortableHandle
} from "react-sortable-hoc";
import ButtonWithConfirm from "../form/ButtonWithConfirm";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faPlus,
faTrashAlt,
faCheck,
faCogs
} from "@fortawesome/free-solid-svg-icons";
import { grades } from "../../Util";
import { ReactMultiEmail, isEmail } from "react-multi-email";
import "react-multi-email/style.css";
import { AppContext } from "../../AppContext";
const DragHandle = sortableHandle(({ children }) => (
{children}
));
const SortableCandidate = sortableElement(({ candidate, sortIndex, form }) => (
{sortIndex + 1}
form.editCandidateLabel(event, sortIndex)}
onKeyPress={event =>
form.handleKeypressOnCandidateLabel(event, sortIndex)
}
placeholder="Nom du candidat ou de la proposition ..."
tabIndex={sortIndex + 1}
innerRef={ref => (form.candidateInputs[sortIndex] = ref)}
maxLength="250"
/>
Suppression ?
Êtes-vous sûr de vouloir supprimer{" "}
{candidate.label !== "" ? (
"{candidate.label}"
) : (
la ligne {sortIndex + 1}
)}{" "}
?
form.removeCandidate(sortIndex)}
>
Oui
Non
Saisissez ici le nom de votre candidat ou de votre proposition (250
caractères max.)
));
const SortableCandidatesContainer = sortableContainer(({ items, form }) => {
return (
{items.map((candidate, index) => (
))}
);
});
class CreateElection extends Component {
static contextType = AppContext;
constructor(props) {
super(props);
//default value : start now
const startedAt = new Date();
const startedHour = startedAt.getHours();
//default value : finish in one week
const finishedAt = new Date(startedAt.getTime() + 7 * 24 * 60 * 60 * 1000);
const params = new URLSearchParams(window.location.search);
this.state = {
candidates: [{ label: "" }, { label: "" }],
numCandidatesWithLabel: 0,
title: params.get("title") ? params.get("title") : "",
isVisibleTipsDragAndDropCandidate: true,
numGrades: 7,
successCreate: false,
redirectTo: null,
isAdvancedOptionsOpen: false,
startedDayAt: startedAt.toISOString().substring(0, 10),
finishedDayAt: finishedAt.toISOString().substring(0, 10),
startedTimeAt: Math.floor(startedHour / 2) * 2 + ":00:00",
finishedTimeAt: "23:59:59",
electorEmails: []
};
this.candidateInputs = [];
this.focusInput = React.createRef();
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeTitle = event => {
this.setState({ title: event.target.value });
};
addCandidate = event => {
let candidates = this.state.candidates;
if (candidates.length < 100) {
candidates.push({ label: "" });
this.setState({ candidates: candidates });
}
if (event.type === "keypress") {
setTimeout(() => {
this.candidateInputs[this.state.candidates.length - 1].focus();
}, 250);
}
};
removeCandidate = index => {
let candidates = this.state.candidates;
candidates.splice(index, 1);
if (candidates.length === 0) {
candidates = [{ label: "" }];
}
this.setState({ candidates: candidates });
};
editCandidateLabel = (event, index) => {
let candidates = this.state.candidates;
let numLabels = 0;
candidates[index].label = event.currentTarget.value;
candidates.map((candidate, i) => {
if (candidate.label !== "") {
numLabels++;
}
return candidate.label;
});
this.setState({
candidates: candidates,
numCandidatesWithLabel: numLabels
});
};
handleKeypressOnCandidateLabel = (event, index) => {
if (event.key === "Enter") {
event.preventDefault();
if (index + 1 === this.state.candidates.length) {
this.addCandidate(event);
} else {
this.candidateInputs[index + 1].focus();
}
}
};
onCandidatesSortEnd = ({ oldIndex, newIndex }) => {
let candidates = this.state.candidates;
candidates = arrayMove(candidates, oldIndex, newIndex);
this.setState({ candidates: candidates });
};
handleChangeNumGrades = event => {
this.setState({ numGrades: event.target.value });
};
toggleAdvancedOptions = () => {
this.setState({ isAdvancedOptionsOpen: !this.state.isAdvancedOptionsOpen });
};
handleSubmit() {
const { candidates, title, numGrades } = this.state;
const endpoint = resolve(
this.context.urlServer,
this.context.routesServer.setElection
);
fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
title: title,
candidates: candidates.map(c => c.label),
on_invitation_only: this.state.electorEmails.length > 0,
num_grades: numGrades,
elector_emails: this.state.electorEmails,
started_at: this.state.startedDayAt + " " + this.state.startedTimeAt,
finished_at: this.state.finishedDayAt + " " + this.state.finishedTimeAt,
time_offset: new Date().getTimezoneOffset()
})
})
.then(response => response.json())
.then(result =>
this.setState(state => ({
redirectTo: "/create-success/" + result.id,
successCreate: true
}))
)
.catch(error => error);
}
handleSendWithoutCandidate = () => {
toast.error("Vous devez saisir au moins deux candidats !", {
position: toast.POSITION.TOP_CENTER
});
};
formatDate = (dateIsoStr, timeIsoStr) => {
let date = new Date(dateIsoStr + "T" + timeIsoStr);
let day = date.getDate();
let month = date.getMonth() + 1; //Months are zero based
let year = date.getFullYear();
let hours = date.getHours();
let minutes = date.getMinutes();
if (month < 10) {
month = "0" + month;
}
if (day < 10) {
day = "0" + day;
}
if (hours < 10) {
hours = "0" + hours;
}
if (minutes < 10) {
minutes = "0" + minutes;
}
let hoursString = hours + "h" + minutes;
if (hoursString === "23h59") {
hoursString = "minuit";
}
return day + "/" + month + "/" + year + " à " + hoursString;
};
render() {
const { successCreate, redirectTo } = this.state;
const { electorEmails } = this.state;
if (successCreate) return ;
return (
);
}
}
export default CreateElection;