diff --git a/packages/chakra-components/src/components/Election/Envelope.tsx b/packages/chakra-components/src/components/Election/Envelope.tsx new file mode 100644 index 00000000..98ebda94 --- /dev/null +++ b/packages/chakra-components/src/components/Election/Envelope.tsx @@ -0,0 +1,116 @@ +import { useDatesLocale, useElection } from '@vocdoni/react-providers' +import { + ElectionResultsTypeNames, + ElectionStatus, + IChoice, + IQuestion, + IVoteEncryptedPackage, + IVotePackage, + PublishedElection, +} from '@vocdoni/sdk' +import { Text } from '@chakra-ui/react' +import { chakra, ChakraProps, useMultiStyleConfig } from '@chakra-ui/system' +import { format } from 'date-fns' + +export type VotePackageType = IVotePackage | IVoteEncryptedPackage + +export const Envelope = ({ + votePackage, + ...props +}: { + votePackage: VotePackageType +} & ChakraProps) => { + const styles = useMultiStyleConfig('Envelope') + const { election, localize } = useElection() + const locale = useDatesLocale() + + if ( + !election || + 'encrypted' in votePackage || + !(election instanceof PublishedElection) || + election?.status === ElectionStatus.CANCELED + ) + return null + + if (election?.electionType.secretUntilTheEnd && election.status !== ElectionStatus.RESULTS) { + return ( + + {localize('results.secret_until_the_end', { + endDate: format(election.endDate, localize('results.date_format'), { locale }), + })} + + ) + } + + return ( + + {election.questions.map((q, i) => { + return ( + + {localize('envelopes.question_title', { title: q.title.default })} + + + ) + })} + + ) +} + +const SelectedOptions = ({ + question, + questionIndex, + votes, +}: { + question: IQuestion + questionIndex: number + votes: number[] +}) => { + const { election, localize } = useElection() + const styles = useMultiStyleConfig('Envelope') + + if (!election || !(election instanceof PublishedElection)) return null + + const selectedOptions: IChoice[] = [] + switch (election.resultsType.name) { + case ElectionResultsTypeNames.MULTIPLE_CHOICE: + const abstainValues = election.resultsType?.properties?.abstainValues ?? [] + let abstainCount = 0 + votes.forEach((v) => { + if (abstainValues.includes(v.toString())) { + abstainCount++ + return + } + selectedOptions.push(question.choices[v]) + }) + if (abstainCount > 0) { + selectedOptions.push({ + title: { + default: localize('envelopes.envelope_abstain_count', { count: abstainCount }), + }, + results: abstainCount.toString(), + value: -1, + } as IChoice) + } + break + case ElectionResultsTypeNames.APPROVAL: + votes.forEach((v, i) => { + if (v > 0) selectedOptions.push(question.choices[i]) + }) + break + case ElectionResultsTypeNames.SINGLE_CHOICE_MULTIQUESTION: + selectedOptions.push(question.choices[votes[questionIndex]]) + break + default: + selectedOptions.push(question.choices[votes[0]]) + } + + return ( + <> + {selectedOptions.map((c, i) => ( + + {c.title.default} + + ))} + + ) +} diff --git a/packages/chakra-components/src/components/Election/index.tsx b/packages/chakra-components/src/components/Election/index.tsx index 8e676627..dcafec5c 100644 --- a/packages/chakra-components/src/components/Election/index.tsx +++ b/packages/chakra-components/src/components/Election/index.tsx @@ -1,5 +1,6 @@ export * from './Actions' export * from './Description' +export * from './Envelope' export * from './Election' export * from './Header' export * from './Questions' diff --git a/packages/chakra-components/src/i18n/locales.ts b/packages/chakra-components/src/i18n/locales.ts index 2015c922..addaa82b 100644 --- a/packages/chakra-components/src/i18n/locales.ts +++ b/packages/chakra-components/src/i18n/locales.ts @@ -28,6 +28,10 @@ export const locales = { end_process_button: 'End process', }, empty: 'Apparently this process has no questions 🤔', + envelopes: { + envelope_abstain_count: 'Abstained {{ count }} times', + question_title: 'Option/s selected in "{{ title }}":', + }, errors: { wrong_data_title: 'Wrong data', wrong_data_description: 'The specified data is not correct', diff --git a/packages/chakra-components/src/theme/envelope.ts b/packages/chakra-components/src/theme/envelope.ts new file mode 100644 index 00000000..f2381443 --- /dev/null +++ b/packages/chakra-components/src/theme/envelope.ts @@ -0,0 +1,38 @@ +import { createMultiStyleConfigHelpers } from '@chakra-ui/styled-system' + +export const envelopeAnatomy = [ + // all questions wrapper + 'wrapper', + // individual question wrapper + 'question', + // question title + 'title', + // choice wrapper + 'choiceWrapper', + // choice title + 'choiceTitle', + // secret envelope (no results until the end text) + 'secret', +] + +const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(envelopeAnatomy) + +const baseStyle = definePartsStyle({ + wrapper: { + flexDirection: 'column', + gap: 2, + }, + title: { + pb: 0, + fontWeight: 'bold', + }, + secret: { + color: 'red.200', + textAlign: 'center', + fontWeight: 'bold', + }, +}) + +export const EnvelopeTheme = defineMultiStyleConfig({ + baseStyle, +}) diff --git a/packages/chakra-components/src/theme/index.ts b/packages/chakra-components/src/theme/index.ts index 60c70bd2..8ac4bcc0 100644 --- a/packages/chakra-components/src/theme/index.ts +++ b/packages/chakra-components/src/theme/index.ts @@ -2,16 +2,18 @@ import { ConfirmModalTheme } from './confirm' import { ElectionScheduleTheme as ElectionSchedule, ElectionTitleTheme as ElectionTitle } from './election' import { HorizontalRulerTheme } from './layout' import { - QuestionsTheme as ElectionQuestions, QuestionsConfirmationTheme, + QuestionsTheme as ElectionQuestions, QuestionsTipTheme, QuestionsTypeBadgeTheme, } from './questions' import { ResultsTheme as ElectionResults } from './results' import { VoteWeightTheme } from './vote' +import { EnvelopeTheme } from './envelope' export const theme = { components: { + Envelope: EnvelopeTheme, ElectionQuestions, ElectionResults, ElectionSchedule, @@ -27,6 +29,7 @@ export const theme = { export * from './actions' export * from './confirm' +export * from './envelope' export * from './election' export * from './layout' export * from './questions'