diff --git a/components/ballot/BallotDesktop.tsx b/components/ballot/BallotDesktop.tsx
new file mode 100644
index 0000000..2cb0694
--- /dev/null
+++ b/components/ballot/BallotDesktop.tsx
@@ -0,0 +1,77 @@
+import {MouseEvent} from 'react'
+import {useRouter} from 'next/router';
+import {useTranslation} from 'next-i18next';
+import Button from '@components/Button';
+import {Col, Row, Container} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faCalendarDays, faCheck} from '@fortawesome/free-solid-svg-icons';
+import {useBallot, BallotTypes, BallotProvider} from '@services/BallotContext';
+import CandidateCard from '@components/ballot/CandidateCard'
+import TitleBar from '@components/ballot/TitleBar'
+import GradeInput from '@components/ballot/GradeInput'
+
+
+const BallotDesktop = () => {
+ const {t} = useTranslation();
+
+ const [ballot, dispatch] = useBallot();
+
+ const numGrades = ballot.election.grades.length;
+ const disabled = ballot.votes.length !== ballot.election.candidates.length;
+ const router = useRouter();
+
+ const handleSubmit = (event: MouseEvent) => {
+ event.preventDefault();
+
+ // const gradesById = {};
+ // judgments.forEach((c) => {
+ // gradesById[c.id] = c.value;
+ // });
+ // const gradesByCandidate = [];
+ // Object.keys(gradesById).forEach((id) => {
+ // gradesByCandidate.push(gradesById[id]);
+ // });
+
+ // castBallot(gradesByCandidate, election.id.toString(), token, () => {
+ router.push(`/confirm/${ballot.election.id}`);
+ // });
+ };
+
+ return (
+
+
+
+
{ballot.election.name}
+ {ballot.election.candidates.map((candidate, candidateId) => {
+ return (
+
+
+
+ {ballot.election.grades.map((_, gradeId) => {
+ console.assert(gradeId < numGrades);
+ return (
+
+ );
+ })}
+
+
+ );
+ })}
+
+
+
+
+
+ )
+}
+export default BallotDesktop
diff --git a/components/ballot/BallotMobile.tsx b/components/ballot/BallotMobile.tsx
new file mode 100644
index 0000000..306c884
--- /dev/null
+++ b/components/ballot/BallotMobile.tsx
@@ -0,0 +1,65 @@
+import {MouseEvent} from 'react'
+import {useRouter} from 'next/router';
+import {useTranslation} from 'next-i18next';
+import Button from '@components/Button';
+import {Col, Row, Container} from 'reactstrap';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+import {faCalendarDays, faCheck} from '@fortawesome/free-solid-svg-icons';
+import {useBallot, BallotTypes, BallotProvider} from '@services/BallotContext';
+import CandidateCard from '@components/ballot/CandidateCard'
+import TitleBar from '@components/ballot/TitleBar'
+import GradeInput from '@components/ballot/GradeInput'
+
+
+const BallotMobile = () => {
+ const {t} = useTranslation();
+
+ const [ballot, dispatch] = useBallot();
+
+ const numGrades = ballot.election.grades.length;
+ const disabled = ballot.votes.length !== ballot.election.candidates.length;
+ const router = useRouter();
+
+ const handleSubmit = (event: MouseEvent) => {
+ event.preventDefault();
+ router.push(`/confirm/${ballot.election.id}`);
+ };
+
+ return (
+
+
+
{ballot.election.name}
+ {ballot.election.candidates.map((candidate, candidateId) => {
+ return (
+
+
+
+ {ballot.election.grades.map((_, gradeId) => {
+ console.assert(gradeId < numGrades);
+ return (
+
+ );
+ })}
+
+
+ );
+ })}
+
+
+
+
+
+ )
+}
+
+export default BallotMobile
diff --git a/components/ballot/CandidateCard.tsx b/components/ballot/CandidateCard.tsx
new file mode 100644
index 0000000..9ac9463
--- /dev/null
+++ b/components/ballot/CandidateCard.tsx
@@ -0,0 +1,28 @@
+import Image from 'next/image';
+import {useTranslation} from 'next-i18next';
+import defaultAvatar from '../../public/avatarBlue.svg';
+import {CandidatePayload} from '@services/api';
+
+interface CandidateCardInterface {
+ candidate: CandidatePayload;
+}
+const CandidateCard = ({candidate}: CandidateCardInterface) => {
+ const {t} = useTranslation();
+ return (
+
+
+ {candidate.name}
+
+ {t("vote.more-details")}
+
+
)
+}
+
+
+export default CandidateCard;
diff --git a/components/ballot/GradeInput.tsx b/components/ballot/GradeInput.tsx
new file mode 100644
index 0000000..00e14e7
--- /dev/null
+++ b/components/ballot/GradeInput.tsx
@@ -0,0 +1,34 @@
+import {useState, useCallback, useEffect, MouseEvent} from 'react';
+import {useBallot, BallotTypes} from '@services/BallotContext';
+import {getGradeColor} from '@services/grades';
+
+interface GradeInputInterface {
+ gradeId: number;
+ candidateId: number;
+}
+const GradeInput = ({gradeId, candidateId}: GradeInputInterface) => {
+ const [ballot, dispatch] = useBallot();
+ if (!ballot) {throw Error("Ensure the election is loaded")}
+
+ const grade = ballot.election.grades[gradeId];
+ const numGrades = ballot.election.grades.length;
+
+ const handleClick = (event: MouseEvent) => {
+ dispatch({type: BallotTypes.VOTE, candidateId: candidateId, gradeId: gradeId})
+ };
+
+ const active = ballot.votes.some(b => b.gradeId === gradeId && b.candidateId === candidateId)
+ const color = active ? getGradeColor(gradeId, numGrades) : '#C3BFD8';
+
+ return (
+
+ {grade.name}
+
+ )
+}
+
+export default GradeInput
diff --git a/components/ballot/TitleBar.tsx b/components/ballot/TitleBar.tsx
new file mode 100644
index 0000000..1e777ba
--- /dev/null
+++ b/components/ballot/TitleBar.tsx
@@ -0,0 +1,30 @@
+import {useRouter} from 'next/router';
+import Button from '@components/Button';
+import {useTranslation} from 'next-i18next';
+import {getElection, castBallot, apiErrors, ElectionPayload, CandidatePayload, GradePayload} from '@services/api';
+import {getLocaleShort} from '@services/utils';
+import {faCalendarDays} from '@fortawesome/free-solid-svg-icons';
+import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
+
+
+interface TitleBarInterface {
+ election: ElectionPayload;
+}
+const TitleBar = ({election}: TitleBarInterface) => {
+ const {t} = useTranslation();
+ const router = useRouter();
+ const locale = getLocaleShort(router);
+
+ return (
+
+
+
+
+
+ {` ${t("vote.open-until")} ${new Date(election.date_end).toLocaleDateString(locale, {dateStyle: "long"})}`}
+
+
+ )
+};
+
+export default TitleBar
diff --git a/pages/ballot/[pid]/[[...tid]].tsx b/pages/ballot/[pid]/[[...tid]].tsx
index 83e31ea..35efe43 100644
--- a/pages/ballot/[pid]/[[...tid]].tsx
+++ b/pages/ballot/[pid]/[[...tid]].tsx
@@ -1,22 +1,13 @@
-import {useState, useCallback, useEffect, MouseEvent} from 'react';
-import Image from 'next/image';
+import {useEffect} from 'react';
import Head from 'next/head';
import {useRouter} from 'next/router';
import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
import {useTranslation} from 'next-i18next';
-import {Col, Row, Container} from 'reactstrap';
-// import {toast, ToastContainer} from "react-toastify";
-import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
-import {faCalendarDays, faCheck} from '@fortawesome/free-solid-svg-icons';
import {getElection, castBallot, apiErrors, ElectionPayload, CandidatePayload, GradePayload} from '@services/api';
-import Button from '@components/Button';
-import useEmblaCarousel from 'embla-carousel-react';
-import {DotButton} from '@components/admin/EmblaCarouselButtons';
-import {getGradeColor} from '@services/grades';
+import BallotDesktop from '@components/ballot/BallotDesktop'
+import BallotMobile from '@components/ballot/BallotMobile'
import {useBallot, BallotTypes, BallotProvider} from '@services/BallotContext';
-import {getLocaleShort} from '@services/utils';
import {ENDED_VOTE} from '@services/routes';
-import defaultAvatar from '../../../public/avatarBlue.svg';
const shuffle = (array) => array.sort(() => Math.random() - 0.5);
@@ -64,115 +55,8 @@ export async function getServerSideProps({query: {pid, tid}, locale}) {
};
}
-interface TitleBarInterface {
- election: ElectionPayload;
-}
-const TitleBar = ({election}: TitleBarInterface) => {
- const {t} = useTranslation();
- const router = useRouter();
- const locale = getLocaleShort(router);
-
- return (
-
-
-
-
-
- {` ${t("vote.open-until")} ${new Date(election.date_end).toLocaleDateString(locale, {dateStyle: "long"})}`}
-
-
- )
-};
-
-interface CandidateCardInterface {
- candidate: CandidatePayload;
-}
-const CandidateCard = ({candidate}: CandidateCardInterface) => {
- const {t} = useTranslation();
- return (
-
-
- {candidate.name}
-
- {t("vote.more-details")}
-
-
)
-}
-interface GradeInputInterface {
- gradeId: number;
- candidateId: number;
-}
-const GradeInput = ({gradeId, candidateId}: GradeInputInterface) => {
- const [ballot, dispatch] = useBallot();
- if (!ballot) {throw Error("Ensure the election is loaded")}
-
- const grade = ballot.election.grades[gradeId];
- const numGrades = ballot.election.grades.length;
- const color = getGradeColor(gradeId, numGrades);
-
- const handleClick = (event: MouseEvent) => {
- dispatch({type: BallotTypes.VOTE, candidateId: candidateId, gradeId: gradeId})
- };
-
- const active = ballot.votes.some(b => b.gradeId === gradeId && b.candidateId === candidateId)
-
- return (
-
-
- {grade.name}
-
-
- { /**/}
- {grade.name}
- { /**/}
-
-
- )
-}
interface VoteInterface {
election: ElectionPayload;
@@ -197,7 +81,6 @@ const VoteBallot = ({election, token}: VoteInterface) => {
}
const numGrades = ballot.election.grades.length;
- const disabled = ballot.votes.length !== ballot.election.candidates.length;
const colSizeCandidateLg = 4;
const colSizeCandidateMd = 6;
const colSizeCandidateXs = 12;
@@ -254,7 +137,7 @@ const VoteBallot = ({election, token}: VoteInterface) => {
// }, [embla, setScrollSnaps, onSelect]);
return (
- <>
+
);
};
diff --git a/styles/scss/_button.scss b/styles/scss/_button.scss
index cd37c4c..b8301c5 100644
--- a/styles/scss/_button.scss
+++ b/styles/scss/_button.scss
@@ -76,3 +76,7 @@
top: 20px;
right: 20px;
}
+
+.btn_shadow{
+ box-shadow: 0px 2px 0px #8F88BA;
+}
diff --git a/styles/scss/config.scss b/styles/scss/config.scss
index 1451474..882ce7d 100644
--- a/styles/scss/config.scss
+++ b/styles/scss/config.scss
@@ -46,7 +46,7 @@ $font-sizes: (
2: $h2-font-size,
3: $h3-font-size,
4: $h4-font-size,
- 5: $font-size-base,
+ 5: $font-size-base * 0.9,
6: $font-size-base * 0.75
);