import React, { useEffect, useState } from 'react' import { ArrowLeftIcon } from '@heroicons/react/outline' import { useContractWithPreload } from 'web/hooks/use-contract' import { ContractOverview } from 'web/components/contract/contract-overview' import { BetPanel } from 'web/components/bet-panel' import { Col } from 'web/components/layout/col' import { useUser } from 'web/hooks/use-user' import { ResolutionPanel } from 'web/components/resolution-panel' import { Spacer } from 'web/components/layout/spacer' import { Contract, getContractFromSlug, tradingAllowed, } from 'web/lib/firebase/contracts' import { SEO } from 'web/components/SEO' import { Page } from 'web/components/page' import { Bet, listAllBets } from 'web/lib/firebase/bets' import { listAllComments } from 'web/lib/firebase/comments' import Custom404 from '../404' import { AnswersPanel } from 'web/components/answers/answers-panel' import { fromPropz, usePropz } from 'web/hooks/use-propz' import { ContractTabs } from 'web/components/contract/contract-tabs' import { FullscreenConfetti } from 'web/components/fullscreen-confetti' import { NumericBetPanel } from 'web/components/numeric-bet-panel' import { NumericResolutionPanel } from 'web/components/numeric-resolution-panel' import { useIsIframe } from 'web/hooks/use-is-iframe' import ContractEmbedPage from '../embed/[username]/[contractSlug]' import { useBets } from 'web/hooks/use-bets' import { CPMMBinaryContract } from 'common/contract' import { AlertBox } from 'web/components/alert-box' import { useTracking } from 'web/hooks/use-tracking' import { useTipTxns } from 'web/hooks/use-tip-txns' import { useSaveReferral } from 'web/hooks/use-save-referral' import { User } from 'common/user' import { ContractComment } from 'common/comment' import { getOpenGraphProps } from 'common/contract-details' import { ContractLeaderboard, ContractTopTrades, } from 'web/components/contract/contract-leaderboard' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { params: { username: string; contractSlug: string } }) { const { username, contractSlug } = props.params const contract = (await getContractFromSlug(contractSlug)) || null const contractId = contract?.id const [bets, comments] = await Promise.all([ contractId ? listAllBets(contractId) : [], contractId ? listAllComments(contractId) : [], ]) return { props: { contract, username, slug: contractSlug, // Limit the data sent to the client. Client will still load all bets and comments directly. bets: bets.slice(0, 5000), comments: comments.slice(0, 1000), }, revalidate: 60, // regenerate after a minute } } export async function getStaticPaths() { return { paths: [], fallback: 'blocking' } } export default function ContractPage(props: { contract: Contract | null username: string bets: Bet[] comments: ContractComment[] slug: string backToHome?: () => void }) { props = usePropz(props, getStaticPropz) ?? { contract: null, username: '', comments: [], bets: [], slug: '', } const user = useUser() const inIframe = useIsIframe() if (inIframe) { return } const { contract } = props if (!contract) { return } return } export function ContractPageSidebar(props: { user: User | null | undefined contract: Contract }) { const { contract, user } = props const { creatorId, isResolved, outcomeType } = contract const isCreator = user?.id === creatorId const isBinary = outcomeType === 'BINARY' const isPseudoNumeric = outcomeType === 'PSEUDO_NUMERIC' const isNumeric = outcomeType === 'NUMERIC' const allowTrade = tradingAllowed(contract) const allowResolve = !isResolved && isCreator && !!user const hasSidePanel = (isBinary || isNumeric || isPseudoNumeric) && (allowTrade || allowResolve) return hasSidePanel ? ( {allowTrade && (isNumeric ? ( ) : ( ))} {allowResolve && (isNumeric || isPseudoNumeric ? ( ) : ( ))} ) : null } export function ContractPageContent( props: Parameters[0] & { contract: Contract user?: User | null } ) { const { backToHome, comments, user } = props const contract = useContractWithPreload(props.contract) ?? props.contract useTracking('view market', { slug: contract.slug, contractId: contract.id, creatorId: contract.creatorId, }) const bets = useBets(contract.id) ?? props.bets // Sort for now to see if bug is fixed. comments.sort((c1, c2) => c1.createdTime - c2.createdTime) const tips = useTipTxns({ contractId: contract.id }) const [showConfetti, setShowConfetti] = useState(false) useEffect(() => { const shouldSeeConfetti = !!( user && contract.creatorId === user.id && Date.now() - contract.createdTime < 10 * 1000 ) setShowConfetti(shouldSeeConfetti) }, [contract, user]) const { isResolved, question, outcomeType } = contract const allowTrade = tradingAllowed(contract) const ogCardProps = getOpenGraphProps(contract) useSaveReferral(user, { defaultReferrerUsername: contract.creatorUsername, contractId: contract.id, }) const rightSidebar = return ( {showConfetti && ( )} {ogCardProps && ( )} {backToHome && ( )} !b.challengeSlug)} /> {outcomeType === 'NUMERIC' && ( )} {(outcomeType === 'FREE_RESPONSE' || outcomeType === 'MULTIPLE_CHOICE') && ( <> )} {outcomeType === 'NUMERIC' && allowTrade && ( )} {isResolved && ( <>
)}
) }