Resolve answer UI
This commit is contained in:
parent
fbdc6eacad
commit
0a178a7519
|
@ -14,7 +14,7 @@ import { Avatar } from './avatar'
|
||||||
import { SiteLink } from './site-link'
|
import { SiteLink } from './site-link'
|
||||||
import { DateTimeTooltip } from './datetime-tooltip'
|
import { DateTimeTooltip } from './datetime-tooltip'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { BuyButton } from './yes-no-selector'
|
import { BuyButton, ChooseCancelSelector } from './yes-no-selector'
|
||||||
import { Spacer } from './layout/spacer'
|
import { Spacer } from './layout/spacer'
|
||||||
import {
|
import {
|
||||||
formatMoney,
|
formatMoney,
|
||||||
|
@ -32,6 +32,7 @@ import {
|
||||||
import { firebaseLogin } from '../lib/firebase/users'
|
import { firebaseLogin } from '../lib/firebase/users'
|
||||||
import { Bet } from '../../common/bet'
|
import { Bet } from '../../common/bet'
|
||||||
import { useAnswers } from '../hooks/use-answers'
|
import { useAnswers } from '../hooks/use-answers'
|
||||||
|
import { ResolveConfirmationButton } from './confirmation-button'
|
||||||
|
|
||||||
export function AnswersPanel(props: {
|
export function AnswersPanel(props: {
|
||||||
contract: Contract<'MULTI'>
|
contract: Contract<'MULTI'>
|
||||||
|
@ -45,18 +46,49 @@ export function AnswersPanel(props: {
|
||||||
(answer) => -1 * getOutcomeProbability(contract.totalShares, answer.id)
|
(answer) => -1 * getOutcomeProbability(contract.totalShares, answer.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const user = useUser()
|
||||||
|
|
||||||
|
const [resolveOption, setResolveOption] = useState<
|
||||||
|
'CHOOSE' | 'CANCEL' | undefined
|
||||||
|
>()
|
||||||
|
const [answerChoice, setAnswerChoice] = useState<string | undefined>()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Col className="gap-3">
|
<Col className="gap-3">
|
||||||
{sortedAnswers.map((answer) => (
|
{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} />
|
<CreateAnswerInput contract={contract} />
|
||||||
|
|
||||||
|
{user?.id === contract.creatorId && (
|
||||||
|
<AnswerResolvePanel
|
||||||
|
contract={contract}
|
||||||
|
resolveOption={resolveOption}
|
||||||
|
setResolveOption={setResolveOption}
|
||||||
|
answer={answerChoice}
|
||||||
|
clearAnswerChoice={() => setAnswerChoice(undefined)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function AnswerItem(props: { answer: Answer; contract: Contract<'MULTI'> }) {
|
function AnswerItem(props: {
|
||||||
const { answer, contract } = 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 { username, avatarUrl, name, createdTime, number, text } = answer
|
||||||
|
|
||||||
const createdDate = dayjs(createdTime).format('MMM D')
|
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">
|
<Row className="self-end sm:self-start items-center gap-4">
|
||||||
<div className="text-2xl text-green-500">{probPercent}</div>
|
<div className="text-2xl text-green-500">{probPercent}</div>
|
||||||
<BuyButton
|
{showChoice ? (
|
||||||
className="justify-end self-end flex-initial btn-md !px-8"
|
<div className="form-control py-1">
|
||||||
onClick={() => {
|
<label className="cursor-pointer label gap-2">
|
||||||
setIsBetting(true)
|
<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>
|
</Row>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
@ -327,3 +375,64 @@ function CreateAnswerInput(props: { contract: Contract<'MULTI'> }) {
|
||||||
</Col>
|
</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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -27,5 +27,5 @@ export function ProbLabel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AnswerNumberLabel(props: { number: string }) {
|
export function AnswerNumberLabel(props: { number: string }) {
|
||||||
return <span className="text-blue-400">#{props.number}</span>
|
return <span className="text-primary">#{props.number}</span>
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { Title } from './title'
|
||||||
import { User } from '../lib/firebase/users'
|
import { User } from '../lib/firebase/users'
|
||||||
import { YesNoCancelSelector } from './yes-no-selector'
|
import { YesNoCancelSelector } from './yes-no-selector'
|
||||||
import { Spacer } from './layout/spacer'
|
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 { resolveMarket } from '../lib/firebase/api-call'
|
||||||
import { ProbabilitySelector } from './probability-selector'
|
import { ProbabilitySelector } from './probability-selector'
|
||||||
import { getProbability } from '../../common/calculate'
|
import { getProbability } from '../../common/calculate'
|
||||||
|
@ -114,27 +114,12 @@ export function ResolutionPanel(props: {
|
||||||
|
|
||||||
{!!error && <div className="text-red-500">{error}</div>}
|
{!!error && <div className="text-red-500">{error}</div>}
|
||||||
|
|
||||||
<ConfirmationButton
|
<ResolveConfirmationButton
|
||||||
id="resolution-modal"
|
onResolve={resolve}
|
||||||
openModelBtn={{
|
isSubmitting={isSubmitting}
|
||||||
className: clsx(
|
openModelButtonClass={clsx('w-full mt-2', submitButtonClass)}
|
||||||
'border-none self-start mt-2 w-full',
|
submitButtonClass={submitButtonClass}
|
||||||
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>
|
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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]
|
const fundAmounts = [500, 1000, 2500, 10000]
|
||||||
|
|
||||||
export function FundsSelector(props: {
|
export function FundsSelector(props: {
|
||||||
|
@ -121,7 +152,7 @@ export function BuyButton(props: { className?: string; onClick?: () => void }) {
|
||||||
const { className, onClick } = props
|
const { className, onClick } = props
|
||||||
return (
|
return (
|
||||||
<Button className={className} onClick={onClick} color="green">
|
<Button className={className} onClick={onClick} color="green">
|
||||||
Buy
|
BUY
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user