Add vote modals (#56)
This commit is contained in:
parent
b937d77d26
commit
024c9ac1f5
|
@ -5,17 +5,19 @@ import React, { useEffect, useState } from 'react'
|
||||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { RadioGroup, SmallButton } from '@status-waku-voting/react-components'
|
import { RadioGroup, SmallButton, Theme } from '@status-waku-voting/react-components'
|
||||||
import { PollResults } from './PollResults'
|
import { PollResults } from './PollResults'
|
||||||
import { useEthers } from '@usedapp/core'
|
import { useEthers } from '@usedapp/core'
|
||||||
import { Modal } from '@status-waku-voting/react-components'
|
import { Modal } from '@status-waku-voting/react-components'
|
||||||
|
|
||||||
type PollProps = {
|
type PollProps = {
|
||||||
|
theme: Theme
|
||||||
poll: DetailedTimedPoll
|
poll: DetailedTimedPoll
|
||||||
wakuPolling: WakuPolling | undefined
|
wakuPolling: WakuPolling | undefined
|
||||||
signer: Wallet | JsonRpcSigner | undefined
|
signer: Wallet | JsonRpcSigner | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Poll({ poll, wakuPolling, signer }: PollProps) {
|
export function Poll({ poll, wakuPolling, theme, signer }: PollProps) {
|
||||||
const { account } = useEthers()
|
const { account } = useEthers()
|
||||||
const [selectedAnswer, setSelectedAnswer] = useState<number | undefined>(undefined)
|
const [selectedAnswer, setSelectedAnswer] = useState<number | undefined>(undefined)
|
||||||
const [tokenAmount, setTokenAmount] = useState(0)
|
const [tokenAmount, setTokenAmount] = useState(0)
|
||||||
|
@ -83,7 +85,7 @@ export function Poll({ poll, wakuPolling, signer }: PollProps) {
|
||||||
</SmallButton>
|
</SmallButton>
|
||||||
)}
|
)}
|
||||||
{showNotEnoughTokens && (
|
{showNotEnoughTokens && (
|
||||||
<Modal heading={''} setShowModal={setShowNotEnoughTokens}>
|
<Modal heading={''} setShowModal={setShowNotEnoughTokens} theme={theme}>
|
||||||
<ModalTextWrapper>You don't have enough tokens to vote</ModalTextWrapper>
|
<ModalTextWrapper>You don't have enough tokens to vote</ModalTextWrapper>
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||||
import { WakuPolling } from '@status-waku-voting/core'
|
import { WakuPolling } from '@status-waku-voting/core'
|
||||||
import { Input, addIcon, SmallButton, Modal } from '@status-waku-voting/react-components'
|
import { Input, addIcon, SmallButton, Modal, Theme } from '@status-waku-voting/react-components'
|
||||||
|
|
||||||
function getLocaleIsoTime(dateTime: Date) {
|
function getLocaleIsoTime(dateTime: Date) {
|
||||||
const MS_PER_MINUTE = 60000
|
const MS_PER_MINUTE = 60000
|
||||||
|
@ -35,12 +35,13 @@ function ConfirmScreen({ children, setShowModal }: ConfirmScreenProps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PollCreationProps = {
|
type PollCreationProps = {
|
||||||
|
theme: Theme
|
||||||
signer: JsonRpcSigner | Wallet
|
signer: JsonRpcSigner | Wallet
|
||||||
wakuPolling: WakuPolling | undefined
|
wakuPolling: WakuPolling | undefined
|
||||||
setShowPollCreation: (val: boolean) => void
|
setShowPollCreation: (val: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollCreationProps) {
|
export function PollCreation({ signer, wakuPolling, theme, setShowPollCreation }: PollCreationProps) {
|
||||||
const [answers, setAnswers] = useState<string[]>(['', ''])
|
const [answers, setAnswers] = useState<string[]>(['', ''])
|
||||||
const [question, setQuestion] = useState('')
|
const [question, setQuestion] = useState('')
|
||||||
const [showCreateConfirmation, setShowCreateConfirmation] = useState(false)
|
const [showCreateConfirmation, setShowCreateConfirmation] = useState(false)
|
||||||
|
@ -49,7 +50,7 @@ export function PollCreation({ signer, wakuPolling, setShowPollCreation }: PollC
|
||||||
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
|
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal heading="Create a poll" setShowModal={setShowPollCreation}>
|
<Modal heading="Create a poll" setShowModal={setShowPollCreation} theme={theme}>
|
||||||
<NewPollBox>
|
<NewPollBox>
|
||||||
{!showCreateConfirmation && !showNotEnoughTokens && (
|
{!showCreateConfirmation && !showNotEnoughTokens && (
|
||||||
<PollForm>
|
<PollForm>
|
||||||
|
|
|
@ -5,13 +5,15 @@ import React, { useEffect, useState } from 'react'
|
||||||
import { Poll } from './Poll'
|
import { Poll } from './Poll'
|
||||||
import { JsonRpcSigner } from '@ethersproject/providers'
|
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { Theme } from '@status-waku-voting/react-components'
|
||||||
|
|
||||||
type PollListProps = {
|
type PollListProps = {
|
||||||
|
theme: Theme
|
||||||
wakuPolling: WakuPolling | undefined
|
wakuPolling: WakuPolling | undefined
|
||||||
signer: Wallet | JsonRpcSigner | undefined
|
signer: Wallet | JsonRpcSigner | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PollList({ wakuPolling, signer }: PollListProps) {
|
export function PollList({ wakuPolling, signer, theme }: PollListProps) {
|
||||||
const [polls, setPolls] = useState<DetailedTimedPoll[]>([])
|
const [polls, setPolls] = useState<DetailedTimedPoll[]>([])
|
||||||
const [dividedPolls, setDividedPolls] = useState<DetailedTimedPoll[][]>([[], [], []])
|
const [dividedPolls, setDividedPolls] = useState<DetailedTimedPoll[][]>([[], [], []])
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -43,7 +45,7 @@ export function PollList({ wakuPolling, signer }: PollListProps) {
|
||||||
return (
|
return (
|
||||||
<ColumnWrapper key={idx}>
|
<ColumnWrapper key={idx}>
|
||||||
{pollArray.map((poll) => {
|
{pollArray.map((poll) => {
|
||||||
return <Poll key={poll.poll.id} poll={poll} wakuPolling={wakuPolling} signer={signer} />
|
return <Poll key={poll.poll.id} poll={poll} wakuPolling={wakuPolling} signer={signer} theme={theme} />
|
||||||
})}
|
})}
|
||||||
</ColumnWrapper>
|
</ColumnWrapper>
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,7 +22,12 @@ export function WakuPolling({ appName, signer, theme }: WakuPollingProps) {
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
{showPollCreation && signer && (
|
{showPollCreation && signer && (
|
||||||
<PollCreation signer={signer} wakuPolling={wakuPolling} setShowPollCreation={setShowPollCreation} />
|
<PollCreation
|
||||||
|
signer={signer}
|
||||||
|
wakuPolling={wakuPolling}
|
||||||
|
setShowPollCreation={setShowPollCreation}
|
||||||
|
theme={theme}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
{account ? (
|
{account ? (
|
||||||
<CreateButton theme={theme} disabled={!signer} onClick={() => setShowPollCreation(true)}>
|
<CreateButton theme={theme} disabled={!signer} onClick={() => setShowPollCreation(true)}>
|
||||||
|
@ -41,12 +46,12 @@ export function WakuPolling({ appName, signer, theme }: WakuPollingProps) {
|
||||||
</CreateButton>
|
</CreateButton>
|
||||||
)}
|
)}
|
||||||
{selectConnect && (
|
{selectConnect && (
|
||||||
<Modal heading="Connect" setShowModal={setSelectConnect}>
|
<Modal heading="Connect" theme={theme} setShowModal={setSelectConnect}>
|
||||||
<Networks />
|
<Networks />
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<PollList wakuPolling={wakuPolling} signer={signer} />
|
<PollList wakuPolling={wakuPolling} signer={signer} theme={theme} />
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import styled from 'styled-components'
|
||||||
|
|
||||||
|
export const Input = styled.input`
|
||||||
|
max-width: 420px;
|
||||||
|
padding: 11px 20px;
|
||||||
|
background: #f0f1f3;
|
||||||
|
color: #00000;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #eef2f5;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:active,
|
||||||
|
&:focus {
|
||||||
|
border: 1px solid #5d7be2;
|
||||||
|
caret-color: #5d7be2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
`
|
|
@ -8,7 +8,7 @@ export function Proposal() {
|
||||||
return (
|
return (
|
||||||
<ProposalWrapper>
|
<ProposalWrapper>
|
||||||
<ProposalHeader theme={blueTheme} />
|
<ProposalHeader theme={blueTheme} />
|
||||||
<ProposalList />
|
<ProposalList theme={blueTheme} />
|
||||||
</ProposalWrapper>
|
</ProposalWrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { Theme } from '@status-waku-voting/react-components'
|
||||||
import { ProposalInfo } from './ProposalInfo'
|
import { ProposalInfo } from './ProposalInfo'
|
||||||
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
|
import { ProposalVote } from './ProposalVoteCard/ProposalVote'
|
||||||
|
|
||||||
interface ProposalCardProps {
|
interface ProposalCardProps {
|
||||||
|
theme: Theme
|
||||||
heading: string
|
heading: string
|
||||||
text: string
|
text: string
|
||||||
address: string
|
address: string
|
||||||
|
@ -12,11 +14,11 @@ interface ProposalCardProps {
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalCard({ heading, text, address, vote, voteWinner }: ProposalCardProps) {
|
export function ProposalCard({ heading, text, address, vote, voteWinner, theme }: ProposalCardProps) {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<ProposalInfo heading={heading} text={text} address={address} />
|
<ProposalInfo heading={heading} text={text} address={address} />
|
||||||
<ProposalVote vote={vote} voteWinner={voteWinner} address={address} />
|
<ProposalVote vote={vote} voteWinner={voteWinner} address={address} heading={heading} theme={theme} />
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ export function ProposalHeader({ theme }: ProposalHeaderProps) {
|
||||||
</CreateButton>
|
</CreateButton>
|
||||||
)}
|
)}
|
||||||
{selectConnect && (
|
{selectConnect && (
|
||||||
<Modal heading="Connect" setShowModal={setSelectConnect}>
|
<Modal heading="Connect" setShowModal={setSelectConnect} theme={theme}>
|
||||||
<Networks />
|
<Networks />
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { Theme } from '@status-waku-voting/react-components'
|
||||||
import { ProposalCard } from './ProposalCard'
|
import { ProposalCard } from './ProposalCard'
|
||||||
|
|
||||||
export function ProposalList() {
|
type ProposalListProps = {
|
||||||
|
theme: Theme
|
||||||
|
}
|
||||||
|
export function ProposalList({ theme }: ProposalListProps) {
|
||||||
return (
|
return (
|
||||||
<List>
|
<List>
|
||||||
<ProposalCard
|
<ProposalCard
|
||||||
|
@ -13,6 +17,7 @@ export function ProposalList() {
|
||||||
address={'#'}
|
address={'#'}
|
||||||
vote={2345678}
|
vote={2345678}
|
||||||
voteWinner={2}
|
voteWinner={2}
|
||||||
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
<ProposalCard
|
<ProposalCard
|
||||||
heading={'Short proposal title'}
|
heading={'Short proposal title'}
|
||||||
|
@ -20,6 +25,7 @@ export function ProposalList() {
|
||||||
'This is a shorter description of the proposal. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales.'
|
'This is a shorter description of the proposal. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque interdum rutrum sodales.'
|
||||||
}
|
}
|
||||||
address={'#'}
|
address={'#'}
|
||||||
|
theme={theme}
|
||||||
/>
|
/>
|
||||||
</List>
|
</List>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,31 +5,99 @@ import { FinalBtn, VoteBtnAgainst, VoteBtnFor } from '../Buttons'
|
||||||
import { VoteSubmitButton } from './VoteSubmitButton'
|
import { VoteSubmitButton } from './VoteSubmitButton'
|
||||||
import { VoteChart } from './VoteChart'
|
import { VoteChart } from './VoteChart'
|
||||||
import { ViewLink } from '../ViewLink'
|
import { ViewLink } from '../ViewLink'
|
||||||
|
import { Modal, Theme } from '@status-waku-voting/react-components'
|
||||||
|
import { VoteModal } from '../VoteModal'
|
||||||
|
import { VoteAnimatedModal } from '../VoteAnimatedModal'
|
||||||
|
|
||||||
interface ProposalVoteProps {
|
interface ProposalVoteProps {
|
||||||
|
theme: Theme
|
||||||
vote?: number
|
vote?: number
|
||||||
voteWinner?: number
|
voteWinner?: number
|
||||||
|
heading: string
|
||||||
address: string
|
address: string
|
||||||
hideModalFunction?: (val: boolean) => void
|
hideModalFunction?: (val: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ProposalVote({ vote, voteWinner, address, hideModalFunction }: ProposalVoteProps) {
|
export function ProposalVote({ vote, voteWinner, address, heading, theme, hideModalFunction }: ProposalVoteProps) {
|
||||||
const { account } = useEthers()
|
const { account } = useEthers()
|
||||||
const [showVoteModal, setShowVoteModal] = useState(false)
|
const [showVoteModal, setShowVoteModal] = useState(false)
|
||||||
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||||
|
const [proposingAmount, setProposingAmount] = useState(0)
|
||||||
|
const [selectedVoted, setSelectedVoted] = useState(0)
|
||||||
|
|
||||||
|
const setNext = (val: boolean) => {
|
||||||
|
setShowConfirmModal(val)
|
||||||
|
setShowVoteModal(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const hideConfirm = (val: boolean) => {
|
||||||
|
if (hideModalFunction) {
|
||||||
|
hideModalFunction(false)
|
||||||
|
}
|
||||||
|
setShowConfirmModal(val)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
|
{showVoteModal && (
|
||||||
|
<Modal heading={heading} setShowModal={setShowVoteModal} theme={theme}>
|
||||||
|
<VoteModal
|
||||||
|
votesFor={1865567}
|
||||||
|
votesAgainst={1740235}
|
||||||
|
timeLeft={4855555577}
|
||||||
|
availableAmount={65245346}
|
||||||
|
selectedVote={selectedVoted}
|
||||||
|
proposingAmount={proposingAmount}
|
||||||
|
setShowConfirmModal={setNext}
|
||||||
|
setProposingAmount={setProposingAmount}
|
||||||
|
/>{' '}
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
{showConfirmModal && (
|
||||||
|
<Modal heading={heading} setShowModal={hideConfirm} theme={theme}>
|
||||||
|
<VoteAnimatedModal
|
||||||
|
votesFor={1865567}
|
||||||
|
votesAgainst={1740235}
|
||||||
|
timeLeft={4855555577}
|
||||||
|
selectedVote={selectedVoted}
|
||||||
|
setShowModal={hideConfirm}
|
||||||
|
proposingAmount={proposingAmount}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
{voteWinner ? <CardHeading>Proposal {voteWinner == 1 ? 'rejected' : 'passed'}</CardHeading> : <CardHeading />}
|
{voteWinner ? <CardHeading>Proposal {voteWinner == 1 ? 'rejected' : 'passed'}</CardHeading> : <CardHeading />}
|
||||||
|
|
||||||
<VoteChart votesFor={1865567} votesAgainst={1740235} timeLeft={4855555577} voteWinner={voteWinner} />
|
<VoteChart
|
||||||
|
votesFor={1865567}
|
||||||
|
votesAgainst={1740235}
|
||||||
|
timeLeft={4855555577}
|
||||||
|
voteWinner={voteWinner}
|
||||||
|
selectedVote={selectedVoted}
|
||||||
|
/>
|
||||||
|
|
||||||
<CardButtons>
|
<CardButtons>
|
||||||
{voteWinner ? (
|
{voteWinner ? (
|
||||||
<FinalBtn disabled={!account}>Finalize the vote</FinalBtn>
|
<FinalBtn disabled={!account}>Finalize the vote</FinalBtn>
|
||||||
) : (
|
) : (
|
||||||
<VotesBtns>
|
<VotesBtns>
|
||||||
<VoteBtnAgainst disabled={!account}>Vote Against</VoteBtnAgainst>
|
<VoteBtnAgainst
|
||||||
<VoteBtnFor disabled={!account}>Vote For</VoteBtnFor>
|
disabled={!account}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedVoted(0)
|
||||||
|
setShowVoteModal(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Vote Against
|
||||||
|
</VoteBtnAgainst>
|
||||||
|
<VoteBtnFor
|
||||||
|
disabled={!account}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedVoted(1)
|
||||||
|
setShowVoteModal(true)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Vote For
|
||||||
|
</VoteBtnFor>
|
||||||
</VotesBtns>
|
</VotesBtns>
|
||||||
)}
|
)}
|
||||||
</CardButtons>
|
</CardButtons>
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
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
|
||||||
|
proposingAmount: number
|
||||||
|
selectedVote: number
|
||||||
|
setShowModal: (val: boolean) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VoteAnimatedModal({
|
||||||
|
votesFor,
|
||||||
|
votesAgainst,
|
||||||
|
timeLeft,
|
||||||
|
selectedVote,
|
||||||
|
proposingAmount,
|
||||||
|
setShowModal,
|
||||||
|
}: VoteAnimatedModalProps) {
|
||||||
|
return (
|
||||||
|
<VoteConfirm>
|
||||||
|
<ConfirmText>Your vote for this proposal has been cast!</ConfirmText>
|
||||||
|
<VoteChart
|
||||||
|
votesFor={votesFor}
|
||||||
|
votesAgainst={votesAgainst}
|
||||||
|
timeLeft={timeLeft}
|
||||||
|
proposingAmount={proposingAmount}
|
||||||
|
selectedVote={selectedVote}
|
||||||
|
isAnimation={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FinalBtn onClick={() => setShowModal(false)}>Close</FinalBtn>
|
||||||
|
</VoteConfirm>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const VoteConfirm = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 32px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ConfirmText = styled.div`
|
||||||
|
margin-bottom: 32px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,76 @@
|
||||||
|
import React from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
import { VoteChart } from './ProposalVoteCard/VoteChart'
|
||||||
|
import { VoteBtnAgainst, VoteBtnFor } from './Buttons'
|
||||||
|
import { VotePropose } from './VotePropose'
|
||||||
|
|
||||||
|
export interface VoteModalProps {
|
||||||
|
votesFor: number
|
||||||
|
votesAgainst: number
|
||||||
|
timeLeft: number
|
||||||
|
voteWinner?: number
|
||||||
|
selectedVote: number
|
||||||
|
availableAmount: number
|
||||||
|
proposingAmount: number
|
||||||
|
setShowConfirmModal: (show: boolean) => void
|
||||||
|
setProposingAmount: (val: number) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VoteModal({
|
||||||
|
votesFor,
|
||||||
|
votesAgainst,
|
||||||
|
timeLeft,
|
||||||
|
voteWinner,
|
||||||
|
selectedVote,
|
||||||
|
availableAmount,
|
||||||
|
proposingAmount,
|
||||||
|
setShowConfirmModal,
|
||||||
|
setProposingAmount,
|
||||||
|
}: VoteModalProps) {
|
||||||
|
const disabled = proposingAmount === 0
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Column>
|
||||||
|
<VoteChart
|
||||||
|
votesFor={votesFor}
|
||||||
|
votesAgainst={votesAgainst}
|
||||||
|
timeLeft={timeLeft}
|
||||||
|
voteWinner={voteWinner}
|
||||||
|
proposingAmount={proposingAmount}
|
||||||
|
selectedVote={selectedVote}
|
||||||
|
/>
|
||||||
|
<VotePropose
|
||||||
|
availableAmount={availableAmount}
|
||||||
|
setProposingAmount={setProposingAmount}
|
||||||
|
proposingAmount={proposingAmount}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{selectedVote === 0 ? (
|
||||||
|
<ModalVoteBtnAgainst disabled={disabled} onClick={() => setShowConfirmModal(true)}>
|
||||||
|
Vote Against
|
||||||
|
</ModalVoteBtnAgainst>
|
||||||
|
) : (
|
||||||
|
<ModalVoteBtnFor disabled={disabled} onClick={() => setShowConfirmModal(true)}>
|
||||||
|
Vote For
|
||||||
|
</ModalVoteBtnFor>
|
||||||
|
)}
|
||||||
|
</Column>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Column = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 32px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ModalVoteBtnAgainst = styled(VoteBtnAgainst)`
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 32px;
|
||||||
|
`
|
||||||
|
const ModalVoteBtnFor = styled(VoteBtnFor)`
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 32px;
|
||||||
|
`
|
|
@ -0,0 +1,136 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { useState } from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
import { addCommas } from '../helpers/addCommas'
|
||||||
|
import { Input } from './Input'
|
||||||
|
|
||||||
|
export interface VoteProposingProps {
|
||||||
|
availableAmount: number
|
||||||
|
setProposingAmount: (show: number) => void
|
||||||
|
proposingAmount: number
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VotePropose({ availableAmount, proposingAmount, setProposingAmount }: VoteProposingProps) {
|
||||||
|
const [displayAmount, setDisplayAmount] = useState(addCommas(proposingAmount) + ' SNT')
|
||||||
|
|
||||||
|
let step = 10 ** (Math.floor(Math.log10(availableAmount)) - 2)
|
||||||
|
if (availableAmount < 100) {
|
||||||
|
step = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const setAvailableAmount = () => {
|
||||||
|
setProposingAmount(availableAmount)
|
||||||
|
setDisplayAmount(addCommas(availableAmount) + ' SNT')
|
||||||
|
}
|
||||||
|
|
||||||
|
const sliderChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (Number(e.target.value) == step * Math.floor(availableAmount / step)) {
|
||||||
|
setAvailableAmount()
|
||||||
|
} else {
|
||||||
|
setProposingAmount(Number(e.target.value))
|
||||||
|
setDisplayAmount(addCommas(Number(e.target.value)) + ' SNT')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const progress = (proposingAmount / availableAmount) * 100 + '%'
|
||||||
|
|
||||||
|
const onInputAmountBlur = () => {
|
||||||
|
if (proposingAmount > availableAmount) {
|
||||||
|
setAvailableAmount()
|
||||||
|
} else {
|
||||||
|
setDisplayAmount(addCommas(proposingAmount) + ' SNT')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<VoteProposing>
|
||||||
|
<VoteProposingInfo>
|
||||||
|
<p>My vote</p>
|
||||||
|
<span>Available {addCommas(availableAmount)} ABC</span>
|
||||||
|
</VoteProposingInfo>
|
||||||
|
<VoteProposingAmount
|
||||||
|
value={displayAmount}
|
||||||
|
onInput={(e) => {
|
||||||
|
setProposingAmount(Number(e.currentTarget.value))
|
||||||
|
setDisplayAmount(e.currentTarget.value)
|
||||||
|
}}
|
||||||
|
onBlur={onInputAmountBlur}
|
||||||
|
onFocus={() => setDisplayAmount(proposingAmount.toString())}
|
||||||
|
/>
|
||||||
|
<VoteProposingRangeWrap>
|
||||||
|
<VoteProposingRange
|
||||||
|
type="range"
|
||||||
|
min={0}
|
||||||
|
max={availableAmount}
|
||||||
|
step={step}
|
||||||
|
value={proposingAmount}
|
||||||
|
onChange={sliderChange}
|
||||||
|
style={{
|
||||||
|
background: `linear-gradient(90deg, #0F3595 0% ${progress}, #EDF1FF ${progress} 100%)`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</VoteProposingRangeWrap>
|
||||||
|
</VoteProposing>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const VoteProposing = styled.div`
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
`
|
||||||
|
const VoteProposingInfo = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
& > span {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
color: #939ba1;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteProposingAmount = styled(Input)`
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteProposingRangeWrap = styled.div`
|
||||||
|
width: 294px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteProposingRange = styled.input`
|
||||||
|
appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 4px;
|
||||||
|
padding: 0;
|
||||||
|
margin: 10px 0;
|
||||||
|
border-radius: 2px;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #5d7be2;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background: #5d7be2;
|
||||||
|
border: 0.5px solid rgba(0, 0, 0, 0);
|
||||||
|
border-radius: 50px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
`
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M16.4697 17.5303C16.7626 17.8232 17.2374 17.8232 17.5303 17.5303C17.8232 17.2374 17.8232 16.7626 17.5303 16.4697L13.4142 12.3536C13.219 12.1583 13.219 11.8417 13.4142 11.6464L17.5303 7.53033C17.8232 7.23744 17.8232 6.76256 17.5303 6.46967C17.2374 6.17678 16.7626 6.17678 16.4697 6.46967L12.3536 10.5858C12.1583 10.781 11.8417 10.781 11.6464 10.5858L7.53033 6.46967C7.23744 6.17678 6.76256 6.17678 6.46967 6.46967C6.17678 6.76256 6.17678 7.23744 6.46967 7.53033L10.5858 11.6464C10.781 11.8417 10.781 12.1583 10.5858 12.3536L6.46967 16.4697C6.17678 16.7626 6.17678 17.2374 6.46967 17.5303C6.76256 17.8232 7.23744 17.8232 7.53033 17.5303L11.6464 13.4142C11.8417 13.219 12.1583 13.219 12.3536 13.4142L16.4697 17.5303Z" fill="#0F3595"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 844 B |
|
@ -1,14 +1,16 @@
|
||||||
import React, { ReactNode, useEffect } from 'react'
|
import React, { ReactNode, useEffect } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import closeButton from '../assets/svg/close.svg'
|
import { Theme } from '../style/themes'
|
||||||
|
import { CloseButton } from './misc/Buttons'
|
||||||
|
|
||||||
type ModalProps = {
|
type ModalProps = {
|
||||||
heading: string
|
heading: string
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
|
theme: Theme
|
||||||
setShowModal: (val: boolean) => void
|
setShowModal: (val: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Modal({ heading, children, setShowModal }: ModalProps) {
|
export function Modal({ heading, children, theme, setShowModal }: ModalProps) {
|
||||||
const body = document.getElementById('root')
|
const body = document.getElementById('root')
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -25,7 +27,7 @@ export function Modal({ heading, children, setShowModal }: ModalProps) {
|
||||||
<PopUpWindow onClick={(e) => e.stopPropagation()}>
|
<PopUpWindow onClick={(e) => e.stopPropagation()}>
|
||||||
<PopUpHeader>
|
<PopUpHeader>
|
||||||
<PopUpHeading>{heading}</PopUpHeading>
|
<PopUpHeading>{heading}</PopUpHeading>
|
||||||
<CloseButton onClick={() => setShowModal(false)} />
|
<CloseButton theme={theme} onClick={() => setShowModal(false)} />
|
||||||
</PopUpHeader>
|
</PopUpHeader>
|
||||||
<PopUpContetnt>{children}</PopUpContetnt>
|
<PopUpContetnt>{children}</PopUpContetnt>
|
||||||
</PopUpWindow>
|
</PopUpWindow>
|
||||||
|
@ -85,10 +87,3 @@ const PopUpHeading = styled.p`
|
||||||
const PopUpContetnt = styled.div`
|
const PopUpContetnt = styled.div`
|
||||||
width: 100%;
|
width: 100%;
|
||||||
`
|
`
|
||||||
const CloseButton = styled.button`
|
|
||||||
width: 24px;
|
|
||||||
height: 24px;
|
|
||||||
background-image: url(${closeButton});
|
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
|
||||||
`
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ export function TopBar({ logo, title, theme, activate, deactivate, account }: To
|
||||||
</ContentWrapper>
|
</ContentWrapper>
|
||||||
|
|
||||||
{selectConnect && (
|
{selectConnect && (
|
||||||
<Modal heading="Connect" setShowModal={setSelectConnect}>
|
<Modal heading="Connect" theme={theme} setShowModal={setSelectConnect}>
|
||||||
<Networks />
|
<Networks />
|
||||||
</Modal>
|
</Modal>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import styled, { css } from 'styled-components'
|
import styled, { css } from 'styled-components'
|
||||||
import { Theme } from '../../style/themes'
|
import { orangeTheme, Theme } from '../../style/themes'
|
||||||
|
import closeButton from '../../assets/svg/close.svg'
|
||||||
|
import blueCloseButton from '../../assets/svg/blueClose.svg'
|
||||||
|
|
||||||
export const Button = styled.button`
|
export const Button = styled.button`
|
||||||
height: 44px;
|
height: 44px;
|
||||||
|
@ -154,3 +156,14 @@ export const ButtonDisconnect = styled.button<DisconnectProps>`
|
||||||
color: ${({ theme }) => theme.activeTextColor};
|
color: ${({ theme }) => theme.activeTextColor};
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
interface CloseProps {
|
||||||
|
theme: Theme
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CloseButton = styled.button<CloseProps>`
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background-image: url(${({ theme }) => (theme === orangeTheme ? closeButton : blueCloseButton)});
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
`
|
||||||
|
|
Loading…
Reference in New Issue