fix: grade colors

pull/102/head
Pierre-Louis Guhur 8 months ago
parent f239441a54
commit 6a301df00e

@ -429,7 +429,7 @@ const ManageElection = ({token}) => {
<Col className={isClosed(election) ? 'col-12' : 'col-lg-3 col-12'}>
<Container className="py-4 d-none d-md-block">
<h4>{t('common.the-vote')}</h4>
{election.numVoters !== undefined &&
{election.restricted && election.numVoters !== undefined &&
<h5>{t('admin.num-voters')} {election.numVoters}</h5>
}
{election.numVoted !== undefined &&

@ -1,11 +1,11 @@
import {useState} from 'react';
import { useState } from 'react';
import Head from 'next/head';
import Image from 'next/image';
import {useTranslation} from 'next-i18next';
import {serverSideTranslations} from 'next-i18next/serverSideTranslations';
import { useTranslation } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import Link from 'next/link';
import {Container, Collapse, Card, CardHeader, CardBody} from 'reactstrap';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import { Container, Collapse, Card, CardHeader, CardBody } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faArrowRight,
faChevronDown,
@ -18,25 +18,25 @@ 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 { getResults } from '@services/api';
import {
GradeResultInterface,
ResultInterface,
MeritProfileInterface,
CandidateResultInterface,
} from '@services/type';
import {getUrl, RouteTypes} from '@services/routes';
import {displayRef, getLocaleShort} from '@services/utils';
import {getMajorityGrade} from '@services/majorityJudgment';
import { getUrl, RouteTypes } from '@services/routes';
import { displayRef, getLocaleShort } from '@services/utils';
import { getMajorityGrade } from '@services/majorityJudgment';
import avatarBlue from '../../../public/avatarBlue.svg';
import calendar from '../../../public/calendar.svg';
import arrowUpload from '../../../public/arrowUpload.svg';
import arrowLink from '../../../public/arrowL.svg';
import {getGradeColor} from '@services/grades';
import {useRouter} from 'next/router';
import { getGradeColor } from '@services/grades';
import { useRouter } from 'next/router';
export async function getServerSideProps({query, locale}) {
const {pid, tid: token} = query;
export async function getServerSideProps({ query, locale }) {
const { pid, tid: token } = query;
const electionRef = pid.replaceAll('-', '');
const [payload, translations] = await Promise.all([
@ -45,16 +45,24 @@ export async function getServerSideProps({query, locale}) {
]);
if ('message' in payload) {
return {props: {err: payload, electionRef, ...translations}};
return { props: { err: payload, electionRef, ...translations } };
}
const numGrades = payload.grades.length;
const grades = payload.grades.map((g, i) => ({
...g,
color: getGradeColor(g.value, numGrades),
}));
const gradesByValue: {[key: number]: GradeResultInterface} = {};
const gradeValues = payload.grades.map((g) => g.value).sort();
const grades = payload.grades.map((g) => {
const gradeIdx = gradeValues.indexOf(g.value);
if (gradeIdx === -1) {
throw new Error('Could not find grade value in grades');
}
const color = getGradeColor(gradeIdx, numGrades);
return { ...g, color };
});
const gradesByValue: { [key: number]: GradeResultInterface } = {};
grades.forEach((g) => (gradesByValue[g.value] = g));
console.log('Grades', grades);
const result: ResultInterface = {
name: payload.name,
@ -106,8 +114,8 @@ const getNumVotes = (result: ResultInterface) => {
return numVotes;
};
const WillClose = ({delay, forceClose}) => {
const {t} = useTranslation();
const WillClose = ({ delay, forceClose }) => {
const { t } = useTranslation();
if (delay < 365 || forceClose) {
return <div>{t('result.closed')}</div>;
} else if (delay < 0) {
@ -126,8 +134,8 @@ const WillClose = ({delay, forceClose}) => {
interface ResultBanner {
result: ResultInterface;
}
const ResultBanner = ({result}) => {
const {t} = useTranslation();
const ResultBanner = ({ result }) => {
const { t } = useTranslation();
const router = useRouter();
const dateEnd = new Date(result.dateEnd);
@ -208,16 +216,16 @@ const ResultBanner = ({result}) => {
);
};
const Downloader = ({result, children, ...rest}) => {
const Downloader = ({ result, children, ...rest }) => {
const values = result.grades.map((v) => v.value).sort();
const data = result.candidates.map((c) => {
const grades = {};
result.grades.forEach(
(g) =>
(grades[g.name] =
g.value in c.meritProfile ? c.meritProfile[g.value].toString() : '0')
(grades[g.name] =
g.value in c.meritProfile ? c.meritProfile[g.value].toString() : '0')
);
return {name: c.name, ...grades};
return { name: c.name, ...grades };
});
return (
@ -231,8 +239,8 @@ const Downloader = ({result, children, ...rest}) => {
);
};
const BottomButtonsMobile = ({result}) => {
const {t} = useTranslation();
const BottomButtonsMobile = ({ result }) => {
const { t } = useTranslation();
const router = useRouter();
const locale = getLocaleShort(router);
@ -278,8 +286,8 @@ interface TitleBannerInterface {
token?: string;
}
const TitleBanner = ({name, electionRef, token}: TitleBannerInterface) => {
const {t} = useTranslation();
const TitleBanner = ({ name, electionRef, token }: TitleBannerInterface) => {
const { t } = useTranslation();
const router = useRouter();
const locale = getLocaleShort(router);
@ -333,7 +341,7 @@ interface ButtonGradeResultInterface {
grade: GradeResultInterface;
}
const ButtonGrade = ({grade}: ButtonGradeResultInterface) => {
const ButtonGrade = ({ grade }: ButtonGradeResultInterface) => {
const style = {
color: 'white',
backgroundColor: grade.color,
@ -353,7 +361,7 @@ interface CandidateRankedInterface {
candidate: CandidateResultInterface;
}
const CandidateRanked = ({candidate}: CandidateRankedInterface) => {
const CandidateRanked = ({ candidate }: CandidateRankedInterface) => {
const isFirst = candidate.rank == 1;
return (
<div className="m-3 d-flex flex-column justify-content-end align-items-center candidate_rank fw-bold">
@ -379,8 +387,8 @@ interface CandidateCardInterface {
grades: Array<GradeResultInterface>;
}
const CandidateCard = ({candidate, grades}: CandidateCardInterface) => {
const {t} = useTranslation();
const CandidateCard = ({ candidate, grades }: CandidateCardInterface) => {
const { t } = useTranslation();
const [collapse, setCollapse] = useState(true);
return (
@ -426,8 +434,8 @@ interface PodiumInterface {
candidates: Array<CandidateResultInterface>;
}
const Podium = ({candidates}: PodiumInterface) => {
const {t} = useTranslation();
const Podium = ({ candidates }: PodiumInterface) => {
const { t } = useTranslation();
// get best candidates
const numBest = Math.min(3, candidates.length);
@ -475,7 +483,7 @@ const ResultPage = ({
err,
electionRef,
}: ResultPageInterface) => {
const {t} = useTranslation();
const { t } = useTranslation();
const router = useRouter();
const locale = getLocaleShort(router);
@ -490,7 +498,10 @@ const ResultPage = ({
<div className="d-md-flex d-grid">
<Button
className="d-md-flex d-grid"
color="primary" icon={faArrowRight} position="right">
color="primary"
icon={faArrowRight}
position="right"
>
{t('result.go-to-vote')}
</Button>
</div>
@ -533,8 +544,7 @@ const ResultPage = ({
}
const candidateByRank = {};
result.candidates
.forEach((c) => (candidateByRank[c.rank] = c));
result.candidates.forEach((c) => (candidateByRank[c.rank] = c));
return (
<Container className="h-100 resultContainer resultPage d-flex flex-column align-flex-stretch">
@ -546,28 +556,25 @@ const ResultPage = ({
<TitleBanner electionRef={result.ref} token={token} name={result.name} />
<ResultBanner result={result} />
<Container
style={{maxWidth: '1000px'}}
>
<Container style={{ maxWidth: '1000px' }}>
<Podium candidates={result.candidates} />
</Container>
<Container
style={{maxWidth: '750px'}}
style={{ maxWidth: '750px' }}
className="my-5 h-100 d-flex flex-fill flex-column justify-content-between"
>
<div>
<h5 className="text-white">{t('result.details')}</h5>
{Object.keys(candidateByRank)
.map((rank, i) => {
return (
<CandidateCard
candidate={candidateByRank[rank]}
grades={result.grades}
key={i}
/>
);
})}
{Object.keys(candidateByRank).map((rank, i) => {
return (
<CandidateCard
candidate={candidateByRank[rank]}
grades={result.grades}
key={i}
/>
);
})}
</div>
<BottomButtonsMobile result={result} />
</Container>

@ -1,17 +1,15 @@
/**
/**
* This is a mini-SDK to submit files upload to imgpush
*/
import {IMGPUSH_URL} from '@services/constants';
import { IMGPUSH_URL } from '@services/constants';
export const upload = async (photo) => {
const formData = new FormData();
formData.append('file', photo);
formData.append('fileName', photo.name);
return fetch(
IMGPUSH_URL,
{method: "POST", body: formData}
)
.then(ans => {return ans.json();})
.catch(console.log)
}
return fetch(IMGPUSH_URL, { method: 'POST', body: formData })
.then((ans) => {
return ans.json();
})
.catch(console.log);
};

Loading…
Cancel
Save