diff --git a/components/Error.tsx b/components/Error.tsx index 49bcbe6..73d83d6 100644 --- a/components/Error.tsx +++ b/components/Error.tsx @@ -1,31 +1,34 @@ -import {Container} from 'reactstrap'; -import {useTranslation} from 'next-i18next'; -import {CONTACT_MAIL} from '@services/constants'; -import Button from '@components/Button' -import {faEnvelope} from '@fortawesome/free-solid-svg-icons'; +import { Container } from 'reactstrap'; +import { useTranslation } from 'next-i18next'; +import { CONTACT_MAIL } from '@services/constants'; +import Button from '@components/Button'; +import { faEnvelope } from '@fortawesome/free-solid-svg-icons'; -const Error = ({msg}) => { - const {t} = useTranslation(); - if (!msg) return null; +const Error = ({ children }) => { + const { t } = useTranslation(); + if (!children) return null; return ( - -

{t("common.error")}

-
{msg}
+
+ +

{t('common.error')}

+

{children}

- - - -
+ + + + +
); }; diff --git a/components/Experience.tsx b/components/Experience.tsx index 64df866..ff913ae 100644 --- a/components/Experience.tsx +++ b/components/Experience.tsx @@ -18,7 +18,6 @@ const Experiencediv = () => { /> -

{t('home.experience-name')}

diff --git a/components/WaitingBallot.tsx b/components/WaitingBallot.tsx index cd2c3aa..5a0d429 100644 --- a/components/WaitingBallot.tsx +++ b/components/WaitingBallot.tsx @@ -1,20 +1,20 @@ import Image from 'next/image'; -import {useTranslation} from 'next-i18next'; -import {CSSProperties, useEffect, useState} from 'react'; -import {faArrowRight} from '@fortawesome/free-solid-svg-icons'; -import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; -import {Col, Container, Row} from 'reactstrap'; +import { useTranslation } from 'next-i18next'; +import { CSSProperties, useEffect, useState } from 'react'; +import { faArrowRight } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Col, Container, Row } from 'reactstrap'; import Button from '@components/Button'; import ButtonCopy from '@components/ButtonCopy'; import Share from '@components/Share'; import ErrorMessage from '@components/Error'; import AdminModalEmail from '@components/admin/AdminModalEmail'; -import {BallotPayload, ErrorPayload} from '@services/api'; -import {AppTypes, useAppContext} from '@services/context'; -import {displayRef, isEnded} from '@services/utils'; -import {RESULTS} from '@services/routes'; +import { BallotPayload, ErrorPayload } from '@services/api'; +import { AppTypes, useAppContext } from '@services/context'; +import { displayRef, isEnded } from '@services/utils'; +import { RESULTS } from '@services/routes'; import Logo from './Logo'; -import {FORM_FEEDBACK, MAJORITY_JUDGMENT_LINK} from '@services/constants'; +import { FORM_FEEDBACK, MAJORITY_JUDGMENT_LINK } from '@services/constants'; import urne from '../public/urne.svg'; import star from '../public/star.svg'; import logo from '../public/logo-red-blue.svg'; @@ -25,8 +25,8 @@ export interface WaitingBallotInterface { error?: ErrorPayload; } -const ButtonResults = ({election}) => { - const {t} = useTranslation(); +const ButtonResults = ({ election }) => { + const { t } = useTranslation(); if (!election.hideResults || isEnded(election.date_end)) { return ( @@ -42,14 +42,18 @@ const ButtonResults = ({election}) => { }; const DiscoverMajorityJudgment = () => { - const {t} = useTranslation(); + const { t } = useTranslation(); return (
{t('vote.discover-mj')}

{t('vote.discover-mj-desc')}

- +
{t('common.about')}
@@ -60,7 +64,7 @@ const DiscoverMajorityJudgment = () => { }; const SupportBetterVote = () => { - const {t} = useTranslation(); + const { t } = useTranslation(); return (
@@ -81,7 +85,7 @@ const SupportBetterVote = () => { }; const Thanks = () => { - const {t} = useTranslation(); + const { t } = useTranslation(); return ( <>
{t('vote.thanks')}
@@ -99,13 +103,13 @@ interface InfoInterface extends WaitingBallotInterface { display: string; } -const Info = ({ballot, error, display}: InfoInterface) => { - const {t} = useTranslation(); +const Info = ({ ballot, error, display }: InfoInterface) => { + const { t } = useTranslation(); if (!ballot) return null; if (error) { - return ; + return {error.detail[0].msg}; } return ( @@ -132,7 +136,7 @@ const Info = ({ballot, error, display}: InfoInterface) => { ); }; -export default ({ballot, error}: WaitingBallotInterface) => { +export default ({ ballot, error }: WaitingBallotInterface) => { const [_, dispatch] = useAppContext(); const [urneProperties, setUrne] = useState({ @@ -154,7 +158,7 @@ export default ({ballot, error}: WaitingBallotInterface) => { }); useEffect(() => { - dispatch({type: AppTypes.FULLPAGE, value: true}); + dispatch({ type: AppTypes.FULLPAGE, value: true }); setUrne((urne) => ({ ...urne, @@ -193,7 +197,7 @@ export default ({ballot, error}: WaitingBallotInterface) => { }, 3000); const timer3 = setTimeout(() => { - setBallot({display: 'grid'}); + setBallot({ display: 'grid' }); }, 4500); return () => { diff --git a/components/WaitingElection.tsx b/components/WaitingElection.tsx index 699fb8b..d909bbc 100644 --- a/components/WaitingElection.tsx +++ b/components/WaitingElection.tsx @@ -44,7 +44,7 @@ const InfoElection = ({ election, error, display }: InfoElectionInterface) => { >
{error && error.detail ? ( - + {error.detail[0].msg} ) : null} {election && election.ref ? ( diff --git a/components/layouts/LanguageSelector.tsx b/components/layouts/LanguageSelector.tsx index 619c548..b6f6e04 100644 --- a/components/layouts/LanguageSelector.tsx +++ b/components/layouts/LanguageSelector.tsx @@ -1,7 +1,6 @@ -import {useRouter} from 'next/router'; +import { useRouter } from 'next/router'; import ReactFlagsSelect from 'react-flags-select'; -import {getLocaleShort} from '@services/utils'; - +import { getLocaleShort } from '@services/utils'; const LanguageSelector = (props) => { const router = useRouter(); @@ -10,7 +9,9 @@ const LanguageSelector = (props) => { const selectHandler = (e) => { let locale = e.toLowerCase(); if (locale === 'gb') locale = 'en'; - router.push('', '', {locale}); + const { pathname, asPath, query } = router; + // change just the locale and maintain all other route information including href's query + router.push({ pathname, query }, asPath, { locale }); }; return ( @@ -20,8 +21,8 @@ const LanguageSelector = (props) => { // ["GB", "FR", "ES", "DE", "RU"] ['GB', 'FR'] } - selected={localeShort == "en" ? "GB" : localeShort.toUpperCase()} - customLabels={{GB: 'English', FR: 'Francais'}} + selected={localeShort == 'en' ? 'GB' : localeShort.toUpperCase()} + customLabels={{ GB: 'English', FR: 'Francais' }} {...props} className="menu-flags" /> diff --git a/pages/end/[pid]/[[...tid]].tsx b/pages/end/[pid]/[[...tid]].tsx index 3912182..8639d80 100644 --- a/pages/end/[pid]/[[...tid]].tsx +++ b/pages/end/[pid]/[[...tid]].tsx @@ -1,37 +1,37 @@ -import Link from 'next/link' -import {useTranslation} from 'next-i18next'; -import {serverSideTranslations} from 'next-i18next/serverSideTranslations'; -import {faArrowRight} from '@fortawesome/free-solid-svg-icons'; -import {Container} from 'reactstrap'; +import Link from 'next/link'; +import { useTranslation } from 'next-i18next'; +import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; +import { faArrowRight } from '@fortawesome/free-solid-svg-icons'; +import { Container } from 'reactstrap'; import ErrorMessage from '@components/Error'; -import {RESULTS} from '@services/routes' -import {displayRef} from '@services/utils' -import Blur from '@components/Blur' +import { RESULTS } from '@services/routes'; +import { displayRef } from '@services/utils'; +import Blur from '@components/Blur'; import Button from '@components/Button'; - -export const getServerSideProps = async ({query: {pid, tid}, locale}) => { +export const getServerSideProps = async ({ query: { pid, tid }, locale }) => { return { props: { ...(await serverSideTranslations(locale, ['resource'])), token: tid, - electionRef: pid.replaceAll("-", "") + electionRef: pid.replaceAll('-', ''), }, - } -} + }; +}; -const End = ({electionRef, token}) => { - const {t} = useTranslation(); +const End = ({ electionRef, token }) => { + const { t } = useTranslation(); return ( <>
- + {t('error.ended-election')} + href={`${RESULTS}/${displayRef(electionRef)}/${token ? token : ''}`} + > + {t('vote.go-to-results')} +
diff --git a/pages/result/[pid]/[[...tid]].tsx b/pages/result/[pid]/[[...tid]].tsx index 839543a..401573d 100644 --- a/pages/result/[pid]/[[...tid]].tsx +++ b/pages/result/[pid]/[[...tid]].tsx @@ -3,18 +3,11 @@ import Head from 'next/head'; import Image from 'next/image'; import { useTranslation } from 'next-i18next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; -import { useRouter } from 'next/router'; import Link from 'next/link'; -import { - Container, - Collapse, - Card, - CardHeader, - CardBody, - Button, -} from 'reactstrap'; +import { Container, Collapse, Card, CardHeader, CardBody } from 'reactstrap'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { + faArrowRight, faChevronDown, faChevronRight, faChevronUp, @@ -24,6 +17,7 @@ import ErrorMessage from '@components/Error'; import CSVLink from '@components/CSVLink'; import Logo from '@components/Logo'; import MeritProfile from '@components/MeritProfile'; +import Button from '@components/Button'; import { getResults } from '@services/api'; import { GradeResultInterface, @@ -31,7 +25,7 @@ import { MeritProfileInterface, CandidateResultInterface, } from '@services/type'; -import { getUrlAdmin, RESULTS } from '@services/routes'; +import { getUrlAdmin, getUrlVote, RESULTS } from '@services/routes'; import { displayRef } from '@services/utils'; import { getMajorityGrade } from '@services/majorityJudgment'; import avatarBlue from '../../../public/avatarBlue.svg'; @@ -50,7 +44,7 @@ export async function getServerSideProps({ query, locale }) { ]); if ('msg' in payload) { - return { props: { err: payload.msg, ...translations } }; + return { props: { err: payload.msg, electionRef, ...translations } }; } const numGrades = payload.grades.length; @@ -473,18 +467,37 @@ interface ResultPageInterface { result?: ResultInterface; token?: string; err?: ErrorInterface; + electionRef?: string; } -const ResultPage = ({ result, token, err }: ResultPageInterface) => { +const ResultPage = ({ + result, + token, + err, + electionRef, +}: ResultPageInterface) => { const { t } = useTranslation(); - const router = useRouter(); - if (err && err.message !== '') { - return ; + if (err && err.message.startsWith('No votes')) { + const urlVote = getUrlVote(electionRef, token); + return ( + + { + <> +

{t('result.no-votes')}

+ + + + + } +
+ ); } if (!result) { - return ; + return {t('error.catch22')}; } if ( diff --git a/pages/vote/[pid]/[[...tid]].tsx b/pages/vote/[pid]/[[...tid]].tsx index 50141e9..e809cdf 100644 --- a/pages/vote/[pid]/[[...tid]].tsx +++ b/pages/vote/[pid]/[[...tid]].tsx @@ -65,7 +65,7 @@ const GoToBallotConfirmDesktop = ({ electionRef, token }) => { - diff --git a/public/locales/en/resource.json b/public/locales/en/resource.json index 607e0e4..135bcb3 100644 --- a/public/locales/en/resource.json +++ b/public/locales/en/resource.json @@ -167,6 +167,8 @@ "admin.go-to-result": "View results", "result.download": "Download results", "result.go-to-admin": "Manage the election", + "result.go-to-vote": "Would you go to the voting page?", + "result.no-votes": "No vote has been recorded yet.", "result.merit-profile": "Merit profile of the candidate", "result.has-closed": "Closed since", "result.opened": "The election is opened", diff --git a/public/locales/fr/resource.json b/public/locales/fr/resource.json index 49530e3..7fab802 100644 --- a/public/locales/fr/resource.json +++ b/public/locales/fr/resource.json @@ -168,6 +168,8 @@ "admin.go-to-result": "Voir les résultats", "result.download": "Télécharger les résultats", "result.go-to-admin": "Administrer le vote", + "result.go-to-vote": "Souhaitez-vous accéder au vote ?", + "result.no-votes": "Aucun vote n'a encore été enregistré.", "result.has-closed": "Terminée depuis", "result.closed": "L'élection est terminée", "result.opened": "L'élection est en cours", diff --git a/styles/scss/_button.scss b/styles/scss/_button.scss index da2f734..c402cd5 100644 --- a/styles/scss/_button.scss +++ b/styles/scss/_button.scss @@ -17,6 +17,9 @@ border-style: solid; border-radius: 0px; } +.btn:hover { + color: #afafaf; +} *[class*='btn-outline-'] { box-shadow: 0px 4px 0px; border-width: 2px; @@ -67,7 +70,7 @@ .btn-outline-secondary:hover { background-color: white!important; border-color: $mv-blue-color; - color: $mv-blue-color; + color: $mv-blue-color!important; } .btn.btn-danger:hover { color: map.get($theme-colors, 'danger'); diff --git a/styles/scss/config.scss b/styles/scss/config.scss index fa39c6c..0c6dd18 100644 --- a/styles/scss/config.scss +++ b/styles/scss/config.scss @@ -50,6 +50,8 @@ $font-sizes: ( 6: $font-size-base * 0.75, ); +$hover-color: white; + @import '_bootstrap.scss'; @import 'app.scss'; @import '_button.scss';