diff --git a/web/components/contract/contract-card.tsx b/web/components/contract/contract-card.tsx
index 10d9b2cd..f415a38c 100644
--- a/web/components/contract/contract-card.tsx
+++ b/web/components/contract/contract-card.tsx
@@ -1,27 +1,15 @@
import clsx from 'clsx'
import Link from 'next/link'
import _ from 'lodash'
-import { ClockIcon, DatabaseIcon, PencilIcon } from '@heroicons/react/outline'
-import { TrendingUpIcon } from '@heroicons/react/solid'
import { Row } from '../layout/row'
-import { formatMoney, formatPercent } from '../../../common/util/format'
-import { UserLink } from '../user-page'
+import { formatPercent } from '../../../common/util/format'
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 { ContractInfoDialog } from './contract-info-dialog'
-import { Bet } from '../../../common/bet'
import {
Binary,
CPMM,
@@ -36,6 +24,7 @@ import {
FreeResponseOutcomeLabel,
} from '../outcome-label'
import { getOutcomeProbability } from '../../../common/calculate'
+import { AbbrContractDetails } from './contract-details'
export function ContractCard(props: {
contract: Contract
@@ -187,215 +176,3 @@ export function FreeResponseResolutionOrChance(props: {
)
}
-
-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
- bets: Bet[]
- isCreator?: boolean
- hideShareButtons?: boolean
-}) {
- const { contract, bets, isCreator, hideShareButtons } = props
- const { closeTime, creatorName, creatorUsername } = contract
- const { volumeLabel, createdDate, resolvedDate } = contractMetrics(contract)
-
- return (
-
-
-
-
-
-
-
- {(!!closeTime || !!resolvedDate) && (
-
-
-
- {/*
- {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 isSameYear = dayjs(closeTime).isSame(dayjs(), 'year')
- const isSameDay = dayjs(closeTime).isSame(dayjs(), 'day')
-
- 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}
- >
- {isSameYear
- ? dayjs(closeTime).format('MMM D')
- : dayjs(closeTime).format('MMM D, YYYY')}
- {isSameDay && <> ({fromNow(closeTime)})>}
-
- )}
-
- {isCreator &&
- (isEditingCloseTime ? (
-
- ) : (
-
- ))}
- >
- )
-}
diff --git a/web/components/contract/contract-details.tsx b/web/components/contract/contract-details.tsx
new file mode 100644
index 00000000..83c3c25a
--- /dev/null
+++ b/web/components/contract/contract-details.tsx
@@ -0,0 +1,232 @@
+import clsx from 'clsx'
+import _ from 'lodash'
+import { ClockIcon, DatabaseIcon, PencilIcon } from '@heroicons/react/outline'
+import { TrendingUpIcon } from '@heroicons/react/solid'
+import { Row } from '../layout/row'
+import { formatMoney } from '../../../common/util/format'
+import { UserLink } from '../user-page'
+import {
+ Contract,
+ contractMetrics,
+ 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 { useState } from 'react'
+import { ContractInfoDialog } from './contract-info-dialog'
+import { Bet } from '../../../common/bet'
+
+export 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
+ bets: Bet[]
+ isCreator?: boolean
+ hideShareButtons?: boolean
+}) {
+ const { contract, bets, isCreator, hideShareButtons } = props
+ const { closeTime, creatorName, creatorUsername } = contract
+ const { volumeLabel, createdDate, resolvedDate } = contractMetrics(contract)
+
+ return (
+
+
+
+
+
+
+
+ {(!!closeTime || !!resolvedDate) && (
+
+
+
+ {/*
+ {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 isSameYear = dayjs(closeTime).isSame(dayjs(), 'year')
+ const isSameDay = dayjs(closeTime).isSame(dayjs(), 'day')
+
+ 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}
+ >
+ {isSameYear
+ ? dayjs(closeTime).format('MMM D')
+ : dayjs(closeTime).format('MMM D, YYYY')}
+ {isSameDay && <> ({fromNow(closeTime)})>}
+
+ )}
+
+ {isCreator &&
+ (isEditingCloseTime ? (
+
+ ) : (
+
+ ))}
+ >
+ )
+}
diff --git a/web/components/contract/contract-overview.tsx b/web/components/contract/contract-overview.tsx
index c928c1d7..88dc053f 100644
--- a/web/components/contract/contract-overview.tsx
+++ b/web/components/contract/contract-overview.tsx
@@ -8,7 +8,6 @@ import { Linkify } from '../linkify'
import clsx from 'clsx'
import {
FreeResponseResolutionOrChance,
- ContractDetails,
BinaryResolutionOrChance,
} from './contract-card'
import { Bet } from '../../../common/bet'
@@ -17,6 +16,7 @@ import BetRow from '../bet-row'
import { AnswersGraph } from '../answers/answers-graph'
import { DPM, FreeResponse, FullContract } from '../../../common/contract'
import { ContractDescription } from './contract-description'
+import { ContractDetails } from './contract-details'
export const ContractOverview = (props: {
contract: Contract