Resolve answer UI

This commit is contained in:
James Grugett 2022-02-15 18:08:21 -06:00
parent fbdc6eacad
commit 0a178a7519
5 changed files with 192 additions and 34 deletions

View File

@ -14,7 +14,7 @@ import { Avatar } from './avatar'
import { SiteLink } from './site-link'
import { DateTimeTooltip } from './datetime-tooltip'
import dayjs from 'dayjs'
import { BuyButton } from './yes-no-selector'
import { BuyButton, ChooseCancelSelector } from './yes-no-selector'
import { Spacer } from './layout/spacer'
import {
formatMoney,
@ -32,6 +32,7 @@ import {
import { firebaseLogin } from '../lib/firebase/users'
import { Bet } from '../../common/bet'
import { useAnswers } from '../hooks/use-answers'
import { ResolveConfirmationButton } from './confirmation-button'
export function AnswersPanel(props: {
contract: Contract<'MULTI'>
@ -45,18 +46,49 @@ export function AnswersPanel(props: {
(answer) => -1 * getOutcomeProbability(contract.totalShares, answer.id)
)
const user = useUser()
const [resolveOption, setResolveOption] = useState<
'CHOOSE' | 'CANCEL' | undefined
>()
const [answerChoice, setAnswerChoice] = useState<string | undefined>()
return (
<Col className="gap-3">
{sortedAnswers.map((answer) => (
<AnswerItem key={answer.id} answer={answer} contract={contract} />
<AnswerItem
key={answer.id}
answer={answer}
contract={contract}
showChoice={resolveOption === 'CHOOSE'}
isChosen={answer.id === answerChoice}
onChoose={() => setAnswerChoice(answer.id)}
/>
))}
<CreateAnswerInput contract={contract} />
{user?.id === contract.creatorId && (
<AnswerResolvePanel
contract={contract}
resolveOption={resolveOption}
setResolveOption={setResolveOption}
answer={answerChoice}
clearAnswerChoice={() => setAnswerChoice(undefined)}
/>
)}
</Col>
)
}
function AnswerItem(props: { answer: Answer; contract: Contract<'MULTI'> }) {
const { answer, contract } = props
function AnswerItem(props: {
answer: Answer
contract: Contract<'MULTI'>
showChoice: boolean
isChosen: boolean
onChoose: () => void
}) {
const { answer, contract, showChoice, isChosen, onChoose } = props
const { username, avatarUrl, name, createdTime, number, text } = answer
const createdDate = dayjs(createdTime).format('MMM D')
@ -99,12 +131,28 @@ function AnswerItem(props: { answer: Answer; contract: Contract<'MULTI'> }) {
) : (
<Row className="self-end sm:self-start items-center gap-4">
<div className="text-2xl text-green-500">{probPercent}</div>
<BuyButton
className="justify-end self-end flex-initial btn-md !px-8"
onClick={() => {
setIsBetting(true)
}}
/>
{showChoice ? (
<div className="form-control py-1">
<label className="cursor-pointer label gap-2">
<span className="label-text">Choose this answer</span>
<input
className={clsx('radio', isChosen && '!bg-green-500')}
type="radio"
name="opt"
checked={isChosen}
onChange={onChoose}
value={answer.id}
/>
</label>
</div>
) : (
<BuyButton
className="justify-end self-end flex-initial btn-md !px-8"
onClick={() => {
setIsBetting(true)
}}
/>
)}
</Row>
)}
</Col>
@ -327,3 +375,64 @@ function CreateAnswerInput(props: { contract: Contract<'MULTI'> }) {
</Col>
)
}
function AnswerResolvePanel(props: {
contract: Contract<'MULTI'>
resolveOption: 'CHOOSE' | 'CANCEL' | undefined
setResolveOption: (option: 'CHOOSE' | 'CANCEL' | undefined) => void
answer: string | undefined
clearAnswerChoice: () => void
}) {
const {
contract,
resolveOption,
setResolveOption,
answer,
clearAnswerChoice,
} = props
const resolutionButtonClass =
resolveOption === 'CANCEL'
? 'bg-yellow-400 hover:bg-yellow-500'
: resolveOption === 'CHOOSE' && answer
? 'btn-primary'
: 'btn-disabled'
return (
<Col className="gap-4 p-4 bg-gray-50 rounded">
<div>Resolve your market</div>
<Col className="sm:flex-row sm:items-center gap-2">
<ChooseCancelSelector
className="!flex-row flex-wrap items-center"
selected={resolveOption}
onSelect={setResolveOption}
/>
<Row
className={clsx(
'flex-1 items-center',
resolveOption ? 'justify-between' : 'justify-end'
)}
>
{resolveOption && (
<button
className="btn btn-ghost"
onClick={() => {
setResolveOption(undefined)
clearAnswerChoice()
}}
>
Clear
</button>
)}
<ResolveConfirmationButton
onResolve={() => {}}
isSubmitting={false}
openModelButtonClass={resolutionButtonClass}
submitButtonClass={resolutionButtonClass}
/>
</Row>
</Col>
</Col>
)
}

View File

@ -51,3 +51,36 @@ export function ConfirmationButton(props: {
</>
)
}
export function ResolveConfirmationButton(props: {
onResolve: () => void
isSubmitting: boolean
openModelButtonClass?: string
submitButtonClass?: string
}) {
const { onResolve, isSubmitting, openModelButtonClass, submitButtonClass } =
props
return (
<ConfirmationButton
id="resolution-modal"
openModelBtn={{
className: clsx(
'border-none self-start',
openModelButtonClass,
isSubmitting && 'btn-disabled loading'
),
label: 'Resolve',
}}
cancelBtn={{
label: 'Back',
}}
submitBtn={{
label: 'Resolve',
className: clsx('border-none', submitButtonClass),
}}
onSubmit={onResolve}
>
<p>Are you sure you want to resolve this market?</p>
</ConfirmationButton>
)
}

View File

@ -27,5 +27,5 @@ export function ProbLabel() {
}
export function AnswerNumberLabel(props: { number: string }) {
return <span className="text-blue-400">#{props.number}</span>
return <span className="text-primary">#{props.number}</span>
}

View File

@ -7,7 +7,7 @@ import { Title } from './title'
import { User } from '../lib/firebase/users'
import { YesNoCancelSelector } from './yes-no-selector'
import { Spacer } from './layout/spacer'
import { ConfirmationButton as ConfirmationButton } from './confirmation-button'
import { ResolveConfirmationButton } from './confirmation-button'
import { resolveMarket } from '../lib/firebase/api-call'
import { ProbabilitySelector } from './probability-selector'
import { getProbability } from '../../common/calculate'
@ -114,27 +114,12 @@ export function ResolutionPanel(props: {
{!!error && <div className="text-red-500">{error}</div>}
<ConfirmationButton
id="resolution-modal"
openModelBtn={{
className: clsx(
'border-none self-start mt-2 w-full',
submitButtonClass,
isSubmitting && 'btn-disabled loading'
),
label: 'Resolve',
}}
cancelBtn={{
label: 'Back',
}}
submitBtn={{
label: 'Resolve',
className: submitButtonClass,
}}
onSubmit={resolve}
>
<p>Are you sure you want to resolve this market?</p>
</ConfirmationButton>
<ResolveConfirmationButton
onResolve={resolve}
isSubmitting={isSubmitting}
openModelButtonClass={clsx('w-full mt-2', submitButtonClass)}
submitButtonClass={submitButtonClass}
/>
</Col>
)
}

View File

@ -90,6 +90,37 @@ export function YesNoCancelSelector(props: {
)
}
export function ChooseCancelSelector(props: {
selected: 'CHOOSE' | 'CANCEL' | undefined
onSelect: (selected: 'CHOOSE' | 'CANCEL') => void
className?: string
btnClassName?: string
}) {
const { selected, onSelect, className } = props
const btnClassName = clsx('px-6 flex-1', props.btnClassName)
return (
<Col className={clsx('gap-2', className)}>
<Button
color={selected === 'CHOOSE' ? 'green' : 'gray'}
onClick={() => onSelect('CHOOSE')}
className={clsx('whitespace-nowrap', btnClassName)}
>
Choose an answer
</Button>
<Button
color={selected === 'CANCEL' ? 'yellow' : 'gray'}
onClick={() => onSelect('CANCEL')}
className={clsx(btnClassName, '')}
>
N/A
</Button>
</Col>
)
}
const fundAmounts = [500, 1000, 2500, 10000]
export function FundsSelector(props: {
@ -121,7 +152,7 @@ export function BuyButton(props: { className?: string; onClick?: () => void }) {
const { className, onClick } = props
return (
<Button className={className} onClick={onClick} color="green">
Buy
BUY
</Button>
)
}