From b8ae38b52281221f79bb4090b02471a448e9de90 Mon Sep 17 00:00:00 2001
From: Pierre-Louis Guhur
Date: Thu, 17 Nov 2022 11:54:53 +0100
Subject: [PATCH] fix: refactor services
---
components/PatternedBackground.tsx | 6 +
components/WaitingBallot.tsx | 5 +
components/admin/AccessResults.tsx | 14 +-
components/admin/CandidateField.tsx | 21 +-
components/admin/CandidateModalDel.tsx | 20 +-
components/admin/CandidateModalSet.tsx | 27 ++-
components/admin/CandidatesField.tsx | 18 +-
components/admin/ConfirmField.tsx | 16 +-
components/admin/GradeField.tsx | 10 +-
components/admin/Grades.tsx | 16 +-
components/admin/LimitDate.tsx | 10 +-
components/admin/ParamsField.tsx | 16 +-
components/admin/Private.tsx | 24 +--
components/admin/Title.tsx | 2 +-
components/layouts/LanguageSelector.tsx | 11 +-
pages/admin/new.tsx | 55 +++++-
pages/index.tsx | 48 ++---
.../admin => services}/ElectionContext.tsx | 111 ++++++-----
services/api.ts | 179 ++++++++----------
services/grades.ts | 2 +-
services/imgpush.ts | 1 +
services/mail.ts | 47 +++++
services/routes.ts | 12 ++
services/type.ts | 19 ++
services/utils.ts | 38 ++++
25 files changed, 440 insertions(+), 288 deletions(-)
create mode 100644 components/PatternedBackground.tsx
create mode 100644 components/WaitingBallot.tsx
rename {components/admin => services}/ElectionContext.tsx (67%)
create mode 100644 services/mail.ts
create mode 100644 services/type.ts
create mode 100644 services/utils.ts
diff --git a/components/PatternedBackground.tsx b/components/PatternedBackground.tsx
new file mode 100644
index 0000000..abd978a
--- /dev/null
+++ b/components/PatternedBackground.tsx
@@ -0,0 +1,6 @@
+
+
+export default ({children}) => {
+
+ return {children}
+}
diff --git a/components/WaitingBallot.tsx b/components/WaitingBallot.tsx
new file mode 100644
index 0000000..990c3b0
--- /dev/null
+++ b/components/WaitingBallot.tsx
@@ -0,0 +1,5 @@
+
+export default ({onSubmit}) => {
+
+ return FOO
+}
diff --git a/components/admin/AccessResults.tsx b/components/admin/AccessResults.tsx
index d1e1069..c00dbc4 100644
--- a/components/admin/AccessResults.tsx
+++ b/components/admin/AccessResults.tsx
@@ -1,10 +1,10 @@
-import { useTranslation } from 'next-i18next';
-import { useElection, useElectionDispatch } from './ElectionContext';
-import { Container, Row, Col } from 'reactstrap';
+import {useTranslation} from 'next-i18next';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
+import {Container, Row, Col} from 'reactstrap';
import Switch from '@components/Switch';
const AccessResults = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const election = useElection();
const dispatch = useElectionDispatch();
@@ -13,7 +13,7 @@ const AccessResults = () => {
dispatch({
type: 'set',
field: 'restrictResult',
- value: !election.restrictResult,
+ value: !election.hideResults,
});
};
@@ -27,10 +27,10 @@ const AccessResults = () => {
{t('admin.access-results-desc')}
-
+
- {election.restrictResult ? (
+ {election.hideResults ? (
{t('admin.access-results-desc')}
diff --git a/components/admin/CandidateField.tsx b/components/admin/CandidateField.tsx
index 67bc68c..7b21e49 100644
--- a/components/admin/CandidateField.tsx
+++ b/components/admin/CandidateField.tsx
@@ -1,13 +1,13 @@
/**
* This is the candidate field used during election creation
*/
-import { useState } from 'react';
+import {useState} from 'react';
import Image from 'next/image';
-import { useTranslation } from 'next-i18next';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faPlus, faTrashCan } from '@fortawesome/free-solid-svg-icons';
-import { Row, Col } from 'reactstrap';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useTranslation} from 'next-i18next';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faPlus, faTrashCan} from '@fortawesome/free-solid-svg-icons';
+import {Row, Col} from 'reactstrap';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
import whiteAvatar from '../../public/avatar.svg';
import CandidateModalSet from './CandidateModalSet';
import CandidateModalDel from './CandidateModalDel';
@@ -25,7 +25,7 @@ const CandidateField = ({
defaultAvatar = whiteAvatar,
...props
}: CandidateProps) => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const election = useElection();
const dispatch = useElectionDispatch();
@@ -37,7 +37,7 @@ const CandidateField = ({
const [modalSet, setModalSet] = useState(false);
const addCandidate = () => {
- dispatch({ type: 'candidate-push', value: 'default' });
+ dispatch({type: 'candidate-push', value: 'default'});
};
const toggleSet = () => setModalSet((m) => !m);
@@ -59,9 +59,8 @@ const CandidateField = ({
src={image}
width={24}
height={24}
- className={`${
- image == defaultAvatar ? 'default-avatar' : ''
- } bg-primary`}
+ className={`${image == defaultAvatar ? 'default-avatar' : ''
+ } bg-primary`}
alt={t('common.thumbnail')}
/>
diff --git a/components/admin/CandidateModalDel.tsx b/components/admin/CandidateModalDel.tsx
index e49afcd..db20a3d 100644
--- a/components/admin/CandidateModalDel.tsx
+++ b/components/admin/CandidateModalDel.tsx
@@ -1,28 +1,28 @@
-import { Row, Col, Label, Input, Modal, ModalBody, Form } from 'reactstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {Row, Col, Label, Input, Modal, ModalBody, Form} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faTrashCan,
faTrashAlt,
faArrowLeft,
} from '@fortawesome/free-solid-svg-icons';
-import { useTranslation } from 'next-i18next';
+import {useTranslation} from 'next-i18next';
import Image from 'next/image';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
import Button from '@components/Button';
-import { upload } from '@services/imgpush';
-import { IMGPUSH_URL } from '@services/constants';
+import {upload} from '@services/imgpush';
+import {IMGPUSH_URL} from '@services/constants';
import defaultAvatar from '../../public/default-avatar.svg';
-import { useEffect } from 'react';
+import {useEffect} from 'react';
-const CandidateModal = ({ isOpen, position, toggle }) => {
- const { t } = useTranslation();
+const CandidateModal = ({isOpen, position, toggle}) => {
+ const {t} = useTranslation();
const election = useElection();
const dispatch = useElectionDispatch();
const candidate = election.candidates[position];
const removeCandidate = () => {
- dispatch({ type: 'candidate-rm', position: position });
+ dispatch({type: 'candidate-rm', position: position});
};
return (
diff --git a/components/admin/CandidateModalSet.tsx b/components/admin/CandidateModalSet.tsx
index 250ef00..8f7a9ea 100644
--- a/components/admin/CandidateModalSet.tsx
+++ b/components/admin/CandidateModalSet.tsx
@@ -1,16 +1,16 @@
-import { useState, useEffect, useRef } from 'react';
-import { Row, Col, Label, Input, Modal, ModalBody, Form } from 'reactstrap';
-import { faPlus, faArrowLeft } from '@fortawesome/free-solid-svg-icons';
-import { useTranslation } from 'next-i18next';
+import {useState, useEffect, useRef} from 'react';
+import {Row, Col, Label, Input, Modal, ModalBody, Form} from 'reactstrap';
+import {faPlus, faArrowLeft} from '@fortawesome/free-solid-svg-icons';
+import {useTranslation} from 'next-i18next';
import Image from 'next/image';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
import Button from '@components/Button';
-import { upload } from '@services/imgpush';
-import { IMGPUSH_URL } from '@services/constants';
+import {upload} from '@services/imgpush';
+import {IMGPUSH_URL} from '@services/constants';
import defaultAvatar from '../../public/default-avatar.svg';
-const CandidateModal = ({ isOpen, position, toggle }) => {
- const { t } = useTranslation();
+const CandidateModal = ({isOpen, position, toggle}) => {
+ const {t} = useTranslation();
const election = useElection();
const dispatch = useElectionDispatch();
const candidate = election.candidates[position];
@@ -19,7 +19,7 @@ const CandidateModal = ({ isOpen, position, toggle }) => {
const handleFile = async (event) => {
const payload = await upload(event.target.files[0]);
- setState((s) => ({ ...s, image: `${IMGPUSH_URL}/${payload['filename']}` }));
+ setState((s) => ({...s, image: `${IMGPUSH_URL}/${payload['filename']}`}));
};
// to manage the hidden ugly file input
@@ -27,7 +27,6 @@ const CandidateModal = ({ isOpen, position, toggle }) => {
useEffect(() => {
setState(election.candidates[position]);
- console.log('effect election', election);
}, [election]);
const save = () => {
@@ -53,11 +52,11 @@ const CandidateModal = ({ isOpen, position, toggle }) => {
};
const handleName = (e) => {
- setState((s) => ({ ...s, name: e.target.value }));
+ setState((s) => ({...s, name: e.target.value}));
};
const handleDescription = (e) => {
- setState((s) => ({ ...s, description: e.target.value }));
+ setState((s) => ({...s, description: e.target.value}));
};
return (
@@ -138,7 +137,7 @@ const CandidateModal = ({ isOpen, position, toggle }) => {
placeholder={t('admin.candidate-desc-placeholder')}
onChange={handleDescription}
value={state.description}
- // maxLength="250"
+ // maxLength="250"
/>
diff --git a/components/admin/CandidatesField.tsx b/components/admin/CandidatesField.tsx
index 2287b88..eb413e3 100644
--- a/components/admin/CandidatesField.tsx
+++ b/components/admin/CandidatesField.tsx
@@ -1,15 +1,15 @@
-import { useState, useEffect, createRef } from 'react';
-import { useTranslation } from 'next-i18next';
-import { Container } from 'reactstrap';
-import { faArrowRight } from '@fortawesome/free-solid-svg-icons';
-import { MAX_NUM_CANDIDATES } from '@services/constants';
+import {useState, useEffect, createRef} from 'react';
+import {useTranslation} from 'next-i18next';
+import {Container} from 'reactstrap';
+import {faArrowRight} from '@fortawesome/free-solid-svg-icons';
+import {MAX_NUM_CANDIDATES} from '@services/constants';
import Alert from '@components/Alert';
import Button from '@components/Button';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
import CandidateField from './CandidateField';
-const CandidatesField = ({ onSubmit }) => {
- const { t } = useTranslation();
+const CandidatesField = ({onSubmit}) => {
+ const {t} = useTranslation();
const election = useElection();
const dispatch = useElectionDispatch();
@@ -21,7 +21,7 @@ const CandidatesField = ({ onSubmit }) => {
useEffect(() => {
// Initialize the list with at least two candidates
if (candidates.length < 2) {
- dispatch({ type: 'candidate-push', value: 'default' });
+ dispatch({type: 'candidate-push', value: 'default'});
}
if (candidates.length > MAX_NUM_CANDIDATES) {
setError('error.too-many-candidates');
diff --git a/components/admin/ConfirmField.tsx b/components/admin/ConfirmField.tsx
index 7568208..5f6e3c6 100644
--- a/components/admin/ConfirmField.tsx
+++ b/components/admin/ConfirmField.tsx
@@ -1,4 +1,4 @@
-import { useTranslation } from 'next-i18next';
+import {useTranslation} from 'next-i18next';
import Footer from '@components/layouts/Footer';
import TrashButton from './TrashButton';
import {
@@ -19,8 +19,8 @@ import {
Label,
Container,
} from 'reactstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { useElection } from './ElectionContext';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {useElection} from '../../services/ElectionContext';
import CandidateField from './CandidateField';
import AccessResults from './AccessResults';
import LimitDate from './LimitDate';
@@ -28,7 +28,7 @@ import Grades from './Grades';
import Private from './Private';
const TitleField = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const election = useElection();
return (
@@ -37,13 +37,13 @@ const TitleField = () => {
{t('admin.confirm-question')}
- {election.title}
+ {election.name}
);
};
const CandidatesField = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const election = useElection();
return (
@@ -66,8 +66,8 @@ const CandidatesField = () => {
);
};
-const ConfirmField = ({ onSubmit, goToCandidates, goToParams }) => {
- const { t } = useTranslation();
+const ConfirmField = ({onSubmit, goToCandidates, goToParams}) => {
+ const {t} = useTranslation();
const election = useElection();
return (
diff --git a/components/admin/GradeField.tsx b/components/admin/GradeField.tsx
index 9c8e74f..3099f84 100644
--- a/components/admin/GradeField.tsx
+++ b/components/admin/GradeField.tsx
@@ -1,6 +1,6 @@
-import { useState } from 'react';
-import { Row, Col } from 'reactstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {useState} from 'react';
+import {Row, Col} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faPlus,
faPen,
@@ -8,9 +8,9 @@ import {
faCheck,
faRotateLeft,
} from '@fortawesome/free-solid-svg-icons';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
-const GradeField = ({ value }) => {
+const GradeField = ({value}) => {
const [modal, setModal] = useState(false);
const toggle = () => setModal((m) => !m);
diff --git a/components/admin/Grades.tsx b/components/admin/Grades.tsx
index 5adaa5c..bc5b04a 100644
--- a/components/admin/Grades.tsx
+++ b/components/admin/Grades.tsx
@@ -1,22 +1,22 @@
/**
* A field to update the grades
*/
-import { useState, useEffect } from 'react';
-import { useTranslation } from 'next-i18next';
-import { Container, Row, Col } from 'reactstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import {useState, useEffect} from 'react';
+import {useTranslation} from 'next-i18next';
+import {Container, Row, Col} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {
faPlus,
faPen,
faXmark,
faCheck,
} from '@fortawesome/free-solid-svg-icons';
-import { DEFAULT_GRADES, GRADE_COLORS } from '@services/constants';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {DEFAULT_GRADES, GRADE_COLORS} from '@services/constants';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
import GradeField from './GradeField';
const AddField = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const [modal, setModal] = useState(false);
const toggle = () => setModal((m) => !m);
@@ -36,7 +36,7 @@ const AddField = () => {
};
const Grades = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const defaultEndDate = new Date();
defaultEndDate.setUTCDate(defaultEndDate.getUTCDate() + 15);
const [endDate, setEndDate] = useState(defaultEndDate);
diff --git a/components/admin/LimitDate.tsx b/components/admin/LimitDate.tsx
index 57ad318..43f99a7 100644
--- a/components/admin/LimitDate.tsx
+++ b/components/admin/LimitDate.tsx
@@ -1,12 +1,12 @@
-import { useState } from 'react';
-import { useTranslation } from 'next-i18next';
-import { Container, Row, Col } from 'reactstrap';
+import {useState} from 'react';
+import {useTranslation} from 'next-i18next';
+import {Container, Row, Col} from 'reactstrap';
import DatePicker from '@components/DatePicker';
import Switch from '@components/Switch';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
const LimitDate = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const defaultEndDate = new Date();
defaultEndDate.setUTCDate(defaultEndDate.getUTCDate() + 15);
const [endDate, setEndDate] = useState(defaultEndDate);
diff --git a/components/admin/ParamsField.tsx b/components/admin/ParamsField.tsx
index f3adcf9..871ca67 100644
--- a/components/admin/ParamsField.tsx
+++ b/components/admin/ParamsField.tsx
@@ -1,14 +1,19 @@
-import { useTranslation } from 'next-i18next';
-import { Container } from 'reactstrap';
-import { faArrowRight } from '@fortawesome/free-solid-svg-icons';
+import {useTranslation} from 'next-i18next';
+import {Container} from 'reactstrap';
+import {faArrowRight} from '@fortawesome/free-solid-svg-icons';
import Button from '@components/Button';
import Grades from './Grades';
import LimitDate from './LimitDate';
import AccessResults from './AccessResults';
import Private from './Private';
+import {useElection} from '@services/ElectionContext';
-const ParamsField = ({ onSubmit }) => {
- const { t } = useTranslation();
+const ParamsField = ({onSubmit}) => {
+ const {t} = useTranslation();
+
+ const election = useElection();
+ const checkDisability = election.restricted && (typeof election.emails === "undefined" || election.emails.length === 0);
+ console.log(election.restricted, typeof election.emails === "undefined", election.emails.length === 0)
return (
@@ -28,6 +33,7 @@ const ParamsField = ({ onSubmit }) => {
color="secondary"
className="bg-blue"
onClick={onSubmit}
+ disabled={checkDisability}
icon={faArrowRight}
position="right"
>
diff --git a/components/admin/Private.tsx b/components/admin/Private.tsx
index ac8d4af..948950f 100644
--- a/components/admin/Private.tsx
+++ b/components/admin/Private.tsx
@@ -1,14 +1,14 @@
/**
* A field to update the grades
*/
-import { useState } from 'react';
-import { useTranslation } from 'next-i18next';
-import { Container, Row, Col } from 'reactstrap';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { faCircleInfo } from '@fortawesome/free-solid-svg-icons';
+import {useState} from 'react';
+import {useTranslation} from 'next-i18next';
+import {Container, Row, Col} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faCircleInfo} from '@fortawesome/free-solid-svg-icons';
import Switch from '@components/Switch';
import ListInput from '@components/ListInput';
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
const validateEmail = (email) => {
// https://stackoverflow.com/a/46181/4986615
@@ -20,7 +20,7 @@ const validateEmail = (email) => {
};
const Private = () => {
- const { t } = useTranslation();
+ const {t} = useTranslation();
const [emails, setEmails] = useState([]);
@@ -30,8 +30,8 @@ const Private = () => {
const toggle = () => {
dispatch({
type: 'set',
- field: 'restrictVote',
- value: !election.restrictVote,
+ field: 'restricted',
+ value: !election.restricted,
});
};
@@ -53,9 +53,9 @@ const Private = () => {
{t('admin.private-desc')}
-
+
- {election.restrictVote ? (
+ {election.restricted ? (
<>
{
>
) : null}
- {election.restrictVote ? (
+ {election.restricted ? (
{t('admin.access-results-desc')}
diff --git a/components/admin/Title.tsx b/components/admin/Title.tsx
index 94be512..2fcbeba 100644
--- a/components/admin/Title.tsx
+++ b/components/admin/Title.tsx
@@ -1,7 +1,7 @@
/**
* This component manages the title of the election
*/
-import { useElection, useElectionDispatch } from './ElectionContext';
+import {useElection, useElectionDispatch} from '../../services/ElectionContext';
const TitleField = () => {
const election = useElection();
diff --git a/components/layouts/LanguageSelector.tsx b/components/layouts/LanguageSelector.tsx
index 777d14c..e5678b7 100644
--- a/components/layouts/LanguageSelector.tsx
+++ b/components/layouts/LanguageSelector.tsx
@@ -1,15 +1,16 @@
-import { useRouter } from 'next/router';
+import {useRouter} from 'next/router';
import ReactFlagsSelect from 'react-flags-select';
+import {getLocaleShort} from '@services/utils';
+
const LanguageSelector = (props) => {
const router = useRouter();
- let localeShort = router.locale.substring(0, 2).toUpperCase();
- if (localeShort === 'EN') localeShort = 'GB';
+ const localeShort = getLocaleShort();
const selectHandler = (e) => {
let locale = e.toLowerCase();
if (locale === 'gb') locale = 'en';
- router.push('', '', { locale });
+ router.push('', '', {locale});
};
return (
{
['GB', 'FR']
}
selected={localeShort}
- customLabels={{ GB: 'English', FR: 'Francais' }}
+ customLabels={{GB: 'English', FR: 'Francais'}}
{...props}
className="menu-flags"
/>
diff --git a/pages/admin/new.tsx b/pages/admin/new.tsx
index 8eafc30..6d20eb5 100644
--- a/pages/admin/new.tsx
+++ b/pages/admin/new.tsx
@@ -1,16 +1,22 @@
-import { useState } from 'react';
-import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
+import {useState} from 'react';
+import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
import CandidatesField from '@components/admin/CandidatesField';
import ParamsField from '@components/admin/ParamsField';
import ConfirmField from '@components/admin/ConfirmField';
+import WaitingBallot from '@components/WaitingBallot';
+import PatternedBackground from '@components/PatternedBackground';
import {
ElectionProvider,
useElection,
-} from '@components/admin/ElectionContext';
-import { ProgressSteps, creationSteps } from '@components/CreationSteps';
-import { GetStaticProps } from 'next';
+} from '@services/ElectionContext';
+import {ProgressSteps, creationSteps} from '@components/CreationSteps';
+import {GetStaticProps} from 'next';
+import {createElection, ElectionPayload} from '@services/api';
+import {getUrlVote, getUrlResult} from '@services/routes';
+import {GradeItem, CandidateItem} from '@services/type';
+import {sendInviteMails} from '@services/mail';
-export const getStaticProps: GetStaticProps = async ({ locale }) => ({
+export const getStaticProps: GetStaticProps = async ({locale}) => ({
props: {
...(await serverSideTranslations(locale, ['resource'])),
},
@@ -22,12 +28,43 @@ export const getStaticProps: GetStaticProps = async ({ locale }) => ({
const CreateElectionForm = () => {
// load the election
const election = useElection();
+ const [wait, setWait] = useState(false);
const handleSubmit = () => {
if (stepId < creationSteps.length - 1) {
setStepId((i) => i + 1);
} else {
- // TODO
+ setWait(true);
+
+ createElection(
+ election.name,
+ election.candidates.map((c: CandidateItem) => ({name: c.name, description: c.description, image: c.image})),
+ election.grades.map((g: GradeItem, i: number) => ({name: g.name, value: i})),
+ election.description,
+ election.emails.length,
+ election.hideResults,
+ election.forceClose,
+ election.restricted,
+ (payload: ElectionPayload) => {
+ const id = payload.id;
+ const tokens = payload.tokens;
+ if (typeof election.emails !== 'undefined' && election.emails.length > 0) {
+ if (typeof payload.tokens === 'undefined' || payload.tokens.length === election.emails.length) {
+ throw Error('Can not send invite emails');
+ }
+ const urlVotes = election.tokens.map((token: string) => getUrlVote(id.toString(), token));
+ const urlResult = getUrlResult(id.toString());
+ sendInviteMails(
+ election.emails,
+ tokens,
+ election.name,
+ urlVotes,
+ urlResult,
+ );
+ }
+ }
+
+ )
}
};
@@ -48,6 +85,10 @@ const CreateElectionForm = () => {
goToParams={() => setStepId(1)}
/>
);
+ } else if (step == 'waiting') {
+ return
+ ;
+
} else {
throw Error(`Unknown step ${step}`);
}
diff --git a/pages/index.tsx b/pages/index.tsx
index f6bdeab..c9318cb 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,12 +1,12 @@
-import { useState } from 'react';
+import {useState} from 'react';
import Link from 'next/link';
import Image from 'next/image';
-import { GetStaticProps } from 'next';
-import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
-import { useTranslation } from 'next-i18next';
-import { Container, Row, Col, Button, Input } from 'reactstrap';
+import {GetStaticProps} from 'next';
+import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
+import {useTranslation} from 'next-i18next';
+import {Container, Row, Col, Button, Input} from 'reactstrap';
import Logo from '@components/Logo';
-import { CREATE_ELECTION } from '@services/routes';
+import {CREATE_ELECTION} from '@services/routes';
import ballotBox from '../public/urne.svg';
import email from '../public/email.svg';
import respect from '../public/respect.svg';
@@ -15,15 +15,15 @@ import twitter from '../public/twitter.svg';
import facebook from '../public/facebook.svg';
import arrowRight from '../public/arrow-white.svg';
-export const getStaticProps: GetStaticProps = async ({ locale }) => ({
+export const getStaticProps: GetStaticProps = async ({locale}) => ({
props: {
...(await serverSideTranslations(locale, ['resource'])),
},
});
const StartForm = () => {
- const { t } = useTranslation('resource');
- const [title, setTitle] = useState(null);
+ const {t} = useTranslation('resource');
+ const [name, setName] = useState(null);
return (