This commit is contained in:
ingawei 2022-10-04 01:07:34 -07:00
parent e39f681c51
commit 04a7085b34
3 changed files with 68 additions and 36 deletions

View File

@ -25,6 +25,8 @@ import { UserLink } from 'web/components/user-link'
import { Button } from 'web/components/button' import { Button } from 'web/components/button'
import { useAdmin } from 'web/hooks/use-admin' import { useAdmin } from 'web/hooks/use-admin'
import { needsAdminToResolve } from 'web/pages/[username]/[contractSlug]' import { needsAdminToResolve } from 'web/pages/[username]/[contractSlug]'
import { CATEGORY_COLORS } from '../charts/contract/choice'
import { getChartAnswers } from '../charts/contract/choice'
export function AnswersPanel(props: { export function AnswersPanel(props: {
contract: FreeResponseContract | MultipleChoiceContract contract: FreeResponseContract | MultipleChoiceContract
@ -38,6 +40,7 @@ export function AnswersPanel(props: {
const answers = (useAnswers(contract.id) ?? contract.answers).filter( const answers = (useAnswers(contract.id) ?? contract.answers).filter(
(a) => a.number != 0 || contract.outcomeType === 'MULTIPLE_CHOICE' (a) => a.number != 0 || contract.outcomeType === 'MULTIPLE_CHOICE'
) )
const hasZeroBetAnswers = answers.some((answer) => totalBets[answer.id] < 1) const hasZeroBetAnswers = answers.some((answer) => totalBets[answer.id] < 1)
const [winningAnswers, losingAnswers] = partition( const [winningAnswers, losingAnswers] = partition(
@ -104,6 +107,11 @@ export function AnswersPanel(props: {
? 'checkbox' ? 'checkbox'
: undefined : undefined
const colorSortedAnswer = getChartAnswers(
contract,
CATEGORY_COLORS.length
).map((value, index) => value.text)
return ( return (
<Col className="gap-3"> <Col className="gap-3">
{(resolveOption || resolution) && {(resolveOption || resolution) &&
@ -128,7 +136,12 @@ export function AnswersPanel(props: {
)} )}
> >
{answerItems.map((item) => ( {answerItems.map((item) => (
<OpenAnswer key={item.id} answer={item} contract={contract} /> <OpenAnswer
key={item.id}
answer={item}
contract={contract}
colorIndex={colorSortedAnswer.indexOf(item.text)}
/>
))} ))}
{hasZeroBetAnswers && !showAllAnswers && ( {hasZeroBetAnswers && !showAllAnswers && (
<Button <Button
@ -174,12 +187,15 @@ export function AnswersPanel(props: {
function OpenAnswer(props: { function OpenAnswer(props: {
contract: FreeResponseContract | MultipleChoiceContract contract: FreeResponseContract | MultipleChoiceContract
answer: Answer answer: Answer
colorIndex: number | undefined
}) { }) {
const { answer, contract } = props const { answer, contract, colorIndex } = props
const { username, avatarUrl, name, text } = answer const { username, avatarUrl, name, text } = answer
const prob = getDpmOutcomeProbability(contract.totalShares, answer.id) const prob = getDpmOutcomeProbability(contract.totalShares, answer.id)
const probPercent = formatPercent(prob) const probPercent = formatPercent(prob)
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const color =
colorIndex != undefined ? CATEGORY_COLORS[colorIndex] : '#B1B1C7'
return ( return (
<> <>
@ -193,46 +209,50 @@ function OpenAnswer(props: {
/> />
</Modal> </Modal>
<Row className="justify-between"> <Col
<Col className="w-4/5"> className="hover:bg-greyscale-1.5 w-full rounded-lg py-1 px-4"
<Row> onClick={() => setOpen(true)}
<Avatar >
className="my-auto mr-2 h-5 w-5" <Row className="-mb-1 pr-[60px]">
username={username} <Avatar
avatarUrl={avatarUrl} className="mt-1 mr-2 h-4 w-4"
/> username={username}
<Linkify avatarUrl={avatarUrl}
className="text-md whitespace-pre-line md:text-lg" />
text={text} <Linkify
/> className="text-md whitespace-pre-line md:text-lg"
</Row> text={text}
<div className="relative h-3"> />
<hr className="bg-greyscale-2 absolute z-0 h-3 w-full rounded-full" /> </Row>
<hr <Row className="gap-2">
className="absolute z-20 h-3 rounded-l-full bg-green-600 text-green-600" {/* <div className="relative h-3 w-[calc(100%-60px)]"> */}
style={{ width: `${100 * Math.max(prob, 0.01)}%` }} {/* <hr className="border-greyscale-2 absolute z-0 mt-2 h-3 w-full rounded-full border bg-white" /> */}
/> <hr
</div> color={color}
</Col> className="mt-1 h-3 w-full rounded-l-full border-none"
<Row className="align-items items-center justify-end gap-4"> style={{ width: `${100 * Math.max(prob, 0.01)}%` }}
<span />
<div
className={clsx( className={clsx(
'text-2xl', 'md:text-md my-auto text-sm'
tradingAllowed(contract) ? 'text-greyscale-7' : 'text-gray-500' // tradingAllowed(contract) ? 'text-greyscale-7' : 'text-gray-500'
)} )}
color={color}
> >
{probPercent} {probPercent}
</span> </div>
</Row>
</Col>
{/* <Row className="align-items justify-end gap-4">
<Button <Button
className={clsx(tradingAllowed(contract) ? '' : '!hidden')} className={clsx(tradingAllowed(contract) ? '' : '!hidden')}
color="indigo" color="gray"
size="xs" size="xs"
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
> >
Buy Buy
</Button> </Button>
</Row> </Row> */}
</Row>
</> </>
) )
} }

View File

@ -22,7 +22,7 @@ import { Row } from 'web/components/layout/row'
import { Avatar } from 'web/components/avatar' import { Avatar } from 'web/components/avatar'
// thanks to https://observablehq.com/@jonhelfman/optimal-orders-for-choosing-categorical-colors // thanks to https://observablehq.com/@jonhelfman/optimal-orders-for-choosing-categorical-colors
const CATEGORY_COLORS = [ export const CATEGORY_COLORS = [
'#00b8dd', '#00b8dd',
'#eecafe', '#eecafe',
'#874c62', '#874c62',
@ -142,6 +142,16 @@ const Legend = (props: { className?: string; items: LegendItem[] }) => {
) )
} }
export function getChartAnswers(
contract: FreeResponseContract | MultipleChoiceContract,
length: number
) {
return useMemo(
() => getTrackedAnswers(contract, CATEGORY_COLORS.length),
[contract]
)
}
export const ChoiceContractChart = (props: { export const ChoiceContractChart = (props: {
contract: FreeResponseContract | MultipleChoiceContract contract: FreeResponseContract | MultipleChoiceContract
bets: Bet[] bets: Bet[]
@ -151,10 +161,11 @@ export const ChoiceContractChart = (props: {
}) => { }) => {
const { contract, bets, width, height, onMouseOver } = props const { contract, bets, width, height, onMouseOver } = props
const [start, end] = getDateRange(contract) const [start, end] = getDateRange(contract)
const answers = useMemo( // const answers = useMemo(
() => getTrackedAnswers(contract, CATEGORY_COLORS.length), // () => getTrackedAnswers(contract, CATEGORY_COLORS.length),
[contract] // [contract]
) // )
const answers = getChartAnswers(contract, CATEGORY_COLORS.length)
const betPoints = useMemo(() => getBetPoints(answers, bets), [answers, bets]) const betPoints = useMemo(() => getBetPoints(answers, bets), [answers, bets])
const data = useMemo( const data = useMemo(
() => [ () => [

View File

@ -18,6 +18,7 @@ module.exports = {
colors: { colors: {
'red-25': '#FDF7F6', 'red-25': '#FDF7F6',
'greyscale-1': '#FBFBFF', 'greyscale-1': '#FBFBFF',
'greyscale-1.5': '#F4F4FB',
'greyscale-2': '#E7E7F4', 'greyscale-2': '#E7E7F4',
'greyscale-3': '#D8D8EB', 'greyscale-3': '#D8D8EB',
'greyscale-4': '#B1B1C7', 'greyscale-4': '#B1B1C7',