Fix styling (#20)

This commit is contained in:
Szymon Szlachtowicz 2021-08-23 15:28:22 +02:00 committed by GitHub
parent bdf845943e
commit 7564d142ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 199 additions and 103 deletions

View File

@ -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
}

View File

@ -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>

View File

@ -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')
)

View File

@ -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) {

View File

@ -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;
`

View File

@ -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;
`

View File

@ -55,7 +55,7 @@ const Wrapper = styled.div`
display: flex;
flex-direction: column;
overflow: auto;
min-height: 500px;
height: 100%;
`
export default WakuPolling

View File

@ -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

View File

@ -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

View File

@ -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;
`