Show challenge on desktop, simplify modal
This commit is contained in:
parent
fecf976ab9
commit
8922b370cc
|
@ -18,7 +18,6 @@ import { NoLabel, YesLabel } from '../outcome-label'
|
||||||
import { QRCode } from '../qr-code'
|
import { QRCode } from '../qr-code'
|
||||||
import { copyToClipboard } from 'web/lib/util/copy'
|
import { copyToClipboard } from 'web/lib/util/copy'
|
||||||
import { AmountInput } from '../amount-input'
|
import { AmountInput } from '../amount-input'
|
||||||
import { getProbability } from 'common/calculate'
|
|
||||||
import { createMarket } from 'web/lib/firebase/api'
|
import { createMarket } from 'web/lib/firebase/api'
|
||||||
import { removeUndefinedProps } from 'common/util/object'
|
import { removeUndefinedProps } from 'common/util/object'
|
||||||
import { FIXED_ANTE } from 'common/economy'
|
import { FIXED_ANTE } from 'common/economy'
|
||||||
|
@ -26,6 +25,7 @@ import Textarea from 'react-expanding-textarea'
|
||||||
import { useTextEditor } from 'web/components/editor'
|
import { useTextEditor } from 'web/components/editor'
|
||||||
import { LoadingIndicator } from 'web/components/loading-indicator'
|
import { LoadingIndicator } from 'web/components/loading-indicator'
|
||||||
import { track } from 'web/lib/service/analytics'
|
import { track } from 'web/lib/service/analytics'
|
||||||
|
import { useWindowSize } from 'web/hooks/use-window-size'
|
||||||
|
|
||||||
type challengeInfo = {
|
type challengeInfo = {
|
||||||
amount: number
|
amount: number
|
||||||
|
@ -110,8 +110,9 @@ 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 { width } = useWindowSize()
|
||||||
|
const isMobile = (width ?? 0) < 768
|
||||||
|
|
||||||
const [challengeInfo, setChallengeInfo] = useState<challengeInfo>({
|
const [challengeInfo, setChallengeInfo] = useState<challengeInfo>({
|
||||||
expiresTime: dayjs().add(2, defaultExpire).valueOf(),
|
expiresTime: dayjs().add(2, defaultExpire).valueOf(),
|
||||||
|
@ -147,7 +148,7 @@ function CreateChallengeForm(props: {
|
||||||
setFinishedCreating(true)
|
setFinishedCreating(true)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Title className="!mt-2" text="Challenge bet " />
|
<Title className="!mt-2 hidden sm:block" text="Challenge bet " />
|
||||||
|
|
||||||
<div className="mb-8">
|
<div className="mb-8">
|
||||||
Challenge a friend to bet on{' '}
|
Challenge a friend to bet on{' '}
|
||||||
|
@ -157,7 +158,7 @@ function CreateChallengeForm(props: {
|
||||||
<Textarea
|
<Textarea
|
||||||
placeholder="e.g. Will a Democrat be the next president?"
|
placeholder="e.g. Will a Democrat be the next president?"
|
||||||
className="input input-bordered mt-1 w-full resize-none"
|
className="input input-bordered mt-1 w-full resize-none"
|
||||||
autoFocus={true}
|
autoFocus={!isMobile}
|
||||||
maxLength={MAX_QUESTION_LENGTH}
|
maxLength={MAX_QUESTION_LENGTH}
|
||||||
value={challengeInfo.question}
|
value={challengeInfo.question}
|
||||||
onChange={(e) =>
|
onChange={(e) =>
|
||||||
|
@ -170,7 +171,8 @@ function CreateChallengeForm(props: {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-2 flex flex-col flex-wrap justify-center gap-x-5 gap-y-2">
|
<Col className="mt-2 flex-wrap justify-center gap-x-5 gap-y-0 sm:gap-y-2">
|
||||||
|
<Col>
|
||||||
<div>You'll bet:</div>
|
<div>You'll bet:</div>
|
||||||
<Row
|
<Row
|
||||||
className={
|
className={
|
||||||
|
@ -184,9 +186,7 @@ function CreateChallengeForm(props: {
|
||||||
return {
|
return {
|
||||||
...m,
|
...m,
|
||||||
amount: newAmount ?? 0,
|
amount: newAmount ?? 0,
|
||||||
acceptorAmount: editingAcceptorAmount
|
acceptorAmount: newAmount ?? 0,
|
||||||
? m.acceptorAmount
|
|
||||||
: newAmount ?? 0,
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -197,7 +197,7 @@ function CreateChallengeForm(props: {
|
||||||
<span className={''}>on</span>
|
<span className={''}>on</span>
|
||||||
{challengeInfo.outcome === 'YES' ? <YesLabel /> : <NoLabel />}
|
{challengeInfo.outcome === 'YES' ? <YesLabel /> : <NoLabel />}
|
||||||
</Row>
|
</Row>
|
||||||
<Row className={'mt-3 max-w-xs justify-end'}>
|
<Row className={'max-w-xs justify-end'}>
|
||||||
<Button
|
<Button
|
||||||
color={'gray-white'}
|
color={'gray-white'}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
@ -212,47 +212,18 @@ function CreateChallengeForm(props: {
|
||||||
<SwitchVerticalIcon className={'h-6 w-6'} />
|
<SwitchVerticalIcon className={'h-6 w-6'} />
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
|
</Col>
|
||||||
<Row className={'items-center'}>If they bet:</Row>
|
<Row className={'items-center'}>If they bet:</Row>
|
||||||
<Row className={'max-w-xs items-center justify-between gap-4 pr-3'}>
|
<Row className={'max-w-xs items-center justify-between gap-4 pr-3'}>
|
||||||
<div className={'w-32 sm:mr-1'}>
|
<div className={'mt-1 w-32 sm:mr-1'}>
|
||||||
<AmountInput
|
<span className={'ml-2 font-bold'}>
|
||||||
amount={challengeInfo.acceptorAmount || undefined}
|
{formatMoney(challengeInfo.acceptorAmount)}
|
||||||
onChange={(newAmount) => {
|
</span>
|
||||||
setEditingAcceptorAmount(true)
|
|
||||||
|
|
||||||
setChallengeInfo((m: challengeInfo) => {
|
|
||||||
return {
|
|
||||||
...m,
|
|
||||||
acceptorAmount: newAmount ?? 0,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
error={undefined}
|
|
||||||
label={'M$'}
|
|
||||||
inputClassName="w-24"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<span>on</span>
|
<span>on</span>
|
||||||
{challengeInfo.outcome === 'YES' ? <NoLabel /> : <YesLabel />}
|
{challengeInfo.outcome === 'YES' ? <NoLabel /> : <YesLabel />}
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</Col>
|
||||||
{contract && (
|
|
||||||
<Button
|
|
||||||
size="2xs"
|
|
||||||
color="gray"
|
|
||||||
onClick={() => {
|
|
||||||
setEditingAcceptorAmount(true)
|
|
||||||
|
|
||||||
const p = getProbability(contract)
|
|
||||||
const prob = challengeInfo.outcome === 'YES' ? p : 1 - p
|
|
||||||
const { amount } = challengeInfo
|
|
||||||
const acceptorAmount = Math.round(amount / prob - amount)
|
|
||||||
setChallengeInfo({ ...challengeInfo, acceptorAmount })
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Use market odds
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
If the challenge is accepted, whoever is right will earn{' '}
|
If the challenge is accepted, whoever is right will earn{' '}
|
||||||
<span className="font-semibold">
|
<span className="font-semibold">
|
||||||
|
|
|
@ -11,14 +11,21 @@ import { FollowMarketButton } from 'web/components/follow-market-button'
|
||||||
import { LikeMarketButton } from 'web/components/contract/like-market-button'
|
import { LikeMarketButton } from 'web/components/contract/like-market-button'
|
||||||
import { ContractInfoDialog } from 'web/components/contract/contract-info-dialog'
|
import { ContractInfoDialog } from 'web/components/contract/contract-info-dialog'
|
||||||
import { Col } from 'web/components/layout/col'
|
import { Col } from 'web/components/layout/col'
|
||||||
|
import { withTracking } from 'web/lib/service/analytics'
|
||||||
|
import { CreateChallengeModal } from 'web/components/challenges/create-challenge-modal'
|
||||||
|
import { CHALLENGES_ENABLED } from 'common/lib/challenge'
|
||||||
|
|
||||||
export function ExtraContractActionsRow(props: {
|
export function ExtraContractActionsRow(props: {
|
||||||
contract: Contract
|
contract: Contract
|
||||||
user: User | undefined | null
|
user: User | undefined | null
|
||||||
}) {
|
}) {
|
||||||
const { user, contract } = props
|
const { user, contract } = props
|
||||||
|
const { outcomeType, resolution } = contract
|
||||||
const [isShareOpen, setShareOpen] = useState(false)
|
const [isShareOpen, setShareOpen] = useState(false)
|
||||||
|
const [openCreateChallengeModal, setOpenCreateChallengeModal] =
|
||||||
|
useState(false)
|
||||||
|
const showChallenge =
|
||||||
|
user && outcomeType === 'BINARY' && !resolution && CHALLENGES_ENABLED
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className={'mt-0.5 justify-around sm:mt-2 lg:justify-start'}>
|
<Row className={'mt-0.5 justify-around sm:mt-2 lg:justify-start'}>
|
||||||
|
@ -45,6 +52,25 @@ export function ExtraContractActionsRow(props: {
|
||||||
user={user}
|
user={user}
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
|
{showChallenge && (
|
||||||
|
<Button
|
||||||
|
size="lg"
|
||||||
|
color="gray-white"
|
||||||
|
className={'flex hidden max-w-xs self-center sm:inline-block'}
|
||||||
|
onClick={withTracking(
|
||||||
|
() => setOpenCreateChallengeModal(true),
|
||||||
|
'click challenge button'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span>⚔️ Challenge</span>
|
||||||
|
<CreateChallengeModal
|
||||||
|
isOpen={openCreateChallengeModal}
|
||||||
|
setOpen={setOpenCreateChallengeModal}
|
||||||
|
user={user}
|
||||||
|
contract={contract}
|
||||||
|
/>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
<FollowMarketButton contract={contract} user={user} />
|
<FollowMarketButton contract={contract} user={user} />
|
||||||
{user?.id !== contract.creatorId && (
|
{user?.id !== contract.creatorId && (
|
||||||
|
|
|
@ -45,7 +45,7 @@ export function ShareModal(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal open={isOpen} setOpen={setOpen} size="md">
|
<Modal open={isOpen} setOpen={setOpen} size="md">
|
||||||
<Col className="gap-4 rounded bg-white p-4">
|
<Col className="gap-2.5 rounded bg-white p-4 sm:gap-4">
|
||||||
<Title className="!mt-0 !mb-2" text="Share this market" />
|
<Title className="!mt-0 !mb-2" text="Share this market" />
|
||||||
<p>
|
<p>
|
||||||
Earn{' '}
|
Earn{' '}
|
||||||
|
@ -57,7 +57,7 @@ export function ShareModal(props: {
|
||||||
<Button
|
<Button
|
||||||
size="2xl"
|
size="2xl"
|
||||||
color="gradient"
|
color="gradient"
|
||||||
className={'mb-2 flex max-w-xs self-center'}
|
className={'flex max-w-xs self-center'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
copyToClipboard(shareUrl)
|
copyToClipboard(shareUrl)
|
||||||
toast.success('Link copied!', {
|
toast.success('Link copied!', {
|
||||||
|
@ -68,17 +68,18 @@ export function ShareModal(props: {
|
||||||
>
|
>
|
||||||
{linkIcon} Copy link
|
{linkIcon} Copy link
|
||||||
</Button>
|
</Button>
|
||||||
|
<Row className={'justify-center'}>or</Row>
|
||||||
{showChallenge && (
|
{showChallenge && (
|
||||||
<Button
|
<Button
|
||||||
size="lg"
|
size="2xl"
|
||||||
color="gray-white"
|
color="gradient"
|
||||||
className={'mb-2 flex max-w-xs self-center'}
|
className={'mb-2 flex max-w-xs self-center'}
|
||||||
onClick={withTracking(
|
onClick={withTracking(
|
||||||
() => setOpenCreateChallengeModal(true),
|
() => setOpenCreateChallengeModal(true),
|
||||||
'click challenge button'
|
'click challenge button'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span>⚔️ Challenge a friend</span>
|
<span>⚔️ Challenge</span>
|
||||||
<CreateChallengeModal
|
<CreateChallengeModal
|
||||||
isOpen={openCreateChallengeModal}
|
isOpen={openCreateChallengeModal}
|
||||||
setOpen={(open) => {
|
setOpen={(open) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user