Add confirm animation (#76)

This commit is contained in:
Maria Rushkova 2021-07-01 15:25:09 +02:00 committed by GitHub
parent e7c749f658
commit ca92e2e71b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 166 additions and 54 deletions

View File

@ -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 ? (

View File

@ -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, lets 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;
}
`

View File

@ -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}

View File

@ -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>
)

View File

@ -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};

View File

@ -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')
}