import { ClockIcon } from '@heroicons/react/outline' import clsx from 'clsx' import { Editor } from '@tiptap/react' import dayjs from 'dayjs' import Link from 'next/link' import { Row } from '../layout/row' import { formatMoney } from 'common/util/format' import { Contract, updateContract } from 'web/lib/firebase/contracts' import { DateTimeTooltip } from '../datetime-tooltip' import { fromNow } from 'web/lib/util/time' import { Avatar } from '../avatar' import { useState } from 'react' import NewContractBadge from '../new-contract-badge' import { MiniUserFollowButton } from '../follow-button' import { DAY_MS } from 'common/util/time' import { useUser } from 'web/hooks/use-user' import { exhibitExts } from 'common/util/parse' import { Button } from 'web/components/button' import { Modal } from 'web/components/layout/modal' import { Col } from 'web/components/layout/col' import { ContractGroupsList } from 'web/components/groups/contract-groups-list' import { linkClass } from 'web/components/site-link' import { getGroupLinkToDisplay, groupPath } from 'web/lib/firebase/groups' import { insertContent } from '../editor/utils' import { contractMetrics } from 'common/contract-details' import { UserLink } from 'web/components/user-link' import { FeaturedContractBadge } from 'web/components/contract/featured-contract-badge' import { Tooltip } from 'web/components/tooltip' import { useWindowSize } from 'web/hooks/use-window-size' import { ExtraContractActionsRow } from './extra-contract-actions-row' import { PlusCircleIcon } from '@heroicons/react/solid' import { GroupLink } from 'common/group' import { Subtitle } from '../subtitle' export type ShowTime = 'resolve-date' | 'close-date' export function MiscDetails(props: { contract: Contract showTime?: ShowTime hideGroupLink?: boolean }) { const { contract, showTime, hideGroupLink } = props const { volume, closeTime, isResolved, createdTime, resolutionTime } = contract const isNew = createdTime > Date.now() - DAY_MS && !isResolved const groupToDisplay = getGroupLinkToDisplay(contract) return ( {showTime === 'close-date' ? ( {(closeTime || 0) < Date.now() ? 'Closed' : 'Closes'}{' '} {fromNow(closeTime || 0)} ) : showTime === 'resolve-date' && resolutionTime !== undefined ? ( {'Resolved '} {fromNow(resolutionTime || 0)} ) : (contract?.featuredOnHomeRank ?? 0) > 0 ? ( ) : volume > 0 || !isNew ? ( {formatMoney(volume)} bet ) : ( )} {!hideGroupLink && groupToDisplay && ( {groupToDisplay.name} )} ) } export function AvatarDetails(props: { contract: Contract className?: string short?: boolean noLink?: boolean }) { const { contract, short, className, noLink } = props const { creatorName, creatorUsername, creatorAvatarUrl } = contract return ( ) } export function useIsMobile() { const { width } = useWindowSize() return (width ?? 0) < 600 } export function ContractDetails(props: { contract: Contract disabled?: boolean }) { const { contract, disabled } = props const isMobile = useIsMobile() return (
{/* GROUPS */} {isMobile && (
)} ) } export function MarketSubheader(props: { contract: Contract disabled?: boolean }) { const { contract, disabled } = props const { creatorName, creatorUsername, creatorId, creatorAvatarUrl } = contract const { resolvedDate } = contractMetrics(contract) const user = useUser() const isCreator = user?.id === creatorId const isMobile = useIsMobile() return ( {!disabled && (
)} {disabled ? ( creatorName ) : ( )} {!isMobile && ( )}
) } export function CloseOrResolveTime(props: { contract: Contract resolvedDate: any isCreator: boolean }) { const { contract, resolvedDate, isCreator } = props const { resolutionTime, closeTime } = contract if (!!closeTime || !!resolvedDate) { return ( {resolvedDate && resolutionTime ? ( <>
resolved 
{resolvedDate}
) : null} {!resolvedDate && closeTime && ( {dayjs().isBefore(closeTime) &&
closes 
} {!dayjs().isBefore(closeTime) &&
closed 
}
)}
) } else return <> } export function MarketGroups(props: { contract: Contract isMobile: boolean | undefined disabled: boolean | undefined }) { const [open, setOpen] = useState(false) const user = useUser() const { contract, isMobile, disabled } = props const groupToDisplay = getGroupLinkToDisplay(contract) return ( <> {!disabled && ( {user && ( )} )} ) } export function ExtraMobileContractDetails(props: { contract: Contract forceShowVolume?: boolean }) { const { contract, forceShowVolume } = props const { volume, resolutionTime, closeTime, creatorId, uniqueBettorCount } = contract const user = useUser() const uniqueBettors = uniqueBettorCount ?? 0 const { resolvedDate } = contractMetrics(contract) const volumeTranslation = volume > 800 || uniqueBettors >= 20 ? 'High' : volume > 300 || uniqueBettors >= 10 ? 'Medium' : 'Low' return ( {resolvedDate && resolutionTime ? ( {resolvedDate} Ended ) : ( !resolvedDate && closeTime && ( Closes  ) )} {(user || forceShowVolume) && ( {volumeTranslation} Activity )} ) } export function GroupDisplay(props: { groupToDisplay?: GroupLink | null isMobile?: boolean }) { const { groupToDisplay, isMobile } = props if (groupToDisplay) { return (
{groupToDisplay.name}
) } else return (
No Group
) } function EditableCloseDate(props: { closeTime: number contract: Contract isCreator: boolean }) { const { closeTime, contract, isCreator } = props const dayJsCloseTime = dayjs(closeTime) const dayJsNow = dayjs() const [isEditingCloseTime, setIsEditingCloseTime] = useState(false) const [closeDate, setCloseDate] = useState( closeTime && dayJsCloseTime.format('YYYY-MM-DD') ) const [closeHoursMinutes, setCloseHoursMinutes] = useState( closeTime && dayJsCloseTime.format('HH:mm') ) const newCloseTime = closeDate ? dayjs(`${closeDate}T${closeHoursMinutes}`).valueOf() : undefined const isSameYear = dayJsCloseTime.isSame(dayJsNow, 'year') const isSameDay = dayJsCloseTime.isSame(dayJsNow, 'day') const onSave = () => { if (!newCloseTime) return if (newCloseTime === closeTime) setIsEditingCloseTime(false) else if (newCloseTime > Date.now()) { const content = contract.description const formattedCloseDate = dayjs(newCloseTime).format('YYYY-MM-DD h:mm a') const editor = new Editor({ content, extensions: exhibitExts }) editor.commands.focus('end') insertContent( editor, `

Close date updated to ${formattedCloseDate}

` ) updateContract(contract.id, { closeTime: newCloseTime, description: editor.getJSON(), }) setIsEditingCloseTime(false) } } return ( <> e.stopPropagation()} onChange={(e) => setCloseDate(e.target.value)} min={Date.now()} value={closeDate} /> e.stopPropagation()} onChange={(e) => setCloseHoursMinutes(e.target.value)} min="00:00" value={closeHoursMinutes} /> Date.now() ? 'Trading ends:' : 'Trading ended:'} time={closeTime} > isCreator && setIsEditingCloseTime(true)} > {isSameDay ? ( {fromNow(closeTime)} ) : isSameYear ? ( dayJsCloseTime.format('MMM D') ) : ( dayJsCloseTime.format('MMM D, YYYY') )} ) }