Skip to content

Commit

Permalink
Implement MultipleElectionVoted
Browse files Browse the repository at this point in the history
  • Loading branch information
selankon committed Oct 22, 2024
1 parent 8691569 commit ec21eae
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,14 +92,17 @@ const useMultiElectionsProvider = ({
const [electionsStates, setElectionsStates] = useState<ElectionStateStorage>({})
const [voting, setVoting] = useState<boolean>(false)

const electionsEmpty = Object.values(electionsStates).length === 0

const voted = useMemo(
() => (electionsStates && Object.values(electionsStates).every(({ voted }) => voted) ? 'true' : null),
[electionsStates]
() =>
electionsStates && !electionsEmpty && Object.values(electionsStates).every(({ voted }) => voted) ? 'true' : null,
[electionsStates, electionsEmpty]
)

const isAbleToVote = useMemo(
() => electionsStates && Object.values(electionsStates).some(({ isAbleToVote }) => isAbleToVote),
[electionsStates]
() => electionsStates && !electionsEmpty && Object.values(electionsStates).some(({ isAbleToVote }) => isAbleToVote),
[electionsStates, electionsEmpty]
)

// Add an election to the storage
Expand Down Expand Up @@ -162,7 +165,7 @@ const useMultiElectionsProvider = ({

setVoting(true)

const votingList = Object.entries(electionsStates).map(([key, { election, vote, voted, isAbleToVote }]) => {
const votingList = Object.entries(electionsStates).map(([key, { election, vote, isAbleToVote }]) => {
if (!(election instanceof PublishedElection) || !values[election.id] || !isAbleToVote) {
return Promise.resolve()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ import { FieldValues, SubmitErrorHandler, ValidateResult } from 'react-hook-form
import { QuestionField } from './Fields'
import { QuestionsFormProvider, QuestionsFormProviderProps, useQuestionsForm } from './Form'
import { QuestionsTypeBadge } from './TypeBadge'
import { Voted } from './Voted'
import { MultiElectionVoted, Voted } from './Voted'
import { FormControl, FormErrorMessage } from '@chakra-ui/form-control'
import { useEffect, useMemo, useState } from 'react'
import { Flex } from '@chakra-ui/layout'

export type RenderWith = {
id: string
Expand All @@ -34,7 +33,7 @@ export const ElectionQuestions = ({ confirmContents, ...props }: ElectionQuestio

export const ElectionQuestionsForm = ({ formId, onInvalid, ...rest }: ElectionQuestionsFormProps) => {
const styles = useMultiStyleConfig('ElectionQuestions')
const { fmethods, voteAll, validate, renderWith } = useQuestionsForm()
const { fmethods, voteAll, validate, renderWith, voted, isAbleToVote } = useQuestionsForm()
const { ConnectButton, election } = useElection() // use Root election information
const [globalError, setGlobalError] = useState('')

Expand All @@ -58,6 +57,7 @@ export const ElectionQuestionsForm = ({ formId, onInvalid, ...rest }: ElectionQu
return (
<form onSubmit={handleSubmit(onSubmit, onInvalid)} id={formId ?? `election-questions-${election.id}`}>
<chakra.div __css={styles.elections}>
<MultiElectionVoted />
<ElectionQuestion {...rest} />
{renderWith?.length > 0 &&
renderWith.map(({ id }) => (
Expand Down Expand Up @@ -87,7 +87,7 @@ export const ElectionQuestion = (props: ChakraProps) => {
if (!(election instanceof PublishedElection)) return null

if (voted && !isAbleToVote) {
return <Voted />
return null
}

if (!questions || (questions && !questions?.length)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
import { Alert, AlertDescription, AlertIcon, AlertTitle } from '@chakra-ui/alert'
import { Link } from '@chakra-ui/layout'
import { useMultiStyleConfig } from '@chakra-ui/system'
import { chakra, useMultiStyleConfig } from '@chakra-ui/system'
import { useClient, useElection } from '@vocdoni/react-providers'
import reactStringReplace from 'react-string-replace'
import { environment } from '../../../environment'
import { useQuestionsForm } from './Form'

export const MultiElectionVoted = () => {
const { voted, elections } = useQuestionsForm()
if (!voted) {
return null
}
const votes = Object.values(elections).map((e) => e.voted)
return <VotedLogic voteds={votes} />
}

export const Voted = () => {
const { env } = useClient()
const { localize, voted } = useElection()
const { voted } = useElection()
if (!voted) {
return null
}
return <VotedLogic voteds={[voted]} />
}

interface IVotedLogicProps {
voteds: string[]
}

const VotedLogic = ({ voteds }: IVotedLogicProps) => {
const { localize } = useElection()
const styles = useMultiStyleConfig('ElectionQuestions')

if (!voted) {
if (!(voteds?.length > 0)) {
return null
}

Expand All @@ -28,12 +49,45 @@ export const Voted = () => {
<AlertIcon />
<AlertTitle sx={styles.alertTitle}>{localize('vote.voted_title')}</AlertTitle>
<AlertDescription isTruncated maxW='100%' whiteSpace='initial' sx={styles.alertDescription}>
{reactStringReplace(localize('vote.voted_description', { id: voted }), voted, (match, k) => (
<Link key={k} href={environment.verifyVote(env, voted)} target='_blank' isTruncated sx={styles.alertLink}>
{match}
</Link>
))}
{voteds.length === 1 ? <SingleElectionVoted voted={voteds[0]} /> : <MultipleElectionVoted voteds={voteds} />}
</AlertDescription>
</Alert>
)
}

const SingleElectionVoted = ({ voted }: { voted: string }) => {
const { localize } = useElection()
const { env } = useClient()
const styles = useMultiStyleConfig('ElectionQuestions')
return reactStringReplace(localize('vote.voted_description', { id: voted }), voted, (match, k) => (
<Link key={k} href={environment.verifyVote(env, voted)} target='_blank' isTruncated sx={styles.alertLink}>
{match}
</Link>
))
}

const MultipleElectionVoted = ({ voteds }: IVotedLogicProps) => {
const { localize } = useElection()
const { env } = useClient()
const styles = useMultiStyleConfig('ElectionQuestions')
const votedsString = voteds.join(',')
return (
<chakra.div __css={styles.alertDescriptionWrapper}>
{reactStringReplace(localize('vote.voted_description_multielection', { ids: votedsString }), votedsString, () => (
<>
{voteds.map((voted) => (
<Link
key={voted}
href={environment.verifyVote(env, voted)}
target='_blank'
isTruncated
sx={styles.alertLink}
>
{voted}
</Link>
))}
</>
))}
</chakra.div>
)
}
1 change: 1 addition & 0 deletions packages/chakra-components/src/i18n/locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ export const locales = {
confirm: 'Please confirm your choices:',
sign: 'Sign first',
voted_description: 'Your vote id is {{ id }}. You can use it to verify your vote.',
voted_description_multielection: 'Your vote ids are: {{ ids }} You can use its to verify your votes.',
voted_title: 'Your vote was successfully cast!',
weight: 'Your voting power is: ',
},
Expand Down
1 change: 1 addition & 0 deletions packages/chakra-components/src/theme/questions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const questionsAnatomy = [
'alert',
'alertTitle',
'alertDescription',
'alertDescriptionWrapper', // Wrapper for multielection voted message
'alertLink',
// elections wrapper for multielections
'elections',
Expand Down

0 comments on commit ec21eae

Please sign in to comment.