From 3c1e16b815927a8d36f8867408150892f87d9073 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Tue, 19 Apr 2022 22:34:41 -0500 Subject: [PATCH] Move contract details components to their own file. --- web/components/contract/contract-card.tsx | 227 +---------------- web/components/contract/contract-details.tsx | 232 ++++++++++++++++++ web/components/contract/contract-overview.tsx | 2 +- 3 files changed, 235 insertions(+), 226 deletions(-) create mode 100644 web/components/contract/contract-details.tsx 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