Skip to content

Commit

Permalink
Merge pull request #374 from mikefranze/main
Browse files Browse the repository at this point in the history
Adding election context provider
  • Loading branch information
mikefranze authored Oct 18, 2023
2 parents d733daf + 95f1512 commit 6b2003c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 30 deletions.
61 changes: 31 additions & 30 deletions frontend/src/components/Election/Election.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useEffect } from "react"
import { useParams } from "react-router";
import React from 'react'
import ElectionHome from "./ElectionHome";
Expand All @@ -11,43 +10,45 @@ import Sidebar from "./Sidebar";
import { Grid } from "@mui/material";
import Thanks from "./Voting/Thanks";
import ViewBallot from "./Admin/ViewBallot";
import { IAuthSession } from "../../hooks/useAuthSession";
import { useGetElection } from "../../hooks/useAPI";
import { IAuthSession } from "../../hooks/useAuthSession"
import useElection, { ElectionContextProvider } from "../ElectionContextProvider";

type Props = {
authSession: IAuthSession,
}

const TempWrapper = ({ authSession }: Props) => {
//Temporary wrapper to get election component inputs
//Once components are converted to use election context this can be removed

const { data, election, refreshElection, permissions, updateElection } = useElection()

return (
<Grid container sx={{ mt: { xs: 0, sm: 5 } }}>
<Grid item xs={12} sm={2}>
<Sidebar electionData={data} />
</Grid>
<Grid xs={12} sm={8}>
<Routes>
<Route path='/' element={<ElectionHome authSession={authSession} electionData={data} fetchElection={refreshElection} />} />
<Route path='/vote' element={<VotePage election={data.election} fetchElection={refreshElection} />} />
<Route path='/thanks' element={<Thanks election={data.election} />} />
<Route path='/results' element={<ViewElectionResults election={data.election} />} />
<Route path='/edit' element={<EditElection authSession={authSession} election={data.election} fetchElection={refreshElection} />} />
<Route path='/admin/*' element={<Admin authSession={authSession} election={data.election} permissions={data.voterAuth.permissions} fetchElection={refreshElection} />} />
<Route path='/ballot/:ballot_id' element={<ViewBallot election={data.election} ballot={null} onClose={null} fetchBallot={null} permissions={data.voterAuth.permissions} />} />
<Route path='/id/:voter_id' element={<ElectionHome authSession={authSession} electionData={data} fetchElection={refreshElection} />} />
</Routes>
</Grid>
</Grid >)
}

const Election = ({ authSession }: Props) => {
const { id } = useParams();
const { data, isPending, error, makeRequest: fetchData } = useGetElection(id)
useEffect(() => {
fetchData()
}, [])

return (
<>
{isPending && <div> Loading Election... </div>}
{data != null &&
<Grid container sx={{ mt: { xs: 0, sm: 5 } }}>
<Grid item xs={12} sm={2}>
<Sidebar electionData={data} />
</Grid>
<Grid xs={12} sm={8}>
<Routes>
<Route path='/' element={<ElectionHome authSession={authSession} electionData={data} fetchElection={fetchData} />} />
<Route path='/vote' element={<VotePage election={data.election} fetchElection={fetchData} />} />
<Route path='/thanks' element={<Thanks election={data.election} />} />
<Route path='/results' element={<ViewElectionResults election={data.election} />} />
<Route path='/edit' element={<EditElection authSession={authSession} election={data.election} fetchElection={fetchData} />} />
<Route path='/admin/*' element={<Admin authSession={authSession} election={data.election} permissions={data.voterAuth.permissions} fetchElection={fetchData} />} />
<Route path='/ballot/:ballot_id' element={<ViewBallot election={data.election} ballot={null} onClose={null} fetchBallot={null} permissions={data.voterAuth.permissions} />} />
<Route path='/id/:voter_id' element={<ElectionHome authSession={authSession} electionData={data} fetchElection={fetchData} />} />
</Routes>
</Grid>
</Grid >
}
</>
<ElectionContextProvider id={id}>
<TempWrapper authSession={authSession} />
</ElectionContextProvider>
)
}

Expand Down
60 changes: 60 additions & 0 deletions frontend/src/components/ElectionContextProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, { useContext, useEffect } from 'react'
import { createContext, Dispatch, SetStateAction } from 'react'
import { Election } from '../../../domain_model/Election';
import { useEditElection, useGetElection } from '../hooks/useAPI';
import { Election as IElection } from '../../../domain_model/Election';
import { VoterAuth } from '../../../domain_model/VoterAuth';
import structuredClone from '@ungap/structured-clone';


export interface IElectionContext {
data: {election: Election, voterAuth: VoterAuth}
election: Election;
refreshElection: Function;
updateElection: Function;
permissions: string[]
}


export const ElectionContext = createContext<IElectionContext>({
data: null,
election: null,
refreshElection: () => false,
updateElection: () => false,
permissions: []
}
)

export const ElectionContextProvider = ({ id, children }) => {

const { data, isPending, error, makeRequest: fetchData } = useGetElection(id)
const { makeRequest: editElection } = useEditElection(id)

useEffect(() => {
fetchData()
}, [id])

const applyElectionUpdate = async (updateFunc: (election: IElection) => any) => {
if (!data.election) return
const electionCopy: IElection = structuredClone(data.election)
updateFunc(electionCopy)
return await editElection({ Election: electionCopy })
};


return (<ElectionContext.Provider
value={{
data: data,
election: data?.election,
refreshElection: fetchData,
updateElection: applyElectionUpdate,
permissions: data?.voterAuth?.permissions
}}>
{data && children}
</ElectionContext.Provider>
)
}

export default function useElection() {
return useContext(ElectionContext);
}

0 comments on commit 6b2003c

Please sign in to comment.