Fix styling (#20)
This commit is contained in:
parent
bdf845943e
commit
7564d142ab
|
@ -139,8 +139,8 @@ class WakuVoting {
|
|||
let updated = false
|
||||
if (!this.asyncUpdating) {
|
||||
this.asyncUpdating = true
|
||||
const { polls, updatedPolls } = await this.getTimedPolls()
|
||||
const { votes, updatedVotes } = await this.getTimedPollsVotes()
|
||||
const { updatedPolls } = await this.getTimedPolls()
|
||||
const { updatedVotes } = await this.getTimedPollsVotes()
|
||||
updated = updatedPolls || updatedVotes
|
||||
this.asyncUpdating = false
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1" />
|
||||
<link rel="icon" type="image/svg+xml" sizes="any" href="/favicon.ico" />
|
||||
<title>waku voting example</title>
|
||||
</head>
|
||||
|
|
|
@ -1,10 +1,28 @@
|
|||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { WakuPolling } from '@status-waku-voting/react-components'
|
||||
import styled, { createGlobalStyle } from 'styled-components'
|
||||
|
||||
export const GlobalStyle = createGlobalStyle`
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body, html, #root {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
`
|
||||
|
||||
const Page = styled.div`
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
ReactDOM.render(
|
||||
<div>
|
||||
<Page>
|
||||
<GlobalStyle />
|
||||
<WakuPolling appName={'testApp_'} />
|
||||
</div>,
|
||||
</Page>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
|
|
|
@ -5,7 +5,6 @@ import React, { useEffect, useState } from 'react'
|
|||
import { JsonRpcSigner } from '@ethersproject/providers'
|
||||
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
import styled from 'styled-components'
|
||||
import checkIcon from '../assets/svg/checkIcon.svg'
|
||||
import { RadioGroup } from '../components/radioGroup'
|
||||
import { SmallButton } from '../components/misc/Buttons'
|
||||
import { PollResults } from './PollResults'
|
||||
|
@ -20,21 +19,22 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
const [selectedAnswer, setSelectedAnswer] = useState<number | undefined>(undefined)
|
||||
const [tokenAmount, setTokenAmount] = useState(0)
|
||||
const [address, setAddress] = useState('')
|
||||
const [userInVoters, setUserInVoters] = useState(false)
|
||||
const [userInVoters, setUserInVoters] = useState(-1)
|
||||
|
||||
useEffect(() => {
|
||||
signer.getAddress().then((e) => setAddress(e))
|
||||
}, [signer])
|
||||
|
||||
useEffect(() => {
|
||||
setUserInVoters(!!poll.votesMessages.find((vote) => vote.voter === address))
|
||||
const msg = poll.votesMessages.find((vote) => vote.voter === address)
|
||||
setUserInVoters(msg?.answer ?? -1)
|
||||
}, [poll, address])
|
||||
|
||||
return (
|
||||
<PollWrapper>
|
||||
<PollTitle>{poll.poll.question}</PollTitle>
|
||||
<PollAnswersWrapper>
|
||||
{!userInVoters && (
|
||||
{userInVoters < 0 && (
|
||||
<VotingWrapper>
|
||||
<RadioGroup
|
||||
options={poll.poll.answers}
|
||||
|
@ -53,9 +53,9 @@ export function Poll({ poll, wakuVoting, signer }: PollProps) {
|
|||
)}
|
||||
</VotingWrapper>
|
||||
)}
|
||||
{userInVoters && <PollResults poll={poll} />}
|
||||
{userInVoters > -1 && <PollResults poll={poll} selectedVote={userInVoters} />}
|
||||
</PollAnswersWrapper>
|
||||
{!userInVoters && (
|
||||
{userInVoters < 0 && (
|
||||
<SmallButton
|
||||
onClick={() => {
|
||||
if (wakuVoting) {
|
||||
|
|
|
@ -4,6 +4,9 @@ import { JsonRpcSigner } from '@ethersproject/providers'
|
|||
import styled from 'styled-components'
|
||||
import { PollType } from '@status-waku-voting/core/dist/esm/src/types/PollType'
|
||||
import WakuVoting from '@status-waku-voting/core'
|
||||
import { Input } from '../components/Input'
|
||||
import addIcon from '../assets/svg/addIcon.svg'
|
||||
import { SmallButton } from '../components/misc/Buttons'
|
||||
|
||||
function getLocaleIsoTime(dateTime: Date) {
|
||||
const MS_PER_MINUTE = 60000
|
||||
|
@ -19,122 +22,123 @@ type PollCreationProps = {
|
|||
}
|
||||
|
||||
export function PollCreation({ signer, wakuVoting, setShowPollCreation }: PollCreationProps) {
|
||||
const [answers, setAnswers] = useState<string[]>([''])
|
||||
const [answers, setAnswers] = useState<string[]>(['', ''])
|
||||
const [question, setQuestion] = useState('')
|
||||
const [selectedType, setSelectedType] = useState(PollType.WEIGHTED)
|
||||
const [selectedType, setSelectedType] = useState(PollType.NON_WEIGHTED)
|
||||
const [endTimePicker, setEndTimePicker] = useState(new Date(new Date().getTime() + 10000000))
|
||||
|
||||
return (
|
||||
<NewPollBoxWrapper onClick={(e) => e.stopPropagation()}>
|
||||
<NewPollBox>
|
||||
<NewPollBoxTitle>
|
||||
Question
|
||||
<CloseNewPollBoxButton onClick={() => setShowPollCreation(false)}>X</CloseNewPollBoxButton>
|
||||
</NewPollBoxTitle>
|
||||
<input value={question} onChange={(e) => setQuestion(e.target.value)} />
|
||||
Poll end time
|
||||
<input
|
||||
type="datetime-local"
|
||||
value={getLocaleIsoTime(endTimePicker)}
|
||||
onChange={(e) => setEndTimePicker(new Date(e.target.value))}
|
||||
/>
|
||||
Answers
|
||||
<button onClick={() => setAnswers((answers) => [...answers, ''])}>Add answer</button>
|
||||
{answers.map((answer, idx) => (
|
||||
<AnswerWraper key={idx}>
|
||||
<AnswerInput
|
||||
value={answer}
|
||||
onChange={(e) =>
|
||||
setAnswers((answers) => {
|
||||
const newAnswers = [...answers]
|
||||
newAnswers[idx] = e.target.value
|
||||
return newAnswers
|
||||
})
|
||||
}
|
||||
/>
|
||||
<RemoveAnswerButton
|
||||
onClick={() =>
|
||||
setAnswers((answers) => {
|
||||
const newAnswers = [...answers]
|
||||
if (newAnswers.length > 1) {
|
||||
newAnswers.splice(idx, 1)
|
||||
}
|
||||
return newAnswers
|
||||
})
|
||||
}
|
||||
>
|
||||
-
|
||||
</RemoveAnswerButton>
|
||||
</AnswerWraper>
|
||||
))}
|
||||
<div onChange={(e) => setSelectedType(Number.parseInt((e.target as any).value))}>
|
||||
<input type="radio" value={PollType.WEIGHTED} name="newPollType" /> Weighted
|
||||
<input type="radio" value={PollType.NON_WEIGHTED} name="newPollType" /> Non weighted
|
||||
</div>
|
||||
<SendButton
|
||||
onClick={async () => {
|
||||
await wakuVoting?.createTimedPoll(
|
||||
signer,
|
||||
question,
|
||||
answers,
|
||||
selectedType,
|
||||
undefined,
|
||||
endTimePicker.getTime()
|
||||
)
|
||||
setAnswers([''])
|
||||
setShowPollCreation(false)
|
||||
}}
|
||||
>
|
||||
Send
|
||||
</SendButton>
|
||||
</NewPollBox>
|
||||
<BoxWrapper>
|
||||
<NewPollBox>
|
||||
<NewPollBoxTitle>
|
||||
Create a poll
|
||||
<CloseNewPollBoxButton onClick={() => setShowPollCreation(false)}>X</CloseNewPollBoxButton>
|
||||
</NewPollBoxTitle>
|
||||
<Input
|
||||
label={'Question or title of the poll'}
|
||||
placeholder={'E.g. What is your favourite color?'}
|
||||
value={question}
|
||||
onChange={(e) => setQuestion(e.target.value)}
|
||||
/>
|
||||
|
||||
<AnswersWraper>
|
||||
{answers.map((answer, idx) => (
|
||||
<Input
|
||||
key={idx}
|
||||
label={`Option ${idx + 1}`}
|
||||
value={answer}
|
||||
onChange={(e) =>
|
||||
setAnswers((answers) => {
|
||||
const newAnswers = [...answers]
|
||||
newAnswers[idx] = e.target.value
|
||||
return newAnswers
|
||||
})
|
||||
}
|
||||
/>
|
||||
))}
|
||||
</AnswersWraper>
|
||||
<NewOptionButton onClick={() => setAnswers((answers) => [...answers, ''])}>
|
||||
Add another option
|
||||
<AddIcon />
|
||||
</NewOptionButton>
|
||||
<SmallButton
|
||||
onClick={async () => {
|
||||
await wakuVoting?.createTimedPoll(
|
||||
signer,
|
||||
question,
|
||||
answers,
|
||||
selectedType,
|
||||
undefined,
|
||||
endTimePicker.getTime()
|
||||
)
|
||||
setShowPollCreation(false)
|
||||
}}
|
||||
>
|
||||
Send
|
||||
</SmallButton>
|
||||
</NewPollBox>
|
||||
</BoxWrapper>
|
||||
</NewPollBoxWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
const AddIcon = styled.div`
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url(${addIcon});
|
||||
margin-left: 10px;
|
||||
`
|
||||
|
||||
const CloseNewPollBoxButton = styled.div`
|
||||
width: 5px;
|
||||
margin-right: 5px;
|
||||
margin-left: auto;
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
`
|
||||
|
||||
const NewPollBoxTitle = styled.div`
|
||||
display: flex;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 17px;
|
||||
line-height: 24px;
|
||||
`
|
||||
|
||||
const AnswerInput = styled.input`
|
||||
margin-right: 5px;
|
||||
width: 200px;
|
||||
`
|
||||
|
||||
const RemoveAnswerButton = styled.button`
|
||||
margin-right: 5px;
|
||||
const NewOptionButton = styled.div`
|
||||
margin-top: 33px;
|
||||
margin-bottom: 33px;
|
||||
margin-left: auto;
|
||||
`
|
||||
|
||||
const SendButton = styled.button`
|
||||
margin: 10px;
|
||||
`
|
||||
|
||||
const AnswerWraper = styled.div`
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
margin: 5px;
|
||||
width: 250px;
|
||||
font-family: 'Inter, sans-serif';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
`
|
||||
|
||||
const AnswersWraper = styled.div`
|
||||
margin-left: 64px;
|
||||
margin-right: 64px;
|
||||
`
|
||||
|
||||
const NewPollBox = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: white;
|
||||
margin: 20px;
|
||||
padding: 20px;
|
||||
box-shadow: 10px 10px 31px -2px #a3a1a1;
|
||||
border-radius: 5px;
|
||||
overflow: auto;
|
||||
z-index: 1;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
z-index: 5;
|
||||
width: 468px;
|
||||
`
|
||||
|
||||
const BoxWrapper = styled.div`
|
||||
position: absolute;
|
||||
marign-bottom: 100px;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
`
|
||||
|
|
|
@ -2,12 +2,14 @@ import React from 'react'
|
|||
import { DetailedTimedPoll } from '@status-waku-voting/core/dist/esm/src/models/DetailedTimedPoll'
|
||||
import styled from 'styled-components'
|
||||
import { colorRouletteGenerator } from '../style/colors'
|
||||
import checkCircle from '../assets/svg/checkCircle.svg'
|
||||
|
||||
type PollResultsProps = {
|
||||
poll: DetailedTimedPoll
|
||||
selectedVote: number
|
||||
}
|
||||
|
||||
export function PollResults({ poll }: PollResultsProps) {
|
||||
export function PollResults({ poll, selectedVote }: PollResultsProps) {
|
||||
const colors = colorRouletteGenerator()
|
||||
return (
|
||||
<Wrapper>
|
||||
|
@ -21,6 +23,7 @@ export function PollResults({ poll }: PollResultsProps) {
|
|||
<ColorBar style={{ backgroundColor: colors.next().value ?? '', width: `${percentage}%` }} />
|
||||
<Transparent>
|
||||
<PollAnswerText>{answer.text}</PollAnswerText>
|
||||
{selectedVote === idx && <CheckCircle />}
|
||||
<VoteCount>{`${percentage}%`}</VoteCount>
|
||||
</Transparent>
|
||||
</PollAnswer>
|
||||
|
@ -35,6 +38,15 @@ export function PollResults({ poll }: PollResultsProps) {
|
|||
)
|
||||
}
|
||||
|
||||
const CheckCircle = styled.div`
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
margin-left: 8px;
|
||||
background-image: url(${checkCircle});
|
||||
`
|
||||
|
||||
const Transparent = styled.div`
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -63,26 +75,40 @@ const ResultInfoWrapper = styled.div`
|
|||
margin-right: auto;
|
||||
margin-bottom: 32px;
|
||||
margin-top: 32px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
`
|
||||
|
||||
const VoteCount = styled.div`
|
||||
margin-left: auto;
|
||||
margin-top: auto;
|
||||
margin-bottom: auto;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-family: 'Inter, sans-serif';
|
||||
`
|
||||
|
||||
const PollAnswer = styled.div`
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 16px;
|
||||
height: 40px;
|
||||
position: relative;
|
||||
font-family: 'Inter, sans-serif';
|
||||
`
|
||||
|
||||
const PollAnswerText = styled.div`
|
||||
width: 200px;
|
||||
font-weight: 700;
|
||||
font-size: 10px;
|
||||
height: 100%;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 8px;
|
||||
font-weight: 500;
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
align-items: center;
|
||||
letter-spacing: 1.5px;
|
||||
text-transform: uppercase;
|
||||
`
|
||||
|
|
|
@ -55,7 +55,7 @@ const Wrapper = styled.div`
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
min-height: 500px;
|
||||
height: 100%;
|
||||
`
|
||||
|
||||
export default WakuPolling
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 5.25C10.4142 5.25 10.75 5.58579 10.75 6V8.75C10.75 9.02614 10.9739 9.25 11.25 9.25H14C14.4142 9.25 14.75 9.58579 14.75 10C14.75 10.4142 14.4142 10.75 14 10.75H11.25C10.9739 10.75 10.75 10.9739 10.75 11.25V14C10.75 14.4142 10.4142 14.75 10 14.75C9.58579 14.75 9.25 14.4142 9.25 14V11.25C9.25 10.9739 9.02614 10.75 8.75 10.75H6C5.58579 10.75 5.25 10.4142 5.25 10C5.25 9.58579 5.58579 9.25 6 9.25H8.75C9.02614 9.25 9.25 9.02614 9.25 8.75V6C9.25 5.58579 9.58579 5.25 10 5.25Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 20C15.5228 20 20 15.5228 20 10C20 4.47715 15.5228 -2.41411e-07 10 0C4.47715 2.41411e-07 -2.41411e-07 4.47715 0 10C2.41411e-07 15.5228 4.47715 20 10 20ZM10 18.5C14.6944 18.5 18.5 14.6944 18.5 10C18.5 5.30558 14.6944 1.5 10 1.5C5.30558 1.5 1.5 5.30558 1.5 10C1.5 14.6944 5.30558 18.5 10 18.5Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 964 B |
|
@ -0,0 +1,3 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5 7L6.33333 8.33333L9 5.66667M13 7C13 7.78793 12.8448 8.56815 12.5433 9.2961C12.2417 10.0241 11.7998 10.6855 11.2426 11.2426C10.6855 11.7998 10.0241 12.2417 9.2961 12.5433C8.56815 12.8448 7.78793 13 7 13C6.21207 13 5.43185 12.8448 4.7039 12.5433C3.97595 12.2417 3.31451 11.7998 2.75736 11.2426C2.20021 10.6855 1.75825 10.0241 1.45672 9.2961C1.15519 8.56815 1 7.78793 1 7C1 5.4087 1.63214 3.88258 2.75736 2.75736C3.88258 1.63214 5.4087 1 7 1C8.5913 1 10.1174 1.63214 11.2426 2.75736C12.3679 3.88258 13 5.4087 13 7Z" stroke="#374151" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 713 B |
|
@ -0,0 +1,41 @@
|
|||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
type InputProps = {
|
||||
label: string
|
||||
value: string
|
||||
onChange: (e: any) => void
|
||||
placeholder?: string
|
||||
}
|
||||
|
||||
export function Input({ label, value, onChange, placeholder }: InputProps) {
|
||||
return (
|
||||
<InputWrapper>
|
||||
<LabelWrapper>{label}</LabelWrapper>
|
||||
<StyledInput value={value} onChange={onChange} placeholder={placeholder} />
|
||||
</InputWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
const StyledInput = styled.input`
|
||||
background-color: #eef2f5;
|
||||
border-radius: 8px;
|
||||
border: 0px;
|
||||
height: 44px;
|
||||
padding-left: 20px;
|
||||
font-weight: 400px;
|
||||
font-size: 15px;
|
||||
font-family: 'Inter, sans-serif';
|
||||
`
|
||||
|
||||
const LabelWrapper = styled.div`
|
||||
font-weight: 400px;
|
||||
font-size: 15px;
|
||||
font-family: 'Inter, sans-serif';
|
||||
margin-bottom: 10px;
|
||||
`
|
||||
|
||||
const InputWrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 32px;
|
||||
`
|
Loading…
Reference in New Issue