New create challenge panel
This commit is contained in:
parent
4252157290
commit
903264b9be
|
@ -64,6 +64,8 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
||||||
const contract = anyContract as CPMMBinaryContract
|
const contract = anyContract as CPMMBinaryContract
|
||||||
const shares = (1 / creatorOutcomeProb) * creatorAmount
|
const shares = (1 / creatorOutcomeProb) * creatorAmount
|
||||||
const createdTime = Date.now()
|
const createdTime = Date.now()
|
||||||
|
const probOfYes =
|
||||||
|
creatorOutcome === 'YES' ? creatorOutcomeProb : 1 - creatorOutcomeProb
|
||||||
|
|
||||||
log(
|
log(
|
||||||
'Creating challenge bet for',
|
'Creating challenge bet for',
|
||||||
|
@ -80,12 +82,12 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
||||||
const yourNewBet: CandidateBet = removeUndefinedProps({
|
const yourNewBet: CandidateBet = removeUndefinedProps({
|
||||||
orderAmount: acceptorAmount,
|
orderAmount: acceptorAmount,
|
||||||
amount: acceptorAmount,
|
amount: acceptorAmount,
|
||||||
shares: shares,
|
shares,
|
||||||
isCancelled: false,
|
isCancelled: false,
|
||||||
contractId: contract.id,
|
contractId: contract.id,
|
||||||
outcome: acceptorOutcome,
|
outcome: acceptorOutcome,
|
||||||
probBefore: creatorOutcomeProb,
|
probBefore: probOfYes,
|
||||||
probAfter: creatorOutcomeProb,
|
probAfter: probOfYes,
|
||||||
loanAmount: 0,
|
loanAmount: 0,
|
||||||
createdTime,
|
createdTime,
|
||||||
fees: noFees,
|
fees: noFees,
|
||||||
|
@ -103,12 +105,12 @@ export const acceptchallenge = newEndpoint({}, async (req, auth) => {
|
||||||
const creatorNewBet: CandidateBet = removeUndefinedProps({
|
const creatorNewBet: CandidateBet = removeUndefinedProps({
|
||||||
orderAmount: creatorAmount,
|
orderAmount: creatorAmount,
|
||||||
amount: creatorAmount,
|
amount: creatorAmount,
|
||||||
shares: shares,
|
shares,
|
||||||
isCancelled: false,
|
isCancelled: false,
|
||||||
contractId: contract.id,
|
contractId: contract.id,
|
||||||
outcome: creatorOutcome,
|
outcome: creatorOutcome,
|
||||||
probBefore: creatorOutcomeProb,
|
probBefore: probOfYes,
|
||||||
probAfter: creatorOutcomeProb,
|
probAfter: probOfYes,
|
||||||
loanAmount: 0,
|
loanAmount: 0,
|
||||||
createdTime,
|
createdTime,
|
||||||
fees: noFees,
|
fees: noFees,
|
||||||
|
|
|
@ -15,15 +15,12 @@ function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
|
||||||
const {
|
const {
|
||||||
creatorAmount,
|
creatorAmount,
|
||||||
acceptances,
|
acceptances,
|
||||||
creatorOutcomeProb,
|
acceptorAmount,
|
||||||
creatorOutcome,
|
creatorOutcome,
|
||||||
acceptorOutcome,
|
acceptorOutcome,
|
||||||
} = challenge || {}
|
} = challenge || {}
|
||||||
const { userName, userAvatarUrl } = acceptances?.[0] ?? {}
|
const { userName, userAvatarUrl } = acceptances?.[0] ?? {}
|
||||||
const challengeAmount =
|
|
||||||
creatorOutcomeProb &&
|
|
||||||
creatorAmount &&
|
|
||||||
Math.round(((1 - creatorOutcomeProb) / creatorOutcomeProb) * creatorAmount)
|
|
||||||
const probabilityParam =
|
const probabilityParam =
|
||||||
props.probability === undefined
|
props.probability === undefined
|
||||||
? ''
|
? ''
|
||||||
|
@ -35,7 +32,7 @@ function buildCardUrl(props: OgCardProps, challenge?: Challenge) {
|
||||||
|
|
||||||
const challengeUrlParams = challenge
|
const challengeUrlParams = challenge
|
||||||
? `&creatorAmount=${creatorAmount}&creatorOutcome=${creatorOutcome}` +
|
? `&creatorAmount=${creatorAmount}&creatorOutcome=${creatorOutcome}` +
|
||||||
`&challengerAmount=${challengeAmount}&challengerOutcome=${acceptorOutcome}` +
|
`&challengerAmount=${acceptorAmount}&challengerOutcome=${acceptorOutcome}` +
|
||||||
`&acceptedName=${userName ?? ''}&acceptedAvatarUrl=${userAvatarUrl ?? ''}`
|
`&acceptedName=${userName ?? ''}&acceptedAvatarUrl=${userAvatarUrl ?? ''}`
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { DuplicateIcon } from '@heroicons/react/outline'
|
import {
|
||||||
|
AdjustmentsIcon,
|
||||||
|
CogIcon,
|
||||||
|
DuplicateIcon,
|
||||||
|
PencilIcon,
|
||||||
|
} from '@heroicons/react/outline'
|
||||||
|
|
||||||
import { Col } from '../layout/col'
|
import { Col } from '../layout/col'
|
||||||
import { Row } from '../layout/row'
|
import { Row } from '../layout/row'
|
||||||
|
@ -80,12 +85,11 @@ function CreateChallengeForm(props: {
|
||||||
const [isCreating, setIsCreating] = useState(false)
|
const [isCreating, setIsCreating] = useState(false)
|
||||||
const [finishedCreating, setFinishedCreating] = useState(false)
|
const [finishedCreating, setFinishedCreating] = useState(false)
|
||||||
const [error, setError] = useState<string>('')
|
const [error, setError] = useState<string>('')
|
||||||
|
const [editingAcceptorAmount, setEditingAcceptorAmount] = useState(false)
|
||||||
const defaultExpire = 'week'
|
const defaultExpire = 'week'
|
||||||
|
|
||||||
const defaultMessage = `${user.name} is challenging you to a bet! Do you think ${contract.question}`
|
const defaultMessage = `${user.name} is challenging you to a bet! Do you think ${contract.question}`
|
||||||
|
|
||||||
const prob = Math.round(getOutcomeProbability(contract, 'YES') * 100) / 100 // round to whole percentage
|
|
||||||
|
|
||||||
const [challengeInfo, setChallengeInfo] = useState<challengeInfo>({
|
const [challengeInfo, setChallengeInfo] = useState<challengeInfo>({
|
||||||
expiresTime: dayjs().add(2, defaultExpire).valueOf(),
|
expiresTime: dayjs().add(2, defaultExpire).valueOf(),
|
||||||
outcome: 'YES',
|
outcome: 'YES',
|
||||||
|
@ -97,10 +101,6 @@ function CreateChallengeForm(props: {
|
||||||
setError('')
|
setError('')
|
||||||
}, [challengeInfo])
|
}, [challengeInfo])
|
||||||
|
|
||||||
const p = challengeInfo.outcome === 'YES' ? prob : 1 - prob
|
|
||||||
|
|
||||||
const friendCost = ((1 - p) / p) * challengeInfo.amount
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{!finishedCreating && (
|
{!finishedCreating && (
|
||||||
|
@ -117,7 +117,6 @@ function CreateChallengeForm(props: {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Title className="!mt-2" text="Challenge a friend to bet " />
|
<Title className="!mt-2" text="Challenge a friend to bet " />
|
||||||
{/*<Row className="label ">How much?</Row>*/}
|
|
||||||
<div className="mt-2 flex flex-col flex-wrap gap-x-5 gap-y-2">
|
<div className="mt-2 flex flex-col flex-wrap gap-x-5 gap-y-2">
|
||||||
{/*<div>Question:</div>*/}
|
{/*<div>Question:</div>*/}
|
||||||
{/*<div className="mb-4 italic">{contract.question}</div>*/}
|
{/*<div className="mb-4 italic">{contract.question}</div>*/}
|
||||||
|
@ -136,7 +135,13 @@ function CreateChallengeForm(props: {
|
||||||
value={challengeInfo.amount}
|
value={challengeInfo.amount}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
setChallengeInfo((m: challengeInfo) => {
|
setChallengeInfo((m: challengeInfo) => {
|
||||||
return { ...m, amount: parseInt(e.target.value) }
|
return {
|
||||||
|
...m,
|
||||||
|
amount: parseInt(e.target.value),
|
||||||
|
acceptorAmount: editingAcceptorAmount
|
||||||
|
? m.acceptorAmount
|
||||||
|
: parseInt(e.target.value),
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -162,11 +167,55 @@ function CreateChallengeForm(props: {
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Spacer h={2} />
|
<Spacer h={2} />
|
||||||
<div>They will bet:</div>
|
<Row className={'items-center'}>They will bet:</Row>
|
||||||
<div>
|
<Row className={'items-center gap-2'}>
|
||||||
<span className="bold">{formatMoney(friendCost)}</span> on{' '}
|
<div className={'ml-1 min-w-[90px]'}>
|
||||||
{challengeInfo.outcome === 'YES' ? <NoLabel /> : <YesLabel />}
|
{editingAcceptorAmount ? (
|
||||||
</div>
|
<Col>
|
||||||
|
<div className="relative">
|
||||||
|
<span className="absolute mx-3 mt-3.5 text-sm text-gray-400">
|
||||||
|
M$
|
||||||
|
</span>
|
||||||
|
<input
|
||||||
|
className="input input-bordered w-40 pl-10"
|
||||||
|
type="number"
|
||||||
|
min={1}
|
||||||
|
value={challengeInfo.acceptorAmount}
|
||||||
|
onChange={(e) =>
|
||||||
|
setChallengeInfo((m: challengeInfo) => {
|
||||||
|
return {
|
||||||
|
...m,
|
||||||
|
acceptorAmount: parseInt(e.target.value),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Col>
|
||||||
|
) : (
|
||||||
|
<span className="font-bold">
|
||||||
|
{formatMoney(challengeInfo.acceptorAmount)}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Row className={'items-center gap-3'}>
|
||||||
|
on
|
||||||
|
{challengeInfo.outcome === 'YES' ? <NoLabel /> : <YesLabel />}
|
||||||
|
{!editingAcceptorAmount && (
|
||||||
|
<Button
|
||||||
|
color={'gray'}
|
||||||
|
onClick={() =>
|
||||||
|
setEditingAcceptorAmount(!editingAcceptorAmount)
|
||||||
|
}
|
||||||
|
className={
|
||||||
|
'flex flex-row gap-2 !bg-transparent py-1 hover:!bg-gray-100'
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</Row>
|
||||||
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
<Row className={'justify-end'}>
|
<Row className={'justify-end'}>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
@ -52,21 +52,19 @@ export async function createChallenge(data: {
|
||||||
if (creatorAmount <= 0 || isNaN(creatorAmount) || !isFinite(creatorAmount))
|
if (creatorAmount <= 0 || isNaN(creatorAmount) || !isFinite(creatorAmount))
|
||||||
return null
|
return null
|
||||||
|
|
||||||
const prob = 1 / (acceptorAmount / creatorAmount + 1)
|
|
||||||
|
|
||||||
const challenge: Challenge = {
|
const challenge: Challenge = {
|
||||||
slug,
|
slug,
|
||||||
creatorId: creator.id,
|
creatorId: creator.id,
|
||||||
creatorUsername: creator.username,
|
creatorUsername: creator.username,
|
||||||
creatorName: creator.name,
|
creatorName: creator.name,
|
||||||
creatorAvatarUrl: creator.avatarUrl,
|
creatorAvatarUrl: creator.avatarUrl,
|
||||||
creatorAmount: creatorAmount,
|
creatorAmount,
|
||||||
|
creatorOutcome: outcome.toString(),
|
||||||
|
creatorOutcomeProb: creatorAmount / (creatorAmount + acceptorAmount),
|
||||||
|
acceptorOutcome: outcome === 'YES' ? 'NO' : 'YES',
|
||||||
|
acceptorAmount,
|
||||||
contractSlug: contract.slug,
|
contractSlug: contract.slug,
|
||||||
contractId: contract.id,
|
contractId: contract.id,
|
||||||
creatorOutcome: outcome.toString(),
|
|
||||||
acceptorOutcome: outcome === 'YES' ? 'NO' : 'YES',
|
|
||||||
creatorOutcomeProb: prob,
|
|
||||||
acceptorAmount,
|
|
||||||
createdTime: Date.now(),
|
createdTime: Date.now(),
|
||||||
expiresTime,
|
expiresTime,
|
||||||
maxUses: 1,
|
maxUses: 1,
|
||||||
|
|
|
@ -140,7 +140,6 @@ function ClosedChallengeContent(props: {
|
||||||
acceptances,
|
acceptances,
|
||||||
creatorAmount,
|
creatorAmount,
|
||||||
creatorOutcome,
|
creatorOutcome,
|
||||||
creatorOutcomeProb,
|
|
||||||
acceptorOutcome,
|
acceptorOutcome,
|
||||||
acceptorAmount,
|
acceptorAmount,
|
||||||
} = challenge
|
} = challenge
|
||||||
|
@ -156,7 +155,6 @@ function ClosedChallengeContent(props: {
|
||||||
}, [acceptances])
|
}, [acceptances])
|
||||||
|
|
||||||
const creatorWon = resolution === creatorOutcome
|
const creatorWon = resolution === creatorOutcome
|
||||||
const amountWon = creatorWon ? acceptorAmount : creatorAmount
|
|
||||||
|
|
||||||
const href = `https://${DOMAIN}${contractPath(contract)}`
|
const href = `https://${DOMAIN}${contractPath(contract)}`
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user