Refactor votingCards (#71)
This commit is contained in:
parent
98fb2ea515
commit
983f557fbc
|
@ -73,6 +73,7 @@ export class WakuVoting extends WakuMessaging {
|
|||
this.lastGetPollsBlockNumber = blockNumber
|
||||
const polls = await this.votingContract.getVotingRooms()
|
||||
this.lastPolls = polls.map((poll: any, idx: number): VotingRoom => {
|
||||
const timeLeft = poll[1].toNumber() - Date.now() / 1000
|
||||
return {
|
||||
startBlock: poll[0],
|
||||
endAt: poll[1],
|
||||
|
@ -82,12 +83,18 @@ export class WakuVoting extends WakuMessaging {
|
|||
totalVotesAgainst: poll[5],
|
||||
voters: poll[6],
|
||||
id: idx,
|
||||
timeLeft,
|
||||
voteWinner: timeLeft <= 0 ? (poll[5].gt(poll[4]) ? 1 : 2) : undefined,
|
||||
}
|
||||
})
|
||||
}
|
||||
return this.lastPolls
|
||||
}
|
||||
|
||||
public async getVotingRoom(id: number) {
|
||||
return (await this.getVotingRooms())[id]
|
||||
}
|
||||
|
||||
public async sendVote(
|
||||
signer: JsonRpcSigner | Wallet,
|
||||
roomId: number,
|
||||
|
|
|
@ -14,4 +14,6 @@ export type VotingRoom = {
|
|||
totalVotesAgainst: BigNumber
|
||||
voters: string[]
|
||||
id: number
|
||||
timeLeft: number
|
||||
voteWinner: number | undefined
|
||||
}
|
||||
|
|
|
@ -4,35 +4,22 @@ import styled from 'styled-components'
|
|||
import { Theme } from '@status-waku-voting/react-components'
|
||||
import { ProposalInfo } from './ProposalInfo'
|
||||
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
interface ProposalCardProps {
|
||||
id: number
|
||||
theme: Theme
|
||||
heading: string
|
||||
text: string
|
||||
address: string
|
||||
votingRoom: VotingRoom
|
||||
mobileVersion?: boolean
|
||||
vote?: number
|
||||
voteWinner?: number
|
||||
theme: Theme
|
||||
hideModalFunction?: (val: boolean) => void
|
||||
}
|
||||
|
||||
export function ProposalCard({
|
||||
id,
|
||||
heading,
|
||||
text,
|
||||
address,
|
||||
vote,
|
||||
voteWinner,
|
||||
theme,
|
||||
mobileVersion,
|
||||
}: ProposalCardProps) {
|
||||
export function ProposalCard({ theme, votingRoom, mobileVersion }: ProposalCardProps) {
|
||||
const history = useHistory()
|
||||
|
||||
return (
|
||||
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${id.toString}`)}>
|
||||
<ProposalInfo heading={heading} text={text} address={address} />
|
||||
<ProposalVote vote={vote} voteWinner={voteWinner} address={address} heading={heading} theme={theme} />
|
||||
<Card onClick={() => mobileVersion && history.push(`/votingRoom/${votingRoom.id.toString()}`)}>
|
||||
<ProposalInfo votingRoom={votingRoom} />
|
||||
<ProposalVote votingRoom={votingRoom} theme={theme} />
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { ViewLink } from './ViewLink'
|
||||
|
||||
type ProposalInfoProps = {
|
||||
heading: string
|
||||
text: string
|
||||
address: string
|
||||
votingRoom: VotingRoom
|
||||
mobileMode?: boolean
|
||||
}
|
||||
|
||||
export function ProposalInfo({ heading, text, address, mobileMode }: ProposalInfoProps) {
|
||||
export function ProposalInfo({ votingRoom, mobileMode }: ProposalInfoProps) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeading>{heading}</CardHeading>
|
||||
<CardText className={mobileMode ? 'mobile' : ''}>{text}</CardText>
|
||||
<CardHeading>{votingRoom.question}</CardHeading>
|
||||
<CardText className={mobileMode ? 'mobile' : ''}>{votingRoom.description}</CardText>
|
||||
<CardViewLink className={mobileMode ? 'mobile' : ''}>
|
||||
<ViewLink address={address} />
|
||||
<ViewLink address={'#'} />
|
||||
</CardViewLink>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -16,18 +16,8 @@ export function ProposalList({ theme, wakuVoting, votes }: ProposalListProps) {
|
|||
const mobileVersion = useMobileVersion(ref, 600)
|
||||
return (
|
||||
<List ref={ref}>
|
||||
{votes.map((vote) => {
|
||||
return (
|
||||
<ProposalCard
|
||||
heading={vote.question}
|
||||
text={vote.description}
|
||||
address={'#'}
|
||||
theme={theme}
|
||||
key={vote.id}
|
||||
id={vote.id}
|
||||
mobileVersion={mobileVersion}
|
||||
/>
|
||||
)
|
||||
{votes.map((votingRoom) => {
|
||||
return <ProposalCard votingRoom={votingRoom} theme={theme} key={votingRoom.id} mobileVersion={mobileVersion} />
|
||||
})}
|
||||
</List>
|
||||
)
|
||||
|
|
|
@ -8,17 +8,15 @@ import { ViewLink } from '../ViewLink'
|
|||
import { Modal, Theme } from '@status-waku-voting/react-components'
|
||||
import { VoteModal } from '../VoteModal'
|
||||
import { VoteAnimatedModal } from '../VoteAnimatedModal'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
interface ProposalVoteProps {
|
||||
theme: Theme
|
||||
vote?: number
|
||||
voteWinner?: number
|
||||
heading: string
|
||||
address: string
|
||||
votingRoom: VotingRoom
|
||||
hideModalFunction?: (val: boolean) => void
|
||||
}
|
||||
|
||||
export function ProposalVote({ vote, voteWinner, address, heading, theme, hideModalFunction }: ProposalVoteProps) {
|
||||
export function ProposalVote({ votingRoom, theme, hideModalFunction }: ProposalVoteProps) {
|
||||
const { account } = useEthers()
|
||||
const [showVoteModal, setShowVoteModal] = useState(false)
|
||||
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||
|
@ -40,11 +38,9 @@ export function ProposalVote({ vote, voteWinner, address, heading, theme, hideMo
|
|||
return (
|
||||
<Card>
|
||||
{showVoteModal && (
|
||||
<Modal heading={heading} setShowModal={setShowVoteModal} theme={theme}>
|
||||
<Modal heading={votingRoom.question} setShowModal={setShowVoteModal} theme={theme}>
|
||||
<VoteModal
|
||||
votesFor={1865567}
|
||||
votesAgainst={1740235}
|
||||
timeLeft={4855555577}
|
||||
votingRoom={votingRoom}
|
||||
availableAmount={65245346}
|
||||
selectedVote={selectedVoted}
|
||||
proposingAmount={proposingAmount}
|
||||
|
@ -54,29 +50,25 @@ export function ProposalVote({ vote, voteWinner, address, heading, theme, hideMo
|
|||
</Modal>
|
||||
)}
|
||||
{showConfirmModal && (
|
||||
<Modal heading={heading} setShowModal={hideConfirm} theme={theme}>
|
||||
<Modal heading={votingRoom.question} setShowModal={hideConfirm} theme={theme}>
|
||||
<VoteAnimatedModal
|
||||
votesFor={1865567}
|
||||
votesAgainst={1740235}
|
||||
timeLeft={4855555577}
|
||||
votingRoom={votingRoom}
|
||||
selectedVote={selectedVoted}
|
||||
setShowModal={hideConfirm}
|
||||
proposingAmount={proposingAmount}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{voteWinner ? <CardHeading>Proposal {voteWinner == 1 ? 'rejected' : 'passed'}</CardHeading> : <CardHeading />}
|
||||
{votingRoom.voteWinner ? (
|
||||
<CardHeading>Proposal {votingRoom.voteWinner == 1 ? 'rejected' : 'passed'}</CardHeading>
|
||||
) : (
|
||||
<CardHeading />
|
||||
)}
|
||||
|
||||
<VoteChart
|
||||
votesFor={1865567}
|
||||
votesAgainst={1740235}
|
||||
timeLeft={4855555577}
|
||||
voteWinner={voteWinner}
|
||||
selectedVote={selectedVoted}
|
||||
/>
|
||||
<VoteChart votingRoom={votingRoom} selectedVote={selectedVoted} />
|
||||
|
||||
<CardButtons>
|
||||
{voteWinner ? (
|
||||
{votingRoom.voteWinner ? (
|
||||
<FinalBtn disabled={!account}>Finalize the vote</FinalBtn>
|
||||
) : (
|
||||
<VotesBtns>
|
||||
|
@ -105,9 +97,9 @@ export function ProposalVote({ vote, voteWinner, address, heading, theme, hideMo
|
|||
<CardVoteBottom>
|
||||
<CardViewLink>
|
||||
{' '}
|
||||
<ViewLink address={address} />
|
||||
<ViewLink address={'#'} />
|
||||
</CardViewLink>
|
||||
{vote && <VoteSubmitButton votes={vote} disabled={!account} />}
|
||||
<VoteSubmitButton votes={15} disabled={!account} />
|
||||
</CardVoteBottom>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useRef } from 'react'
|
||||
import React, { useMemo, useRef } from 'react'
|
||||
import CountUp from 'react-countup'
|
||||
import styled from 'styled-components'
|
||||
import { addCommas } from '../../helpers/addCommas'
|
||||
|
@ -9,43 +9,39 @@ import crossWinnerIcon from '../../assets/svg/crossWinner.svg'
|
|||
import checkIcon from '../../assets/svg/check.svg'
|
||||
import checkWinnerIcon from '../../assets/svg/checkWinner.svg'
|
||||
import { useMobileVersion } from '@status-waku-voting/react-components'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
export interface VoteChartProps {
|
||||
votesFor: number
|
||||
votesAgainst: number
|
||||
timeLeft: number
|
||||
voteWinner?: number
|
||||
votingRoom: VotingRoom
|
||||
proposingAmount?: number
|
||||
selectedVote?: number
|
||||
isAnimation?: boolean
|
||||
tabletMode?: (val: boolean) => void
|
||||
}
|
||||
|
||||
export function VoteChart({
|
||||
votesFor,
|
||||
votesAgainst,
|
||||
timeLeft,
|
||||
voteWinner,
|
||||
proposingAmount,
|
||||
selectedVote,
|
||||
isAnimation,
|
||||
tabletMode,
|
||||
}: VoteChartProps) {
|
||||
export function VoteChart({ votingRoom, proposingAmount, selectedVote, isAnimation, tabletMode }: VoteChartProps) {
|
||||
const ref = useRef<HTMLHeadingElement>(null)
|
||||
const mobileVersion = useMobileVersion(ref, 600)
|
||||
|
||||
const voteSum = votesFor + votesAgainst
|
||||
const graphWidth = (100 * votesAgainst) / voteSum
|
||||
const voteSum = useMemo(
|
||||
() => votingRoom.totalVotesFor.add(votingRoom.totalVotesAgainst),
|
||||
[votingRoom.totalVotesFor.toString(), votingRoom.totalVotesAgainst.toString()]
|
||||
)
|
||||
const graphWidth = useMemo(() => votingRoom.totalVotesAgainst.mul(100).div(voteSum).toNumber(), [voteSum])
|
||||
|
||||
let balanceWidth = graphWidth
|
||||
|
||||
if (proposingAmount) {
|
||||
balanceWidth =
|
||||
selectedVote === 0
|
||||
? (100 * (votesAgainst + proposingAmount)) / (voteSum + proposingAmount)
|
||||
: (100 * votesAgainst) / (voteSum + proposingAmount)
|
||||
}
|
||||
const balanceWidth = useMemo(() => {
|
||||
if (!proposingAmount) {
|
||||
return graphWidth
|
||||
} else {
|
||||
const divider = voteSum.add(proposingAmount)
|
||||
return selectedVote === 0
|
||||
? votingRoom.totalVotesAgainst.add(proposingAmount).mul(100).div(divider).toNumber()
|
||||
: votingRoom.totalVotesAgainst.mul(100).div(divider).toNumber()
|
||||
}
|
||||
}, [graphWidth, voteSum, proposingAmount])
|
||||
|
||||
const timeLeft = useMemo(() => votingRoom.timeLeft, [votingRoom.timeLeft])
|
||||
const voteWinner = useMemo(() => votingRoom.voteWinner, [votingRoom.voteWinner])
|
||||
return (
|
||||
<Votes ref={ref}>
|
||||
<VotesChart className={selectedVote || tabletMode ? '' : 'notModal'}>
|
||||
|
@ -65,9 +61,9 @@ export function VoteChart({
|
|||
<span>
|
||||
{' '}
|
||||
{isAnimation && proposingAmount && selectedVote && selectedVote === 0 ? (
|
||||
<CountUp end={votesAgainst + proposingAmount} separator="," />
|
||||
<CountUp end={votingRoom.totalVotesAgainst.toNumber() + proposingAmount} separator="," />
|
||||
) : (
|
||||
addCommas(votesAgainst)
|
||||
addCommas(votingRoom.totalVotesAgainst.toNumber())
|
||||
)}{' '}
|
||||
<span style={{ fontWeight: 'normal' }}>ABC</span>
|
||||
</span>
|
||||
|
@ -89,9 +85,9 @@ export function VoteChart({
|
|||
<span>
|
||||
{' '}
|
||||
{isAnimation && proposingAmount && selectedVote && selectedVote === 1 ? (
|
||||
<CountUp end={votesFor + proposingAmount} separator="," />
|
||||
<CountUp end={votingRoom.totalVotesFor.toNumber() + proposingAmount} separator="," />
|
||||
) : (
|
||||
addCommas(votesFor)
|
||||
addCommas(votingRoom.totalVotesFor.toNumber())
|
||||
)}{' '}
|
||||
<span style={{ fontWeight: 'normal' }}>ABC</span>
|
||||
</span>
|
||||
|
|
|
@ -1,32 +1,22 @@
|
|||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { FinalBtn } from './Buttons'
|
||||
import { VoteChart } from './ProposalVoteCard/VoteChart'
|
||||
|
||||
interface VoteAnimatedModalProps {
|
||||
votesFor: number
|
||||
votesAgainst: number
|
||||
timeLeft: number
|
||||
votingRoom: VotingRoom
|
||||
proposingAmount: number
|
||||
selectedVote: number
|
||||
setShowModal: (val: boolean) => void
|
||||
}
|
||||
|
||||
export function VoteAnimatedModal({
|
||||
votesFor,
|
||||
votesAgainst,
|
||||
timeLeft,
|
||||
selectedVote,
|
||||
proposingAmount,
|
||||
setShowModal,
|
||||
}: VoteAnimatedModalProps) {
|
||||
export function VoteAnimatedModal({ votingRoom, selectedVote, proposingAmount, setShowModal }: VoteAnimatedModalProps) {
|
||||
return (
|
||||
<VoteConfirm>
|
||||
<ConfirmText>Your vote {selectedVote === 0 ? 'against' : 'for'} this proposal has been cast!</ConfirmText>
|
||||
<VoteChart
|
||||
votesFor={votesFor}
|
||||
votesAgainst={votesAgainst}
|
||||
timeLeft={timeLeft}
|
||||
votingRoom={votingRoom}
|
||||
proposingAmount={proposingAmount}
|
||||
selectedVote={selectedVote}
|
||||
isAnimation={true}
|
||||
|
|
|
@ -3,24 +3,19 @@ import styled from 'styled-components'
|
|||
import { VoteChart } from './ProposalVoteCard/VoteChart'
|
||||
import { DisabledButton, VoteBtnAgainst, VoteBtnFor } from './Buttons'
|
||||
import { VotePropose } from './VotePropose'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
export interface VoteModalProps {
|
||||
votesFor: number
|
||||
votesAgainst: number
|
||||
timeLeft: number
|
||||
voteWinner?: number
|
||||
selectedVote: number
|
||||
votingRoom: VotingRoom
|
||||
availableAmount: number
|
||||
selectedVote: number
|
||||
proposingAmount: number
|
||||
setShowConfirmModal: (show: boolean) => void
|
||||
setProposingAmount: (val: number) => void
|
||||
}
|
||||
|
||||
export function VoteModal({
|
||||
votesFor,
|
||||
votesAgainst,
|
||||
timeLeft,
|
||||
voteWinner,
|
||||
votingRoom,
|
||||
selectedVote,
|
||||
availableAmount,
|
||||
proposingAmount,
|
||||
|
@ -32,14 +27,7 @@ export function VoteModal({
|
|||
|
||||
return (
|
||||
<Column>
|
||||
<VoteChart
|
||||
votesFor={votesFor}
|
||||
votesAgainst={votesAgainst}
|
||||
timeLeft={timeLeft}
|
||||
voteWinner={voteWinner}
|
||||
proposingAmount={proposingAmount}
|
||||
selectedVote={selectedVote}
|
||||
/>
|
||||
<VoteChart votingRoom={votingRoom} proposingAmount={proposingAmount} selectedVote={selectedVote} />
|
||||
<VotePropose
|
||||
availableAmount={availableAmount}
|
||||
setProposingAmount={setProposingAmount}
|
||||
|
|
|
@ -17,7 +17,9 @@ export function ProposalMobile({ wakuVoting }: ProposalMobileProps) {
|
|||
<ProposalWrapper>
|
||||
<Switch>
|
||||
<Route exact path="/" render={() => <Redirect to="/proposal" />} />
|
||||
<Route exact path="/votingRoom/:id" component={ProposalVoteMobile} />
|
||||
<Route exact path="/votingRoom/:id">
|
||||
<ProposalVoteMobile wakuVoting={wakuVoting} availableAmount={123} />
|
||||
</Route>
|
||||
<Route exact path="/creation" component={ProposeMobile} />
|
||||
<Route exact path="/proposal">
|
||||
<ProposalMainMobile wakuVoting={wakuVoting} />
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useMemo, useState } from 'react'
|
||||
import { useParams } from 'react-router'
|
||||
import styled from 'styled-components'
|
||||
import { useEthers } from '@usedapp/core'
|
||||
|
@ -8,48 +8,31 @@ import { VoteChart } from '../ProposalVoteCard/VoteChart'
|
|||
import { ProposalInfo } from '../ProposalInfo'
|
||||
import { VotePropose } from '../VotePropose'
|
||||
import { VotesBtns } from '../ProposalVoteCard/ProposalVote'
|
||||
|
||||
import { useVotingRoom } from '@status-waku-voting/proposal-hooks'
|
||||
import { WakuVoting } from '@status-waku-voting/core'
|
||||
interface ProposalVoteMobileProps {
|
||||
vote?: number
|
||||
voteWinner?: number
|
||||
votesFor: number
|
||||
votesAgainst: number
|
||||
timeLeft: number
|
||||
wakuVoting: WakuVoting
|
||||
availableAmount: number
|
||||
heading: string
|
||||
text: string
|
||||
address: string
|
||||
}
|
||||
|
||||
export function ProposalVoteMobile({
|
||||
votesFor,
|
||||
votesAgainst,
|
||||
timeLeft,
|
||||
vote,
|
||||
voteWinner,
|
||||
address,
|
||||
heading,
|
||||
text,
|
||||
availableAmount,
|
||||
}: ProposalVoteMobileProps) {
|
||||
export function ProposalVoteMobile({ wakuVoting, availableAmount }: ProposalVoteMobileProps) {
|
||||
const { id } = useParams<{ id: string }>()
|
||||
const { account } = useEthers()
|
||||
const [proposingAmount, setProposingAmount] = useState(0)
|
||||
const [selectedVoted, setSelectedVoted] = useState(0)
|
||||
const [mobileVersion, setMobileVersion] = useState(true)
|
||||
const votingRoom = useVotingRoom(Number(id), wakuVoting)
|
||||
|
||||
const voteWinner = useMemo(() => votingRoom?.voteWinner, [votingRoom?.voteWinner])
|
||||
|
||||
if (!votingRoom) {
|
||||
return <>Loading</>
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<ProposalInfo
|
||||
heading={'This is a very long, explainative and sophisticated title for a proposal.'}
|
||||
text={
|
||||
'This is a longer description of the proposal. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales. Nullam mattis fermentum libero, non volutpat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales. Nullam mattis fermentum libero. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales. Nullam mattis fermentum libero.'
|
||||
}
|
||||
address={'#'}
|
||||
mobileMode={mobileVersion}
|
||||
/>
|
||||
<ProposalInfo votingRoom={votingRoom} mobileMode={true} />
|
||||
<VoteChartWrap>
|
||||
<VoteChart votesFor={1865567} votesAgainst={1740235} timeLeft={4855555577} selectedVote={selectedVoted} />
|
||||
<VoteChart votingRoom={votingRoom} selectedVote={selectedVoted} />
|
||||
</VoteChartWrap>
|
||||
{!voteWinner && (
|
||||
<VotePropose
|
||||
|
@ -86,7 +69,7 @@ export function ProposalVoteMobile({
|
|||
|
||||
<CardVoteBottom>
|
||||
{' '}
|
||||
<VoteSubmitButton votes={2345678} disabled={!account} />
|
||||
<VoteSubmitButton votes={15} disabled={!account} />
|
||||
</CardVoteBottom>
|
||||
</Card>
|
||||
)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { WakuVoting } from '@status-waku-voting/core'
|
||||
import { VotingRoom } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
|
||||
export function useVotingRoom(id: number, wakuVoting: WakuVoting) {
|
||||
const [votingRoom, setVotingRoom] = useState<VotingRoom | undefined>(undefined)
|
||||
|
||||
useEffect(() => {
|
||||
const updateFunction = async () => {
|
||||
setVotingRoom(await wakuVoting.getVotingRoom(id))
|
||||
}
|
||||
updateFunction()
|
||||
const interval = setInterval(updateFunction, 10000)
|
||||
return () => clearInterval(interval)
|
||||
}, [id])
|
||||
|
||||
return votingRoom
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
import { useWakuProposal } from './hooks/useWakuProposal'
|
||||
|
||||
export { useWakuProposal }
|
||||
import { useVotingRoom } from './hooks/useVotingRoom'
|
||||
export { useWakuProposal, useVotingRoom }
|
||||
|
|
Loading…
Reference in New Issue