From 7aac2e135eb39724b1184d085706d5039d033541 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Tue, 5 Jul 2022 16:19:44 -0700 Subject: [PATCH] Duplicate a question from '...' screen --- .../contract/contract-info-dialog.tsx | 2 + web/components/copy-contract-button.tsx | 54 +++++++++++++++ web/pages/create.tsx | 69 +++++++++++++------ 3 files changed, 103 insertions(+), 22 deletions(-) create mode 100644 web/components/copy-contract-button.tsx diff --git a/web/components/contract/contract-info-dialog.tsx b/web/components/contract/contract-info-dialog.tsx index 12fd8dd9..3e51902b 100644 --- a/web/components/contract/contract-info-dialog.tsx +++ b/web/components/contract/contract-info-dialog.tsx @@ -21,6 +21,7 @@ import { Title } from '../title' import { TweetButton } from '../tweet-button' import { InfoTooltip } from '../info-tooltip' import { TagsInput } from 'web/components/tags-input' +import { DuplicateContractButton } from '../copy-contract-button' export const contractDetailsButtonClassName = 'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500' @@ -71,6 +72,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) { tweetText={getTweetText(contract, false)} /> +
diff --git a/web/components/copy-contract-button.tsx b/web/components/copy-contract-button.tsx new file mode 100644 index 00000000..ad378878 --- /dev/null +++ b/web/components/copy-contract-button.tsx @@ -0,0 +1,54 @@ +import { DuplicateIcon } from '@heroicons/react/outline' +import clsx from 'clsx' +import { Contract } from 'common/contract' +import { getMappedValue } from 'common/pseudo-numeric' +import { trackCallback } from 'web/lib/service/analytics' + +export function DuplicateContractButton(props: { + contract: Contract + className?: string +}) { + const { contract, className } = props + + return ( + + + ) +} + +// Pass along the Uri to create a new contract +function duplicateContractHref(contract: Contract) { + const params = { + q: contract.question, + closeTime: contract.closeTime || 0, + description: contract.description, + outcomeType: contract.outcomeType, + } as Record + + if (contract.outcomeType === 'PSEUDO_NUMERIC') { + params.min = contract.min + params.max = contract.max + params.isLogScale = contract.isLogScale + params.initValue = getMappedValue(contract)(contract.initialProbability) + } + + return ( + `/create?` + + Object.entries(params) + .map(([key, value]) => `${key}=${encodeURIComponent(value)}`) + .join('&') + ) +} diff --git a/web/pages/create.tsx b/web/pages/create.tsx index 6a5f96ae..83bea10f 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -28,14 +28,32 @@ import { GroupSelector } from 'web/components/groups/group-selector' import { CATEGORIES } from 'common/categories' import { User } from 'common/user' -export default function Create() { - const [question, setQuestion] = useState('') - // get query params: - const router = useRouter() - const { groupId } = router.query as { groupId: string } - useTracking('view create page') - const creator = useUser() +type NewQuestionParams = { + groupId?: string + q: string + type: string + description: string + closeTime: string + outcomeType: string + // Params for PSEUDO_NUMERIC outcomeType + min?: string + max?: string + isLogScale?: string + initValue?: string +} +export default function Create() { + useTracking('view create page') + const router = useRouter() + const params = router.query as NewQuestionParams + // TODO: Not sure why Question is pulled out as its own component; + // Maybe merge into newContract and then we don't need useEffect here. + const [question, setQuestion] = useState('') + useEffect(() => { + setQuestion(params.q ?? '') + }, [params.q]) + + const creator = useUser() useEffect(() => { if (creator === null) router.push('/') }, [creator, router]) @@ -65,11 +83,7 @@ export default function Create() {
- + @@ -80,18 +94,21 @@ export default function Create() { export function NewContract(props: { creator: User question: string - groupId?: string + params?: NewQuestionParams }) { - const { creator, question, groupId } = props - const [outcomeType, setOutcomeType] = useState('BINARY') + const { creator, question, params } = props + const { groupId, initValue } = params ?? {} + const [outcomeType, setOutcomeType] = useState( + (params?.outcomeType as outcomeType) ?? 'BINARY' + ) const [initialProb] = useState(50) - const [minString, setMinString] = useState('') - const [maxString, setMaxString] = useState('') - const [isLogScale, setIsLogScale] = useState(false) - const [initialValueString, setInitialValueString] = useState('') + const [minString, setMinString] = useState(params?.min ?? '') + const [maxString, setMaxString] = useState(params?.max ?? '') + const [isLogScale, setIsLogScale] = useState(!!params?.isLogScale) + const [initialValueString, setInitialValueString] = useState(initValue) - const [description, setDescription] = useState('') + const [description, setDescription] = useState(params?.description ?? '') // const [tagText, setTagText] = useState(tag ?? '') // const tags = parseWordsAsTags(tagText) useEffect(() => { @@ -113,10 +130,18 @@ export function NewContract(props: { // }, [ante, creator]) // const [anteError, setAnteError] = useState() + + // If params.closeTime is set, extract out the specified date and time // By default, close the market a week from today const weekFromToday = dayjs().add(7, 'day').format('YYYY-MM-DD') - const [closeDate, setCloseDate] = useState(weekFromToday) - const [closeHoursMinutes, setCloseHoursMinutes] = useState('23:59') + const timeInMs = Number(params?.closeTime ?? 0) + const initDate = timeInMs + ? dayjs(timeInMs).format('YYYY-MM-DD') + : weekFromToday + const initTime = timeInMs ? dayjs(timeInMs).format('HH:mm') : '23:59' + const [closeDate, setCloseDate] = useState(initDate) + const [closeHoursMinutes, setCloseHoursMinutes] = useState(initTime) + const [marketInfoText, setMarketInfoText] = useState('') const [isSubmitting, setIsSubmitting] = useState(false) const [selectedGroup, setSelectedGroup] = useState(