import clsx from 'clsx' import Link from 'next/link' import { ClockIcon, DatabaseIcon, PencilIcon } from '@heroicons/react/outline' import { TrendingUpIcon } from '@heroicons/react/solid' import { Row } from '../components/layout/row' import { formatMoney, formatPercent } from '../../common/util/format' import { UserLink } from './user-page' import { Contract, contractMetrics, contractPath, getBinaryProbPercent, updateContract, } from '../lib/firebase/contracts' import { Col } from './layout/col' import dayjs from 'dayjs' import { DateTimeTooltip } from './datetime-tooltip' import { fromNow } from '../lib/util/time' import { Avatar } from './avatar' import { Spacer } from './layout/spacer' import { useState } from 'react' import { TweetButton } from './tweet-button' import { getProbability } from '../../common/calculate' import { ShareEmbedButton } from './share-embed-button' export function ContractCard(props: { contract: Contract showHotVolume?: boolean showCloseTime?: boolean className?: string }) { const { contract, showHotVolume, showCloseTime, className } = props const { question } = contract return (

{question}

) } export function ResolutionOrChance(props: { contract: Contract large?: boolean className?: string }) { const { contract, large, className } = props const { resolution, outcomeType } = contract const isBinary = outcomeType === 'BINARY' const marketClosed = (contract.closeTime || Infinity) < Date.now() const resolutionColor = { YES: 'text-primary', NO: 'text-red-400', MKT: 'text-blue-400', CANCEL: 'text-yellow-400', '': '', // Empty if unresolved }[resolution || ''] ?? 'text-primary' const probColor = marketClosed ? 'text-gray-400' : 'text-primary' const resolutionText = { YES: 'YES', NO: 'NO', MKT: isBinary ? formatPercent( contract.resolutionProbability ?? getProbability(contract) ) : 'MULTI', CANCEL: 'N/A', '': '', }[resolution || ''] ?? `#${resolution}` return ( {resolution ? ( <>
Resolved
{resolutionText}
) : ( isBinary && ( <>
{getBinaryProbPercent(contract)}
chance
) )} ) } function AbbrContractDetails(props: { contract: Contract showHotVolume?: boolean showCloseTime?: boolean }) { const { contract, showHotVolume, showCloseTime } = props const { volume24Hours, creatorName, creatorUsername, closeTime } = contract const { volumeLabel } = contractMetrics(contract) return ( {showHotVolume ? ( {formatMoney(volume24Hours)} ) : showCloseTime ? ( {(closeTime || 0) < Date.now() ? 'Closed' : 'Closes'}{' '} {fromNow(closeTime || 0)} ) : ( {/* */} {volumeLabel} )} ) } export function ContractDetails(props: { contract: Contract isCreator?: boolean hideShareButtons?: boolean }) { const { contract, isCreator, hideShareButtons } = props const { closeTime, creatorName, creatorUsername } = contract const { volumeLabel, createdDate, resolvedDate } = contractMetrics(contract) const tweetText = getTweetText(contract, !!isCreator) return ( {createdDate} {resolvedDate && contract.resolutionTime ? ( <> {' - '} {resolvedDate} ) : null} {!resolvedDate && closeTime && ( <> {' - '}{' '} )}
{volumeLabel}
{!hideShareButtons && ( <> )}
) } // String version of the above, to send to the OpenGraph image generator export function contractTextDetails(contract: Contract) { const { closeTime, tags } = contract const { createdDate, resolvedDate, volumeLabel } = contractMetrics(contract) const hashtags = tags.map((tag) => `#${tag}`) return ( `${resolvedDate ? `${createdDate} - ${resolvedDate}` : createdDate}` + (closeTime ? ` • ${closeTime > Date.now() ? 'Closes' : 'Closed'} ${dayjs( closeTime ).format('MMM D, h:mma')}` : '') + ` • ${volumeLabel}` + (hashtags.length > 0 ? ` • ${hashtags.join(' ')}` : '') ) } function EditableCloseDate(props: { closeTime: number contract: Contract isCreator: boolean }) { const { closeTime, contract, isCreator } = props const [isEditingCloseTime, setIsEditingCloseTime] = useState(false) const [closeDate, setCloseDate] = useState( closeTime && dayjs(closeTime).format('YYYY-MM-DDT23:59') ) const onSave = () => { const newCloseTime = dayjs(closeDate).valueOf() if (newCloseTime === closeTime) setIsEditingCloseTime(false) else if (newCloseTime > Date.now()) { const { description } = contract const formattedCloseDate = dayjs(newCloseTime).format('YYYY-MM-DD h:mm a') const newDescription = `${description}\n\nClose date updated to ${formattedCloseDate}` updateContract(contract.id, { closeTime: newCloseTime, description: newDescription, }) setIsEditingCloseTime(false) } } return ( <> {isEditingCloseTime ? (
e.stopPropagation()} onChange={(e) => setCloseDate(e.target.value || '')} min={Date.now()} value={closeDate} />
) : ( Date.now() ? 'Trading ends:' : 'Trading ended:'} time={closeTime} > {dayjs(closeTime).format('MMM D')} ({fromNow(closeTime)}) )} {isCreator && (isEditingCloseTime ? ( ) : ( ))} ) } const getTweetText = (contract: Contract, isCreator: boolean) => { const { question, creatorName, resolution, outcomeType } = contract const isBinary = outcomeType === 'BINARY' const tweetQuestion = isCreator ? question : `${question} Asked by ${creatorName}.` const tweetDescription = resolution ? `Resolved ${resolution}!` : isBinary ? `Currently ${getBinaryProbPercent( contract )} chance, place your bets here:` : `Submit your own answer:` const timeParam = `${Date.now()}`.substring(7) const url = `https://manifold.markets${contractPath(contract)}?t=${timeParam}` return `${tweetQuestion}\n\n${tweetDescription}\n\n${url}` }