manifold/web/components/answers/answer-resolve-panel.tsx

152 lines
4.5 KiB
TypeScript
Raw Normal View History

2022-02-20 22:25:58 +00:00
import clsx from 'clsx'
import { sum } from 'lodash'
import { useEffect, useState } from 'react'
2022-02-20 22:25:58 +00:00
import { FreeResponseContract, MultipleChoiceContract } from 'common/contract'
2022-02-20 22:25:58 +00:00
import { Col } from '../layout/col'
import { APIError, resolveMarket } from 'web/lib/firebase/api'
2022-02-20 22:25:58 +00:00
import { Row } from '../layout/row'
import { ChooseCancelSelector } from '../yes-no-selector'
import { ResolveConfirmationButton } from '../confirmation-button'
import { removeUndefinedProps } from 'common/util/object'
import { BETTOR, PAST_BETS } from 'common/user'
2022-02-20 22:25:58 +00:00
export function AnswerResolvePanel(props: {
isAdmin: boolean
isCreator: boolean
contract: FreeResponseContract | MultipleChoiceContract
2022-02-20 22:25:58 +00:00
resolveOption: 'CHOOSE' | 'CHOOSE_MULTIPLE' | 'CANCEL' | undefined
setResolveOption: (
option: 'CHOOSE' | 'CHOOSE_MULTIPLE' | 'CANCEL' | undefined
) => void
chosenAnswers: { [answerId: string]: number }
}) {
const {
contract,
resolveOption,
setResolveOption,
chosenAnswers,
isAdmin,
isCreator,
} = props
2022-02-20 22:25:58 +00:00
const answers = Object.keys(chosenAnswers)
const [isSubmitting, setIsSubmitting] = useState(false)
const [error, setError] = useState<string | undefined>(undefined)
const [warning, setWarning] = useState<string | undefined>(undefined)
useEffect(() => {
if (resolveOption === 'CANCEL') {
setWarning(
`All ${PAST_BETS} will be returned. Unique ${BETTOR} bonuses will be
withdrawn from your account.`
)
} else {
setWarning(undefined)
}
}, [resolveOption])
2022-02-20 22:25:58 +00:00
const onResolve = async () => {
if (resolveOption === 'CHOOSE' && answers.length !== 1) return
if (resolveOption === 'CHOOSE_MULTIPLE' && answers.length < 2) return
setIsSubmitting(true)
const totalProb = sum(Object.values(chosenAnswers))
const resolutions = Object.entries(chosenAnswers).map(([i, p]) => {
return { answer: parseInt(i), pct: (100 * p) / totalProb }
})
2022-02-20 22:25:58 +00:00
const resolutionProps = removeUndefinedProps({
outcome:
resolveOption === 'CHOOSE'
? parseInt(answers[0])
2022-02-20 22:25:58 +00:00
: resolveOption === 'CHOOSE_MULTIPLE'
? 'MKT'
: 'CANCEL',
resolutions:
resolveOption === 'CHOOSE_MULTIPLE' ? resolutions : undefined,
2022-02-20 22:25:58 +00:00
contractId: contract.id,
})
try {
const result = await resolveMarket(resolutionProps)
console.log('resolved', resolutionProps, 'result:', result)
} catch (e) {
if (e instanceof APIError) {
setError(e.toString())
} else {
console.error(e)
setError('Error resolving market')
}
2022-02-20 22:25:58 +00:00
}
2022-02-20 22:25:58 +00:00
setResolveOption(undefined)
setIsSubmitting(false)
}
return (
<Col className="gap-4 rounded">
<Row className="justify-between">
<div>Resolve your market</div>
{isAdmin && !isCreator && (
<span className="rounded bg-red-200 p-1 text-xs text-red-600">
ADMIN
</span>
)}
</Row>
<Col className="gap-4 sm:flex-row sm:items-center">
2022-02-20 22:25:58 +00:00
<ChooseCancelSelector
className="sm:!flex-row sm: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)
}}
>
Clear
</button>
)}
2022-02-20 22:25:58 +00:00
<ResolveConfirmationButton
color={
resolveOption === 'CANCEL'
? 'yellow'
: resolveOption === 'CHOOSE' && answers.length
? 'green'
: resolveOption === 'CHOOSE_MULTIPLE' &&
answers.length > 1 &&
answers.every((answer) => chosenAnswers[answer] > 0)
? 'blue'
: 'indigo'
}
disabled={
!resolveOption ||
(resolveOption === 'CHOOSE' && !answers.length) ||
(resolveOption === 'CHOOSE_MULTIPLE' &&
(!(answers.length > 1) ||
!answers.every((answer) => chosenAnswers[answer] > 0)))
}
2022-02-20 22:25:58 +00:00
onResolve={onResolve}
isSubmitting={isSubmitting}
/>
</Row>
</Col>
{!!error && <div className="text-red-500">{error}</div>}
{!!warning && <div className="text-warning">{warning}</div>}
2022-02-20 22:25:58 +00:00
</Col>
)
}