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/services/BallotContext.tsx

94 lines
2.1 KiB

/**
* This file provides a context and a reducer to manage a ballot
*/
import {createContext, useContext, useReducer, Dispatch} from 'react';
import {ElectionPayload} from './api';
import {Vote} from './type';
export interface BallotContextInterface {
election: ElectionPayload | null;
votes: Array<Vote>;
}
const defaultBallot: BallotContextInterface = {
election: null,
votes: []
};
export enum BallotTypes {
ELECTION = 'ELECTION',
VOTE = 'VOTE',
}
export type ElectionAction = {
type: BallotTypes.ELECTION;
election: ElectionPayload;
}
export type VoteAction = {
type: BallotTypes.VOTE;
candidateId: number;
gradeId: number;
}
export type BallotActionTypes = ElectionAction | VoteAction;
function reducer(ballot: BallotContextInterface, action: BallotActionTypes) {
/**
* Manage all types of action doable on an election
*/
switch (action.type) {
case BallotTypes.ELECTION: {
return {...ballot, election: action.election}
}
case BallotTypes.VOTE: {
const votes = [...ballot.votes];
const voteForCandidate = votes.filter(v => v.candidateId === action.candidateId);
if (voteForCandidate.length > 1) {
throw Error("Inconsistent ballot")
}
if (voteForCandidate.length === 1) {
voteForCandidate[0].candidateId = action.candidateId;
voteForCandidate[0].gradeId = action.gradeId;
} else {
votes.push({
candidateId: action.candidateId,
gradeId: action.gradeId,
})
}
return {...ballot, votes};
}
default: {
return ballot
}
}
}
type DispatchType = Dispatch<BallotActionTypes>;
const BallotContext = createContext<[BallotContextInterface, DispatchType]>([defaultBallot, () => {}]);
export function BallotProvider({children}) {
/**
* Provide the election and the dispatch to all children components
*/
const [ballot, dispatch] = useReducer(reducer, defaultBallot);
return (
<BallotContext.Provider value={[ballot, dispatch]}>
{children}
</BallotContext.Provider>
);
}
export function useBallot() {
/**
* A simple hook to manage ballots
*/
return useContext(BallotContext);
}