Add mobile voting (#142)
This commit is contained in:
parent
158bb211ca
commit
dc12c4e27b
|
@ -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%;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -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;
|
||||
`
|
||||
|
|
|
@ -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`
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
`
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
|
@ -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;
|
||||
`
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -23,6 +23,5 @@ export const MobileRouter = () => (
|
|||
|
||||
const PageContentMobile = styled.div`
|
||||
height: 100%;
|
||||
padding: 0px 16px 16px;
|
||||
position: relative;
|
||||
`
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue