Add mobile voting (#142)

This commit is contained in:
Maria Rushkova 2021-07-22 12:18:53 +02:00 committed by GitHub
parent 158bb211ca
commit dc12c4e27b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 273 additions and 30 deletions

View File

@ -73,6 +73,10 @@ export const VotesBtns = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
@media (max-width: 600px) {
margin-top: 24px;
}
`
export const VoteBtn = styled(ButtonSecondary)`
width: 44%;

View File

@ -52,14 +52,14 @@ export const CardVoteWrap = styled.div`
@media (max-width: 768px) {
width: 100%;
padding-top: 56px;
box-shadow: none;
border-radius: unset;
border-bottom: 1px solid #e0e0e0;
background-color: unset;
}
@media (max-width: 768px) {
@media (max-width: 600px) {
flex-direction: column;
padding: 16px 0 0;
border-bottom: none;
}
@ -82,4 +82,8 @@ export const CardHeading = styled.h2`
font-size: 17px;
line-height: 24px;
text-align: center;
@media (max-width: 600px) {
text-align: start;
}
`

View File

@ -45,7 +45,7 @@ export const CardCommunity = ({
<VoteHistoryTable>
<tbody>
<tr>
<VoteHistoryTableColumnCell>Date</VoteHistoryTableColumnCell>
<VoteHistoryTableColumnCellDate>Date</VoteHistoryTableColumnCellDate>
<VoteHistoryTableColumnCell>Type</VoteHistoryTableColumnCell>
<VoteHistoryTableColumnCell>Result</VoteHistoryTableColumnCell>
</tr>
@ -106,9 +106,9 @@ export const CardCommunity = ({
<CardLinks className={customStyle ? 'notModal' : ''}>
<LinkExternal>Visit community</LinkExternal>
<LinkExternal>Etherscan</LinkExternal>
<LinkInternal onClick={() => setShowHistoryModal(true)} disabled={isDisabled}>
<HistoryLink onClick={() => setShowHistoryModal(true)} disabled={isDisabled}>
Voting history
</LinkInternal>
</HistoryLink>
</CardLinks>
</CardCommunityBlock>
)
@ -231,29 +231,39 @@ export const CardLinks = styled.div`
}
@media (max-width: 600px) {
display: none;
padding: 12px 20px 0;
}
&.notModal {
@media (max-width: 768px) {
max-width: calc(100% - 60px);
}
@media (max-width: 600px) {
display: none;
}
}
`
const VoteHistoryTable = styled.table`
const HistoryLink = styled(LinkInternal)`
@media (max-width: 600px) {
display: none;
}
`
export const VoteHistoryTable = styled.table`
width: 100%;
`
const VoteHistoryTableColumnCell = styled.td`
export const VoteHistoryTableColumnCell = styled.td`
width: 33.3%;
font-weight: bold;
padding-bottom: 24px;
padding-right: 112px;
width: 65px;
`
const VoteHistoryTableCell = styled.td`
width: 65px;
export const VoteHistoryTableColumnCellDate = styled(VoteHistoryTableColumnCell)`
width: 40%;
`
export const VoteHistoryTableCell = styled.td`
width: 33.3%;
padding-bottom: 18px;
padding-right: 112px;
`

View File

