Add UI for resolution panel!
This commit is contained in:
parent
7e08a68799
commit
0d56ad603e
81
web/components/resolution-panel.tsx
Normal file
81
web/components/resolution-panel.tsx
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
|
import { Contract } from '../lib/firebase/contracts'
|
||||||
|
import { Col } from './layout/col'
|
||||||
|
import { Title } from './title'
|
||||||
|
import { User } from '../lib/firebase/users'
|
||||||
|
import { YesNoCancelSelector } from './yes-no-selector'
|
||||||
|
import { Spacer } from './layout/spacer'
|
||||||
|
|
||||||
|
export function ResolutionPanel(props: {
|
||||||
|
creator: User
|
||||||
|
contract: Contract
|
||||||
|
className?: string
|
||||||
|
}) {
|
||||||
|
const { creator, contract, className } = props
|
||||||
|
|
||||||
|
const [outcome, setOutcome] = useState<'YES' | 'NO' | 'CANCEL' | undefined>()
|
||||||
|
|
||||||
|
const resolveDisabled = false
|
||||||
|
|
||||||
|
function resolve() {}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Col
|
||||||
|
className={clsx(
|
||||||
|
'bg-gray-200 shadow-xl px-8 py-6 rounded-md w-full md:w-auto',
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Title className="mt-0" text="Your market" />
|
||||||
|
|
||||||
|
<div className="pt-2 pb-1 text-sm text-gray-500">Resolve outcome</div>
|
||||||
|
<YesNoCancelSelector
|
||||||
|
className="p-2"
|
||||||
|
selected={outcome}
|
||||||
|
onSelect={setOutcome}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Spacer h={3} />
|
||||||
|
|
||||||
|
<div className="text-gray-500 text-sm">
|
||||||
|
{outcome === 'YES' ? (
|
||||||
|
<>
|
||||||
|
Winnings will be paid out to Yes bettors. You earn 1% of the No
|
||||||
|
bets.
|
||||||
|
</>
|
||||||
|
) : outcome === 'NO' ? (
|
||||||
|
<>
|
||||||
|
Winnings will be paid out to No bettors. You earn 1% of the Yes
|
||||||
|
bets.
|
||||||
|
</>
|
||||||
|
) : outcome === 'CANCEL' ? (
|
||||||
|
<>All bets will be returned with no fees.</>
|
||||||
|
) : (
|
||||||
|
<>Resolving this market will immediately pay out bettors.</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Spacer h={3} />
|
||||||
|
|
||||||
|
<button
|
||||||
|
className={clsx(
|
||||||
|
'btn border-none self-start m-2',
|
||||||
|
resolveDisabled
|
||||||
|
? 'btn-disabled'
|
||||||
|
: outcome === 'YES'
|
||||||
|
? 'btn-primary'
|
||||||
|
: outcome === 'NO'
|
||||||
|
? 'bg-red-400 hover:bg-red-500'
|
||||||
|
: outcome === 'CANCEL'
|
||||||
|
? 'bg-yellow-400 hover:bg-yellow-500'
|
||||||
|
: 'btn-disabled'
|
||||||
|
)}
|
||||||
|
onClick={resolveDisabled ? undefined : resolve}
|
||||||
|
>
|
||||||
|
Resolve
|
||||||
|
</button>
|
||||||
|
</Col>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,32 +1,64 @@
|
||||||
|
import clsx from 'clsx'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Row } from './layout/row'
|
import { Row } from './layout/row'
|
||||||
|
|
||||||
export function YesNoSelector(props: {
|
export function YesNoSelector(props: {
|
||||||
selected: 'YES' | 'NO'
|
selected: 'YES' | 'NO'
|
||||||
onSelect: (selected: 'YES' | 'NO') => void
|
onSelect: (selected: 'YES' | 'NO') => void
|
||||||
yesLabel?: string
|
|
||||||
noLabel?: string
|
|
||||||
className?: string
|
className?: string
|
||||||
}) {
|
}) {
|
||||||
const { selected, onSelect, yesLabel, noLabel, className } = props
|
const { selected, onSelect, className } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row className={className}>
|
<Row className={clsx('space-x-3', className)}>
|
||||||
<Button
|
<Button
|
||||||
color={selected === 'YES' ? 'green' : 'deemphasized'}
|
color={selected === 'YES' ? 'green' : 'gray'}
|
||||||
hideFocusRing
|
|
||||||
onClick={() => onSelect('YES')}
|
onClick={() => onSelect('YES')}
|
||||||
>
|
>
|
||||||
{yesLabel ?? 'Yes'}
|
Yes
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
color={selected === 'NO' ? 'red' : 'deemphasized'}
|
color={selected === 'NO' ? 'red' : 'gray'}
|
||||||
hideFocusRing
|
|
||||||
onClick={() => onSelect('NO')}
|
onClick={() => onSelect('NO')}
|
||||||
className="ml-3"
|
|
||||||
>
|
>
|
||||||
{noLabel ?? 'No'}
|
No
|
||||||
|
</Button>
|
||||||
|
</Row>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function YesNoCancelSelector(props: {
|
||||||
|
selected: 'YES' | 'NO' | 'CANCEL' | undefined
|
||||||
|
onSelect: (selected: 'YES' | 'NO' | 'CANCEL') => void
|
||||||
|
className?: string
|
||||||
|
}) {
|
||||||
|
const { selected, onSelect, className } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row className={clsx('space-x-3', className)}>
|
||||||
|
<Button
|
||||||
|
color={selected === 'YES' ? 'green' : 'gray'}
|
||||||
|
onClick={() => onSelect('YES')}
|
||||||
|
className="px-6"
|
||||||
|
>
|
||||||
|
Yes
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color={selected === 'NO' ? 'red' : 'gray'}
|
||||||
|
onClick={() => onSelect('NO')}
|
||||||
|
className="px-6"
|
||||||
|
>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
color={selected === 'CANCEL' ? 'yellow' : 'gray'}
|
||||||
|
onClick={() => onSelect('CANCEL')}
|
||||||
|
className="px-6"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
|
@ -35,22 +67,20 @@ export function YesNoSelector(props: {
|
||||||
function Button(props: {
|
function Button(props: {
|
||||||
className?: string
|
className?: string
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
color: 'green' | 'red' | 'deemphasized'
|
color: 'green' | 'red' | 'yellow' | 'gray'
|
||||||
hideFocusRing?: boolean
|
|
||||||
children?: any
|
children?: any
|
||||||
}) {
|
}) {
|
||||||
const { className, onClick, children, color, hideFocusRing } = props
|
const { className, onClick, children, color } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={classNames(
|
className={clsx(
|
||||||
'inline-flex items-center px-8 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white',
|
'inline-flex items-center px-8 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white',
|
||||||
!hideFocusRing && 'focus:outline-none focus:ring-2 focus:ring-offset-2',
|
|
||||||
color === 'green' && 'btn-primary',
|
color === 'green' && 'btn-primary',
|
||||||
color === 'red' && 'bg-red-400 hover:bg-red-500 focus:ring-red-400',
|
color === 'red' && 'bg-red-400 hover:bg-red-500',
|
||||||
color === 'deemphasized' &&
|
color === 'yellow' && 'bg-yellow-400 hover:bg-yellow-500',
|
||||||
'text-gray-700 bg-gray-300 hover:bg-gray-400 focus:ring-gray-400',
|
color === 'gray' && 'text-gray-700 bg-gray-300 hover:bg-gray-400',
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
|
@ -59,7 +89,3 @@ function Button(props: {
|
||||||
</button>
|
</button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function classNames(...classes: any[]) {
|
|
||||||
return classes.filter(Boolean).join(' ')
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,8 +5,12 @@ import { Header } from '../../components/header'
|
||||||
import { ContractOverview } from '../../components/contract-overview'
|
import { ContractOverview } from '../../components/contract-overview'
|
||||||
import { BetPanel } from '../../components/bet-panel'
|
import { BetPanel } from '../../components/bet-panel'
|
||||||
import { Col } from '../../components/layout/col'
|
import { Col } from '../../components/layout/col'
|
||||||
|
import { useUser } from '../../hooks/use-user'
|
||||||
|
import { ResolutionPanel } from '../../components/resolution-panel'
|
||||||
|
|
||||||
export default function ContractPage() {
|
export default function ContractPage() {
|
||||||
|
const user = useUser()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { contractId } = router.query as { contractId: string }
|
const { contractId } = router.query as { contractId: string }
|
||||||
|
|
||||||
|
@ -20,6 +24,8 @@ export default function ContractPage() {
|
||||||
return <div>Contract not found...</div>
|
return <div>Contract not found...</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isCreator = user?.id === contract.creatorId
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
<Header />
|
<Header />
|
||||||
|
@ -29,7 +35,11 @@ export default function ContractPage() {
|
||||||
|
|
||||||
<div className="mt-12 md:mt-0" />
|
<div className="mt-12 md:mt-0" />
|
||||||
|
|
||||||
<BetPanel className="self-start" contract={contract} />
|
{isCreator ? (
|
||||||
|
<ResolutionPanel className="self-start" creator={user} contract={contract} />
|
||||||
|
) : (
|
||||||
|
<BetPanel className="self-start" contract={contract} />
|
||||||
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user