Add confirm animation (#76)
This commit is contained in:
parent
e7c749f658
commit
ca92e2e71b
|
@ -17,6 +17,7 @@ import { useContracts } from '../hooks/useContracts'
|
|||
import { getVotingWinner } from '../helpers/voting'
|
||||
import { useVotesAggregate } from '../hooks/useVotesAggregate'
|
||||
import rightIcon from '../assets/images/arrowRight.svg'
|
||||
import { VoteAnimatedModal } from './card/VoteAnimatedModal'
|
||||
|
||||
interface CardCommunityProps {
|
||||
community: CommunityDetail
|
||||
|
@ -142,6 +143,10 @@ export const CardVote = ({ community, room, hideModalFunction }: CardVoteProps)
|
|||
const voteConstants = voteTypes[vote.type]
|
||||
|
||||
const winner = getVotingWinner(vote)
|
||||
const availableAmount = 65800076
|
||||
|
||||
const initialProposing = vote?.type === 'Remove' && availableAmount > 2000000 ? 2000000 : 0
|
||||
const [proposingAmount, setProposingAmount] = useState(initialProposing)
|
||||
|
||||
return (
|
||||
<CardVoteBlock>
|
||||
|
@ -151,14 +156,22 @@ export const CardVote = ({ community, room, hideModalFunction }: CardVoteProps)
|
|||
vote={vote}
|
||||
room={room}
|
||||
selectedVote={selectedVoted}
|
||||
availableAmount={65245346}
|
||||
availableAmount={availableAmount}
|
||||
proposingAmount={proposingAmount}
|
||||
setShowConfirmModal={setNext}
|
||||
setProposingAmount={setProposingAmount}
|
||||
/>{' '}
|
||||
</Modal>
|
||||
)}
|
||||
{showConfirmModal && (
|
||||
<Modal setShowModal={hideConfirm}>
|
||||
<VoteConfirmModal community={community} selectedVote={selectedVoted} setShowModal={hideConfirm} />
|
||||
<VoteAnimatedModal
|
||||
vote={vote}
|
||||
community={community}
|
||||
selectedVote={selectedVoted}
|
||||
setShowModal={hideConfirm}
|
||||
proposingAmount={proposingAmount}
|
||||
/>
|
||||
</Modal>
|
||||
)}
|
||||
{winner ? (
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { VoteType } from '../../constants/voteTypes'
|
||||
import { CommunityDetail, CurrentVoting } from '../../models/community'
|
||||
import { ButtonSecondary } from '../Button'
|
||||
import { VoteChart } from '../votes/VoteChart'
|
||||
|
||||
interface VoteAnimatedModalProps {
|
||||
community: CommunityDetail
|
||||
vote: CurrentVoting
|
||||
selectedVote: VoteType
|
||||
proposingAmount: number
|
||||
setShowModal: (val: boolean) => void
|
||||
}
|
||||
|
||||
export function VoteAnimatedModal({
|
||||
community,
|
||||
vote,
|
||||
proposingAmount,
|
||||
selectedVote,
|
||||
setShowModal,
|
||||
}: VoteAnimatedModalProps) {
|
||||
return (
|
||||
<VoteConfirm>
|
||||
<ConfirmLogo src={community.icon} alt={`${community.name} logo`} />
|
||||
<ConfirmText>
|
||||
Your vote{' '}
|
||||
<span>
|
||||
{selectedVote.verb} {community.name}
|
||||
</span>{' '}
|
||||
has been cast!
|
||||
</ConfirmText>
|
||||
<VoteChart vote={vote} proposingAmount={proposingAmount} selectedVote={selectedVote} isAnimation={true} />
|
||||
|
||||
<ConfirmBtn onClick={() => setShowModal(false)}>
|
||||
OK, let’s move on! <span>🤙</span>
|
||||
</ConfirmBtn>
|
||||
</VoteConfirm>
|
||||
)
|
||||
}
|
||||
|
||||
const VoteConfirm = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const ConfirmLogo = styled.img`
|
||||
width: 64px !important;
|
||||
height: 64px !important;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 32px;
|
||||
`
|
||||
|
||||
const ConfirmText = styled.div`
|
||||
max-width: 272px;
|
||||
margin-bottom: 32px;
|
||||
text-align: center;
|
||||
line-height: 22px;
|
||||
|
||||
& > span {
|
||||
font-weight: bold;
|
||||
}
|
||||
`
|
||||
|
||||
export const ConfirmBtn = styled(ButtonSecondary)`
|
||||
width: 100%;
|
||||
padding: 11px 0;
|
||||
font-weight: 500;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
|
||||
& > span {
|
||||
font-size: 20px;
|
||||
}
|
||||
`
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { VoteChart } from '../votes/VoteChart'
|
||||
import { ButtonSecondary } from '../Button'
|
||||
|
@ -12,14 +12,21 @@ export interface VoteModalProps {
|
|||
vote: CurrentVoting
|
||||
selectedVote: VoteType
|
||||
availableAmount: number
|
||||
proposingAmount: number
|
||||
room: number
|
||||
setShowConfirmModal: (show: boolean) => void
|
||||
setProposingAmount: (val: number) => void
|
||||
}
|
||||
|
||||
export function VoteModal({ vote, room, selectedVote, availableAmount, setShowConfirmModal }: VoteModalProps) {
|
||||
const initialProposing = vote?.type === 'Remove' && availableAmount > 2000000 ? 2000000 : 0
|
||||
|
||||
const [proposingAmount, setProposingAmount] = useState(initialProposing)
|
||||
export function VoteModal({
|
||||
vote,
|
||||
room,
|
||||
selectedVote,
|
||||
availableAmount,
|
||||
proposingAmount,
|
||||
setShowConfirmModal,
|
||||
setProposingAmount,
|
||||
}: VoteModalProps) {
|
||||
const disabled = proposingAmount === 0
|
||||
const sendWakuVote = useSendWakuVote()
|
||||
|
||||
|
@ -36,8 +43,8 @@ export function VoteModal({ vote, room, selectedVote, availableAmount, setShowCo
|
|||
/>
|
||||
|
||||
<VoteConfirmBtn
|
||||
onClick={() => {
|
||||
sendWakuVote(proposingAmount, room, selectedVote.type)
|
||||
onClick={async () => {
|
||||
await sendWakuVote(proposingAmount, room, selectedVote.type)
|
||||
setShowConfirmModal(true)
|
||||
}}
|
||||
disabled={disabled}
|
||||
|
|
|
@ -13,10 +13,26 @@ export interface VoteChartProps {
|
|||
voteWinner?: number
|
||||
proposingAmount?: number
|
||||
selectedVote?: VoteType
|
||||
isAnimation?: boolean
|
||||
}
|
||||
|
||||
export function VoteChart({ vote, voteWinner, proposingAmount, selectedVote }: VoteChartProps) {
|
||||
export function VoteChart({ vote, voteWinner, proposingAmount, selectedVote, isAnimation }: VoteChartProps) {
|
||||
const voteConstants = voteTypes[vote.type]
|
||||
|
||||
const votesFor = vote.voteFor.toNumber()
|
||||
const votesAgainst = vote.voteAgainst.toNumber()
|
||||
const voteSum = votesFor + votesAgainst
|
||||
const graphWidth = (100 * votesAgainst) / voteSum
|
||||
|
||||
let balanceWidth = graphWidth
|
||||
|
||||
if (proposingAmount && selectedVote) {
|
||||
balanceWidth =
|
||||
selectedVote.type === 0
|
||||
? (100 * (votesAgainst + proposingAmount)) / (voteSum + proposingAmount)
|
||||
: (100 * votesAgainst) / (voteSum + proposingAmount)
|
||||
}
|
||||
|
||||
return (
|
||||
<Votes>
|
||||
<VotesChart>
|
||||
|
@ -42,11 +58,10 @@ export function VoteChart({ vote, voteWinner, proposingAmount, selectedVote }: V
|
|||
</VotesChart>
|
||||
|
||||
<VoteGraphBar
|
||||
votesFor={vote.voteFor.toNumber()}
|
||||
votesAgainst={vote.voteAgainst.toNumber()}
|
||||
graphWidth={graphWidth}
|
||||
balanceWidth={balanceWidth}
|
||||
voteWinner={voteWinner}
|
||||
proposingAmount={proposingAmount}
|
||||
selectedVote={selectedVote}
|
||||
isAnimation={isAnimation}
|
||||
/>
|
||||
</Votes>
|
||||
)
|
||||
|
|
|
@ -1,56 +1,56 @@
|
|||
import React from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Colors } from '../../constants/styles'
|
||||
import indicatorIcon from '../../assets/images/indicator.svg'
|
||||
import { VoteType } from '../../constants/voteTypes'
|
||||
|
||||
function createKeyFrames(votesWidth: number, markerWidth: number) {
|
||||
return `
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
width: ${votesWidth}%;
|
||||
}
|
||||
100% {
|
||||
width: ${markerWidth}%;
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
export interface VoteGraphBarProps {
|
||||
votesAgainst: number
|
||||
votesFor: number
|
||||
balanceWidth?: number
|
||||
graphWidth?: number
|
||||
voteWinner?: number
|
||||
proposingAmount?: number
|
||||
selectedVote?: VoteType
|
||||
isAnimation?: boolean
|
||||
}
|
||||
|
||||
export function VoteGraphBar({ votesFor, votesAgainst, voteWinner, proposingAmount, selectedVote }: VoteGraphBarProps) {
|
||||
const voteSum = votesFor + votesAgainst
|
||||
const graphWidth = (100 * votesAgainst) / voteSum
|
||||
export function VoteGraphBar({ graphWidth, balanceWidth, isAnimation }: VoteGraphBarProps) {
|
||||
const markerWidth: number = balanceWidth ? balanceWidth : 3
|
||||
const votesWidth: number = graphWidth ? graphWidth : 3
|
||||
const [keyFrames, setKeyFrames] = useState('')
|
||||
const [style, setStyle] = useState<any>({ width: `${votesWidth}%` })
|
||||
|
||||
let balanceWidth = graphWidth
|
||||
|
||||
if (proposingAmount && selectedVote) {
|
||||
balanceWidth =
|
||||
selectedVote.type === 0
|
||||
? (100 * (votesAgainst + proposingAmount)) / (voteSum + proposingAmount)
|
||||
: (100 * votesAgainst) / (voteSum + proposingAmount)
|
||||
}
|
||||
useEffect(() => {
|
||||
if (isAnimation) {
|
||||
setStyle({ width: `${markerWidth}%`, animation: 'fade-in 2s ease' })
|
||||
setKeyFrames(createKeyFrames(votesWidth, markerWidth))
|
||||
} else {
|
||||
setStyle({ width: `${votesWidth}%` })
|
||||
}
|
||||
}, [isAnimation, votesWidth])
|
||||
|
||||
return (
|
||||
<VoteGraph
|
||||
style={{
|
||||
backgroundColor: voteWinner && voteWinner === 1 ? `${Colors.GrayDisabledLight}` : `${Colors.BlueBar}`,
|
||||
}}
|
||||
>
|
||||
<VoteGraphAgainst
|
||||
style={{
|
||||
width: graphWidth + '%',
|
||||
backgroundColor: voteWinner && voteWinner === 2 ? `${Colors.GrayDisabledLight}` : `${Colors.Orange}`,
|
||||
}}
|
||||
/>
|
||||
<VoteBalance
|
||||
style={{
|
||||
width: balanceWidth + '%',
|
||||
}}
|
||||
></VoteBalance>
|
||||
<VoteGraph>
|
||||
<style children={keyFrames} />
|
||||
<VoteGraphAgainst style={style} />
|
||||
<VoteBalance style={{ width: `${markerWidth}%` }} />
|
||||
</VoteGraph>
|
||||
)
|
||||
}
|
||||
|
||||
const VoteGraph = styled.div`
|
||||
const VoteGraph = styled.div<VoteGraphBarProps>`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 16px;
|
||||
background-color: ${Colors.BlueBar};
|
||||
background-color: ${({ voteWinner }) => (voteWinner && voteWinner === 1 ? Colors.GrayDisabledLight : Colors.BlueBar)};
|
||||
border-radius: 10px;
|
||||
padding-top: 5px;
|
||||
|
||||
|
@ -67,14 +67,15 @@ const VoteGraph = styled.div`
|
|||
}
|
||||
`
|
||||
|
||||
const VoteGraphAgainst = styled.div`
|
||||
const VoteGraphAgainst = styled.div<VoteGraphBarProps>`
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 13px;
|
||||
width: 3%;
|
||||
height: 16px;
|
||||
background-color: ${Colors.Orange};
|
||||
background-color: ${({ voteWinner }) => (voteWinner && voteWinner === 2 ? Colors.GrayDisabledLight : Colors.Orange)};
|
||||
border-radius: 10px 0 0 10px;
|
||||
transition: width 2s;
|
||||
z-index: 2;
|
||||
`
|
||||
|
||||
|
@ -82,7 +83,7 @@ const VoteBalance = styled.div`
|
|||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 13px;
|
||||
width: 3%;
|
||||
height: 16px;
|
||||
background-color: transparent;
|
||||
border-right: 2px solid ${Colors.VioletLight};
|
||||
|
|
|
@ -14,7 +14,7 @@ export function useSendWakuVote() {
|
|||
const msg = await createWakuMessage(account, library?.getSigner(), room, voteAmount, type, config.wakuTopic)
|
||||
if (msg) {
|
||||
if (waku) {
|
||||
waku.relay.send(msg)
|
||||
await waku.relay.send(msg)
|
||||
} else {
|
||||
alert('error sending vote please try again')
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue