You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mvfront-react/components/admin/ConfirmField.tsx

192 lines
5.0 KiB

import { useTranslation } from 'next-i18next';
import { NextRouter, useRouter } from 'next/router';
import { faArrowRight } from '@fortawesome/free-solid-svg-icons';
import { Button, Row, Col, Container } from 'reactstrap';
import TitleField from './Title';
import CandidatesConfirmField from './CandidatesConfirmField';
import AccessResults from './AccessResults';
import LimitDate from './LimitDate';
import Grades from './Grades';
import Private from './Private';
import Order from './Order';
import {
useElection,
ElectionContextInterface,
hasEnoughCandidates,
hasEnoughGrades,
checkName,
canBeFinished,
} from '@services/ElectionContext';
import { createElection, ElectionCreatedPayload } from '@services/api';
import { getUrl, RouteTypes } from '@services/routes';
import { GradeItem, CandidateItem } from '@services/type';
import { sendInviteMails } from '@services/mail';
import { AppTypes, useAppContext } from '@services/context';
import { useEffect } from 'react';
const submitElection = (
election: ElectionContextInterface,
successCallback: Function,
failureCallback: Function,
router: NextRouter
) => {
const candidates = election.candidates
.filter((c) => c.active)
.map((c: CandidateItem) => ({
name: c.name,
description: c.description,
image: c.image,
}));
const grades = election.grades
.filter((c) => c.active)
.map((g: GradeItem, i: number) => ({
name: g.name,
value: election.grades.length - 1 - i,
}));
createElection(
election.name,
candidates,
grades,
election.description,
election.emails.length,
election.hideResults,
election.forceClose,
election.restricted,
election.randomOrder,
async (payload: ElectionCreatedPayload) => {
if (
typeof election.emails !== 'undefined' &&
election.emails.length > 0
) {
if (
typeof payload.invites === 'undefined' ||
payload.invites.length !== election.emails.length
) {
throw Error('Can not send invite emails');
}
const urlVotes = payload.invites.map((token: string) =>
getUrl(RouteTypes.VOTE, router, payload.ref, token)
);
const urlResult = getUrl(RouteTypes.RESULTS, router, payload.ref);
await sendInviteMails(
election.emails,
election.name,
urlVotes,
urlResult,
router
);
}
successCallback(payload);
},
failureCallback
);
};
const ConfirmField = ({ onSubmit, onSuccess, onFailure }) => {
const { t } = useTranslation();
const router = useRouter();
const [election, _] = useElection();
const [app, dispatchApp] = useAppContext();
useEffect(() => {
// move to the head of the page on component loading
window && window.scrollTo(0, 0);
}, []);
const handleSubmit = () => {
if (!checkName(election)) {
dispatchApp({
type: AppTypes.TOAST_ADD,
status: 'error',
message: t('error.uncorrect-name'),
});
return;
}
if (!hasEnoughGrades(election)) {
dispatchApp({
type: AppTypes.TOAST_ADD,
status: 'error',
message: t('error.not-enough-grades'),
});
return;
}
if (!hasEnoughCandidates(election)) {
dispatchApp({
type: AppTypes.TOAST_ADD,
status: 'error',
message: t('error.not-enough-candidates'),
});
return;
}
if (!canBeFinished(election)) {
dispatchApp({
type: AppTypes.TOAST_ADD,
status: 'error',
message: t('error.cant-be-finished'),
});
return;
}
onSubmit();
submitElection(election, onSuccess, onFailure, router);
};
const disabled =
!checkName(election) ||
!hasEnoughCandidates(election) ||
!hasEnoughGrades(election) ||
!canBeFinished(election);
return (
<Container
fluid="xl"
className="my-5 flex-column d-flex justify-content-center"
>
<Container className="px-0 d-md-none mb-5">
<h4>{t('admin.confirm-title')}</h4>
</Container>
<Row>
<Col className="col-lg-3 col-12">
<Container className="py-4 d-none d-md-block">
<h4>{t('common.the-vote')}</h4>
</Container>
<TitleField />
<CandidatesConfirmField />
</Col>
<Col className="col-lg-9 col-12 mt-3 mt-md-0">
<Container className="py-4 d-none d-md-block">
<h4>{t('common.the-params')}</h4>
</Container>
<AccessResults />
<LimitDate />
<Grades />
<Order />
<Private />
</Col>
</Row>
<Container
onClick={handleSubmit}
className="my-5 d-md-flex d-grid justify-content-md-center"
>
<Button
outline={true}
color="secondary"
className="bg-blue"
disabled={disabled}
icon={faArrowRight}
position="right"
>
{t('admin.confirm-submit')}
</Button>
</Container>
</Container>
);
};
export default ConfirmField;