@ -131,7 +131,7 @@ export const CardVote = ({ room, hideModalFunction }: CardVoteProps) => {
)
}
const CardHeadingEndedVote = styled.p`
export const CardHeadingEndedVote = styled.p`
max-width: 290px;
align-self: center;
font-weight: normal;
@ -142,12 +142,16 @@ const CardHeadingEndedVote = styled.p`
@media (max-width: 768px) {
max-width: 100%;
margin-bottom: 26px;
margin-bottom: 24px;
}
`
const VoteBtnFinal = styled(VoteBtn)`
width: 100%;
@media (max-width: 600px) {
margin-top: 24px;
}
`
const CardVoteBottom = styled.div`

View File

@ -0,0 +1,185 @@
import { useContractFunction, useEthers } from '@usedapp/core'
import React, { useState } from 'react'
import styled from 'styled-components'
import { VotesBtns, VoteBtn } from '../components/Button'
import { CardVoteBlock, CardHeading } from '../components/Card'
import {
VoteHistoryTableCell,
VoteHistoryTableColumnCell,
VoteHistoryTableColumnCellDate,
} from '../components/card/CardCommunity'
import { VoteHistoryTable } from '../components/card/CardCommunity'
import { CardHeadingEndedVote } from '../components/card/CardVote/CardVote'
import { VoteSubmitButton } from '../components/card/VoteSubmitButton'
import { LinkInternal } from '../components/Link'
import { VoteChart } from '../components/votes/VoteChart'
import { VotePropose } from '../components/votes/VotePropose'
import { voteTypes } from '../constants/voteTypes'
import voting, { getVotingWinner } from '../helpers/voting'
import { useContracts } from '../hooks/useContracts'
import { DetailedVotingRoom } from '../models/smartContract'
import arrowDown from '../assets/images/arrowDown.svg'
interface CardVoteMobileProps {
room: DetailedVotingRoom
}
export const CardVoteMobile = ({ room }: CardVoteMobileProps) => {
const { account } = useEthers()
const selectedVoted = voteTypes['Add'].for
const { votingContract } = useContracts()
const finalizeVoting = useContractFunction(votingContract, 'finalizeVotingRoom')
const vote = voting.fromRoom(room)
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)
const [showHistoryModal, setShowHistoryModal] = useState(false)
const isDisabled = room.details.votingHistory.length === 0
if (!vote) {
return <CardVoteBlock />
}
return (
<CardVoteBlock>
{winner ? (
<CardHeadingEndedVote>
SNT holders have decided <b>{winner == 1 ? voteConstants.against.verb : voteConstants.for.verb}</b> this
community to the directory!
</CardHeadingEndedVote>
) : (
<CardHeadingMobile>{voteConstants.question}</CardHeadingMobile>
)}
<div>
<Wrapper>
<VoteChart vote={vote} voteWinner={winner} isAnimation={true} />
</Wrapper>
{!winner && (
<WrapperTop>
<VotePropose
vote={vote}
selectedVote={selectedVoted}
availableAmount={availableAmount}
proposingAmount={proposingAmount}
setProposingAmount={setProposingAmount}
/>
</WrapperTop>
)}
{winner ? (
<VoteBtnFinal onClick={() => finalizeVoting.send(room.roomNumber)} disabled={!account}>
Finalize the vote <span></span>
</VoteBtnFinal>
) : (
<VotesBtns>
<VoteBtn disabled={!account}>
{voteConstants.against.text} <span>{voteConstants.against.icon}</span>
</VoteBtn>
<VoteBtn disabled={!account}>
{voteConstants.for.text} <span>{voteConstants.for.icon}</span>
</VoteBtn>
</VotesBtns>
)}
<CardVoteBottom>{vote && vote.timeLeft > 0 && <VoteSubmitButton vote={vote} />}</CardVoteBottom>
</div>
{!isDisabled && (
<HistoryLink
className={showHistoryModal ? 'opened' : ''}
onClick={() => setShowHistoryModal(!showHistoryModal)}
disabled={isDisabled}
>
Voting history
</HistoryLink>
)}
{showHistoryModal && (
<VoteHistoryTable>
<tbody>
<tr>
<VoteHistoryTableColumnCellDate>Date</VoteHistoryTableColumnCellDate>
<VoteHistoryTableColumnCell>Type</VoteHistoryTableColumnCell>
<VoteHistoryTableColumnCell>Result</VoteHistoryTableColumnCell>
</tr>
{room.details.votingHistory.map((vote) => {
return (
<tr key={vote.ID}>
<VoteHistoryTableCell>{vote.date.toLocaleDateString()}</VoteHistoryTableCell>
<VoteHistoryTableCell>{vote.type}</VoteHistoryTableCell>
<VoteHistoryTableCell>{vote.result}</VoteHistoryTableCell>
</tr>
)
})}
</tbody>
</VoteHistoryTable>
)}
</CardVoteBlock>
)
}
const CardHeadingMobile = styled(CardHeading)`
margin-bottom: 24px;
`
const VoteBtnFinal = styled(VoteBtn)`
width: 100%;
`
const CardVoteBottom = styled.div`
display: flex;
justify-content: flex-end;
align-items: center;
`
const Wrapper = styled.div`
margin-bottom: 24px;
`
const WrapperTop = styled.div`
margin-top: 32px;
`
const HistoryLink = styled(LinkInternal)`
width: 120px;
position: relative;
margin: 24px 0;
text-align: start;
padding: 0;
&::after {
content: '';
width: 24px;
height: 24px;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
background-image: url(${arrowDown});
background-size: contain;
background-repeat: no-repeat;
}
&.opened {
&::after {
content: '';
width: 24px;
height: 24px;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%) rotate(180deg);
background-image: url(${arrowDown});
background-size: contain;
background-repeat: no-repeat;
}
}
`

View File

@ -84,12 +84,13 @@ const HeaderMobile = styled.header`
left: 0px;
z-index: 100;
height: 186px;
@media (max-width: 340px) {
height: 205px;
}
`
const HeaderWrapperMobile = styled.div`
export const HeaderWrapperMobile = styled.div`
display: flex;
flex-direction: column;
border-bottom: 1px solid rgba(189, 93, 226, 0.15);

View File

@ -7,11 +7,11 @@ import { getVotingWinner } from '../helpers/voting'
import { VoteChart } from '../components/votes/VoteChart'
import { useHistory } from 'react-router'
interface VotingCardMobileProps {
interface VotingCardCoverProps {
room: DetailedVotingRoom
}
export function VotingCardMobile({ room }: VotingCardMobileProps) {
export function VotingCardCover({ room }: VotingCardCoverProps) {
const vote = voting.fromRoom(room)
const winner = getVotingWinner(vote)
const history = useHistory()

View File

@ -0,0 +1,39 @@
import React from 'react'
import styled from 'styled-components'
import { CardCommunityWrap, CardVoteWrap } from '../components/Card'
import { CardCommunity } from '../components/card/CardCommunity'
import { Colors } from '../constants/styles'
import { DetailedVotingRoom } from '../models/smartContract'
import { CardVoteMobile } from './CardVoteMobile'
import { ConnectMobile } from './ConnectMobile'
import { HeaderWrapperMobile } from './TopBarMobile'
export interface VotingMobileProps {
room: DetailedVotingRoom
}
export const VotingMobile = ({ room }: VotingMobileProps) => {
return (
<TopVoting>
<HeaderVotingMobile>
<ConnectMobile />
<CardCommunityWrap style={{ padding: '0 16px' }}>
{' '}
<CardCommunity community={room.details} />
</CardCommunityWrap>
</HeaderVotingMobile>
<CardVoteWrap style={{ padding: '16px' }}>
{' '}
<CardVoteMobile room={room} />
</CardVoteWrap>
</TopVoting>
)
}
const TopVoting = styled.div`
height: 100%;
`
const HeaderVotingMobile = styled(HeaderWrapperMobile)`
background-color: ${Colors.GrayLight};
padding-bottom: 12px;
`

View File

@ -1,13 +1,11 @@
import { useContractCall } from '@usedapp/core'
import React, { useEffect, useState } from 'react'
import { useParams } from 'react-router'
import styled from 'styled-components'
import { VotingCard } from '../components/votes/VotingCard'
import { VotingCardSkeleton } from '../components/votes/VotingCardSkeleton'
import { getCommunityDetails } from '../helpers/apiMock'
import { useCommunities } from '../hooks/useCommunities'
import { useContracts } from '../hooks/useContracts'
import { DetailedVotingRoom } from '../models/smartContract'
import { VotingMobile } from './VotingMobile'
export function VotingRoomMobile() {
const { id } = useParams<{ id: string }>()
@ -28,5 +26,5 @@ export function VotingRoomMobile() {
}
}, [votingRoom?.roomNumber?.toString(), details?.publicKey])
return <div>{detailedVotingRoom ? <VotingCard room={detailedVotingRoom} /> : <VotingCardSkeleton />}</div>
return <div>{detailedVotingRoom ? <VotingMobile room={detailedVotingRoom} /> : <VotingCardSkeleton />}</div>
}

View File

@ -49,9 +49,7 @@ export function DirectoryMobile() {
}
const Voting = styled.div`
@media (max-width: 600px) {
padding-top: 256px;
}
padding: 256px 16px 16px;
@media (max-width: 556px) {
padding-top: 266px;

View File

@ -23,6 +23,5 @@ export const MobileRouter = () => (
const PageContentMobile = styled.div`
height: 100%;
padding: 0px 16px 16px;
position: relative;
`

View File

@ -10,7 +10,7 @@ import { VotingSortingEnum } from '../models/community'
import styled from 'styled-components'
import { VotingCardSkeleton } from '../components/votes/VotingCardSkeleton'
import { VotingSortingOptions } from '../constants/SortingOptions'
import { VotingCardMobile } from '../componentsMobile/VotingCardMobile'
import { VotingCardCover } from '../componentsMobile/VotingCardCover'
export function VotesMobile() {
const [sortedBy, setSortedBy] = useState(VotingSortingEnum.EndingSoonest)
@ -41,7 +41,7 @@ export function VotesMobile() {
<VotingCardsWrapper>
{roomsToShow.map((room: any, idx) => {
if (room?.details) {
return <VotingCardMobile key={idx} room={room} />
return <VotingCardCover key={idx} room={room} />
} else {
return <VotingCardSkeleton key={idx} />
}
@ -54,7 +54,8 @@ export function VotesMobile() {
}
const VotingCardsWrapper = styled.div`
padding-top: 307px;
padding: 307px 16px 16px;
@media (max-width: 340px) {
padding-top: 320px;
}