mirror of
https://github.com/status-im/community-dapp.git
synced 2025-02-23 11:38:40 +00:00
Extract CardCommunity (#98)
This commit is contained in:
parent
968b3f86c0
commit
f392681556
@ -1,101 +1,4 @@
|
|||||||
import React, { useState } from 'react'
|
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Colors } from '../constants/styles'
|
|
||||||
import { CommunityDetail } from '../models/community'
|
|
||||||
import { LinkExternal, LinkInternal } from './Link'
|
|
||||||
import { Modal } from './Modal'
|
|
||||||
import { VoteConfirmModal } from './card/VoteConfirmModal'
|
|
||||||
import binIcon from '../assets/images/bin.svg'
|
|
||||||
import { RemoveModal } from './card/RemoveModal'
|
|
||||||
|
|
||||||
interface CardCommunityProps {
|
|
||||||
community: CommunityDetail
|
|
||||||
showRemoveButton?: boolean
|
|
||||||
customHeading?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CardCommunity = ({ community, showRemoveButton, customHeading }: CardCommunityProps) => {
|
|
||||||
const [showHistoryModal, setShowHistoryModal] = useState(false)
|
|
||||||
const [showRemoveModal, setShowRemoveModal] = useState(false)
|
|
||||||
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
|
||||||
|
|
||||||
const isDisabled = community.votingHistory.length === 0
|
|
||||||
|
|
||||||
const setNewModal = (val: boolean) => {
|
|
||||||
setShowConfirmModal(val)
|
|
||||||
setShowRemoveModal(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CardCommunityBlock>
|
|
||||||
{showHistoryModal && (
|
|
||||||
<Modal heading={`${community.name} voting history`} setShowModal={setShowHistoryModal}>
|
|
||||||
<VoteHistoryTable>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<VoteHistoryTableColumnCell>Date</VoteHistoryTableColumnCell>
|
|
||||||
<VoteHistoryTableColumnCell>Type</VoteHistoryTableColumnCell>
|
|
||||||
<VoteHistoryTableColumnCell>Result</VoteHistoryTableColumnCell>
|
|
||||||
</tr>
|
|
||||||
{community.votingHistory.map((vote) => {
|
|
||||||
return (
|
|
||||||
<tr key={vote.ID}>
|
|
||||||
<VoteHistoryTableCell>{vote.date.toLocaleDateString()}</VoteHistoryTableCell>
|
|
||||||
<VoteHistoryTableCell>{vote.type}</VoteHistoryTableCell>
|
|
||||||
<VoteHistoryTableCell>{vote.result}</VoteHistoryTableCell>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</tbody>
|
|
||||||
</VoteHistoryTable>
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
{showRemoveModal && (
|
|
||||||
<Modal
|
|
||||||
heading="Remove from directory?"
|
|
||||||
setShowModal={(val: boolean) => {
|
|
||||||
setShowRemoveModal(val)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<RemoveModal community={community} availableAmount={549739700} setShowConfirmModal={setNewModal} />{' '}
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
{showConfirmModal && (
|
|
||||||
<Modal setShowModal={setNewModal}>
|
|
||||||
<VoteConfirmModal community={community} selectedVote={{ verb: 'to remove' }} setShowModal={setNewModal} />
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
<Community>
|
|
||||||
<CardLogoWrap>
|
|
||||||
{' '}
|
|
||||||
<CardLogo src={community.icon} alt={`${community.name} logo`} />
|
|
||||||
</CardLogoWrap>
|
|
||||||
|
|
||||||
<CommunityInfo>
|
|
||||||
<CardTop>
|
|
||||||
<CardHeading>{customHeading ? customHeading : community.name}</CardHeading>
|
|
||||||
{community.directoryInfo && showRemoveButton && <RemoveBtn onClick={() => setShowRemoveModal(true)} />}
|
|
||||||
</CardTop>
|
|
||||||
<CardText>{community.description}</CardText>
|
|
||||||
<CardTags>
|
|
||||||
{community.tags.map((tag, key) => (
|
|
||||||
<Tag key={key}>
|
|
||||||
<p>{tag}</p>
|
|
||||||
</Tag>
|
|
||||||
))}
|
|
||||||
</CardTags>
|
|
||||||
</CommunityInfo>
|
|
||||||
</Community>
|
|
||||||
<CardLinks>
|
|
||||||
<LinkExternal>Visit community</LinkExternal>
|
|
||||||
<LinkExternal>Etherscan</LinkExternal>
|
|
||||||
<LinkInternal onClick={() => setShowHistoryModal(true)} disabled={isDisabled}>
|
|
||||||
Voting history
|
|
||||||
</LinkInternal>
|
|
||||||
</CardLinks>
|
|
||||||
</CardCommunityBlock>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Card = styled.div`
|
export const Card = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -108,13 +11,6 @@ export const Card = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const CardCommunityBlock = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const CardCommunityWrap = styled.div`
|
export const CardCommunityWrap = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
@ -146,7 +42,6 @@ export const CardVoteWrap = styled.div`
|
|||||||
border-bottom: 1px solid #e0e0e0;
|
border-bottom: 1px solid #e0e0e0;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const CardVoteBlock = styled.div`
|
export const CardVoteBlock = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -154,96 +49,9 @@ export const CardVoteBlock = styled.div`
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
`
|
`
|
||||||
|
|
||||||
const Community = styled.div`
|
|
||||||
display: flex;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
`
|
|
||||||
|
|
||||||
const CommunityInfo = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
`
|
|
||||||
|
|
||||||
const CardLogoWrap = styled.div`
|
|
||||||
width: 64px !important;
|
|
||||||
height: 64px !important;
|
|
||||||
object-fit: cover;
|
|
||||||
margin-right: 16px;
|
|
||||||
`
|
|
||||||
const CardLogo = styled.img`
|
|
||||||
width: 64px !important;
|
|
||||||
height: 64px !important;
|
|
||||||
border-radius: 50%;
|
|
||||||
`
|
|
||||||
|
|
||||||
export const CardHeading = styled.h2`
|
export const CardHeading = styled.h2`
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
`
|
`
|
||||||
|
|
||||||
const CardTop = styled.div`
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
line-height: 24px;
|
|
||||||
`
|
|
||||||
|
|
||||||
const RemoveBtn = styled.button`
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: 16px;
|
|
||||||
background-image: url(${binIcon});
|
|
||||||
background-size: cover;
|
|
||||||
`
|
|
||||||
|
|
||||||
const CardText = styled.p`
|
|
||||||
line-height: 22px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
`
|
|
||||||
|
|
||||||
const CardTags = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
`
|
|
||||||
const Tag = styled.div`
|
|
||||||
margin: 0 8px 8px 0;
|
|
||||||
padding: 0 10px;
|
|
||||||
border: 1px solid ${Colors.VioletDark};
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 10px;
|
|
||||||
color: ${Colors.VioletDark};
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 20px;
|
|
||||||
`
|
|
||||||
export const CardLinks = styled.div`
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 15px;
|
|
||||||
line-height: 22px;
|
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
width: auto;
|
|
||||||
margin-left: 80px;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const VoteHistoryTable = styled.table`
|
|
||||||
width: 100%;
|
|
||||||
`
|
|
||||||
|
|
||||||
const VoteHistoryTableColumnCell = styled.td`
|
|
||||||
font-weight: bold;
|
|
||||||
padding-bottom: 24px;
|
|
||||||
padding-right: 112px;
|
|
||||||
width: 65px;
|
|
||||||
`
|
|
||||||
|
|
||||||
const VoteHistoryTableCell = styled.td`
|
|
||||||
width: 65px;
|
|
||||||
padding-bottom: 18px;
|
|
||||||
padding-right: 112px;
|
|
||||||
`
|
|
||||||
|
193
packages/DApp/src/components/card/CardCommunity.tsx
Normal file
193
packages/DApp/src/components/card/CardCommunity.tsx
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import styled from 'styled-components'
|
||||||
|
import { Colors } from '../../constants/styles'
|
||||||
|
import { CommunityDetail } from '../../models/community'
|
||||||
|
import { LinkExternal, LinkInternal } from '../Link'
|
||||||
|
import { Modal } from '../Modal'
|
||||||
|
import { VoteConfirmModal } from './VoteConfirmModal'
|
||||||
|
import binIcon from '../../assets/images/bin.svg'
|
||||||
|
import { RemoveModal } from './RemoveModal'
|
||||||
|
import { CardHeading } from '../Card'
|
||||||
|
|
||||||
|
interface CardCommunityProps {
|
||||||
|
community: CommunityDetail
|
||||||
|
showRemoveButton?: boolean
|
||||||
|
customHeading?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CardCommunity = ({ community, showRemoveButton, customHeading }: CardCommunityProps) => {
|
||||||
|
const [showHistoryModal, setShowHistoryModal] = useState(false)
|
||||||
|
const [showRemoveModal, setShowRemoveModal] = useState(false)
|
||||||
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
||||||
|
|
||||||
|
const isDisabled = community.votingHistory.length === 0
|
||||||
|
|
||||||
|
const setNewModal = (val: boolean) => {
|
||||||
|
setShowConfirmModal(val)
|
||||||
|
setShowRemoveModal(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CardCommunityBlock>
|
||||||
|
{showHistoryModal && (
|
||||||
|
<Modal heading={`${community.name} voting history`} setShowModal={setShowHistoryModal}>
|
||||||
|
<VoteHistoryTable>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<VoteHistoryTableColumnCell>Date</VoteHistoryTableColumnCell>
|
||||||
|
<VoteHistoryTableColumnCell>Type</VoteHistoryTableColumnCell>
|
||||||
|
<VoteHistoryTableColumnCell>Result</VoteHistoryTableColumnCell>
|
||||||
|
</tr>
|
||||||
|
{community.votingHistory.map((vote) => {
|
||||||
|
return (
|
||||||
|
<tr key={vote.ID}>
|
||||||
|
<VoteHistoryTableCell>{vote.date.toLocaleDateString()}</VoteHistoryTableCell>
|
||||||
|
<VoteHistoryTableCell>{vote.type}</VoteHistoryTableCell>
|
||||||
|
<VoteHistoryTableCell>{vote.result}</VoteHistoryTableCell>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</VoteHistoryTable>
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
{showRemoveModal && (
|
||||||
|
<Modal
|
||||||
|
heading="Remove from directory?"
|
||||||
|
setShowModal={(val: boolean) => {
|
||||||
|
setShowRemoveModal(val)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<RemoveModal community={community} availableAmount={549739700} setShowConfirmModal={setNewModal} />{' '}
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
{showConfirmModal && (
|
||||||
|
<Modal setShowModal={setNewModal}>
|
||||||
|
<VoteConfirmModal community={community} selectedVote={{ verb: 'to remove' }} setShowModal={setNewModal} />
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
<Community>
|
||||||
|
<CardLogoWrap>
|
||||||
|
{' '}
|
||||||
|
<CardLogo src={community.icon} alt={`${community.name} logo`} />
|
||||||
|
</CardLogoWrap>
|
||||||
|
|
||||||
|
<CommunityInfo>
|
||||||
|
<CardTop>
|
||||||
|
<CardHeading>{customHeading ? customHeading : community.name}</CardHeading>
|
||||||
|
{community.directoryInfo && showRemoveButton && <RemoveBtn onClick={() => setShowRemoveModal(true)} />}
|
||||||
|
</CardTop>
|
||||||
|
<CardText>{community.description}</CardText>
|
||||||
|
<CardTags>
|
||||||
|
{community.tags.map((tag, key) => (
|
||||||
|
<Tag key={key}>
|
||||||
|
<p>{tag}</p>
|
||||||
|
</Tag>
|
||||||
|
))}
|
||||||
|
</CardTags>
|
||||||
|
</CommunityInfo>
|
||||||
|
</Community>
|
||||||
|
<CardLinks>
|
||||||
|
<LinkExternal>Visit community</LinkExternal>
|
||||||
|
<LinkExternal>Etherscan</LinkExternal>
|
||||||
|
<LinkInternal onClick={() => setShowHistoryModal(true)} disabled={isDisabled}>
|
||||||
|
Voting history
|
||||||
|
</LinkInternal>
|
||||||
|
</CardLinks>
|
||||||
|
</CardCommunityBlock>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CardCommunityBlock = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const Community = styled.div`
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CommunityInfo = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CardLogoWrap = styled.div`
|
||||||
|
width: 64px !important;
|
||||||
|
height: 64px !important;
|
||||||
|
object-fit: cover;
|
||||||
|
margin-right: 16px;
|
||||||
|
`
|
||||||
|
const CardLogo = styled.img`
|
||||||
|
width: 64px !important;
|
||||||
|
height: 64px !important;
|
||||||
|
border-radius: 50%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CardTop = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
line-height: 24px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const RemoveBtn = styled.button`
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
|
background-image: url(${binIcon});
|
||||||
|
background-size: cover;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CardText = styled.p`
|
||||||
|
line-height: 22px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const CardTags = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
`
|
||||||
|
const Tag = styled.div`
|
||||||
|
margin: 0 8px 8px 0;
|
||||||
|
padding: 0 10px;
|
||||||
|
border: 1px solid ${Colors.VioletDark};
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: ${Colors.VioletDark};
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 20px;
|
||||||
|
`
|
||||||
|
export const CardLinks = styled.div`
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
width: auto;
|
||||||
|
margin-left: 80px;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteHistoryTable = styled.table`
|
||||||
|
width: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteHistoryTableColumnCell = styled.td`
|
||||||
|
font-weight: bold;
|
||||||
|
padding-bottom: 24px;
|
||||||
|
padding-right: 112px;
|
||||||
|
width: 65px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const VoteHistoryTableCell = styled.td`
|
||||||
|
width: 65px;
|
||||||
|
padding-bottom: 18px;
|
||||||
|
padding-right: 112px;
|
||||||
|
`
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { CommunityDetail } from '../../models/community'
|
import { CommunityDetail } from '../../models/community'
|
||||||
import { CardCommunity } from '../Card'
|
import { CardCommunity } from './CardCommunity'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import { VotePropose } from '../votes/VotePropose'
|
import { VotePropose } from '../votes/VotePropose'
|
||||||
import { ColumnFlexDiv } from '../../constants/styles'
|
import { ColumnFlexDiv } from '../../constants/styles'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { ButtonPrimary } from '../Button'
|
import { ButtonPrimary } from '../Button'
|
||||||
import { CardCommunity } from '../Card'
|
import { CardCommunity } from './CardCommunity'
|
||||||
import { Input } from '../Input'
|
import { Input } from '../Input'
|
||||||
import { VotePropose } from '../votes/VotePropose'
|
import { VotePropose } from '../votes/VotePropose'
|
||||||
import { Warning } from '../votes/VoteWarning'
|
import { Warning } from '../votes/VoteWarning'
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ColumnFlexDiv } from '../../constants/styles'
|
import { ColumnFlexDiv } from '../../constants/styles'
|
||||||
import { CommunityDetail } from '../../models/community'
|
import { CommunityDetail } from '../../models/community'
|
||||||
import { CardCommunity } from '../Card'
|
import { CardCommunity } from './CardCommunity'
|
||||||
import { RemoveAmountPicker } from '../card/RemoveAmountPicker'
|
import { RemoveAmountPicker } from '../card/RemoveAmountPicker'
|
||||||
|
|
||||||
interface RemoveModalProps {
|
interface RemoveModalProps {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Card, CardCommunity, CardCommunityWrap, CardVoteWrap } from '../Card'
|
import { Card, CardCommunityWrap, CardVoteWrap } from '../Card'
|
||||||
|
import { CardCommunity } from '../card/CardCommunity'
|
||||||
import { CardFeature } from '../card/CardFeature'
|
import { CardFeature } from '../card/CardFeature'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { CommunityDetail, DirectorySortingEnum } from '../../models/community'
|
import { CommunityDetail, DirectorySortingEnum } from '../../models/community'
|
||||||
@ -13,6 +14,7 @@ import { useConfig } from '../../providers/config'
|
|||||||
import { Colors } from '../../constants/styles'
|
import { Colors } from '../../constants/styles'
|
||||||
import { WeeklyFeature } from '../WeeklyFeature'
|
import { WeeklyFeature } from '../WeeklyFeature'
|
||||||
import { DirectoryCardSkeleton } from './DirectoryCardSkeleton'
|
import { DirectoryCardSkeleton } from './DirectoryCardSkeleton'
|
||||||
|
|
||||||
interface DirectoryCardProps {
|
interface DirectoryCardProps {
|
||||||
community: CommunityDetail
|
community: CommunityDetail
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { CardCommunityBlock, CardLinks } from '../Card'
|
import { CardCommunityBlock, CardLinks } from '../card/CardCommunity'
|
||||||
import { LinkExternal, LinkInternal } from '../Link'
|
import { LinkExternal, LinkInternal } from '../Link'
|
||||||
import { Skeleton } from '../skeleton/Skeleton'
|
import { Skeleton } from '../skeleton/Skeleton'
|
||||||
import { TagsSkeletonList } from '../skeleton/TagSkeleton'
|
import { TagsSkeletonList } from '../skeleton/TagSkeleton'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { DetailedVotingRoom } from '../../models/smartContract'
|
import { DetailedVotingRoom } from '../../models/smartContract'
|
||||||
import { Card, CardCommunity, CardCommunityWrap, CardVoteWrap } from '../Card'
|
import { Card, CardCommunityWrap, CardVoteWrap } from '../Card'
|
||||||
|
import { CardCommunity } from '../card/CardCommunity'
|
||||||
import { CardVote } from './../card/CardVote/CardVote'
|
import { CardVote } from './../card/CardVote/CardVote'
|
||||||
|
|
||||||
interface VotingCardProps {
|
interface VotingCardProps {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user