diff --git a/common/challenge.ts b/common/challenge.ts
index 5900743a..561a0a85 100644
--- a/common/challenge.ts
+++ b/common/challenge.ts
@@ -6,6 +6,8 @@ export type Challenge = {
// The user that created the challenge.
creatorId: string
creatorUsername: string
+ creatorName: string
+ creatorAvatarUrl?: string
// Displayed to people claiming the challenge
message: string
diff --git a/web/components/contract/contract-card-preview.tsx b/web/components/contract/contract-card-preview.tsx
new file mode 100644
index 00000000..da46a55a
--- /dev/null
+++ b/web/components/contract/contract-card-preview.tsx
@@ -0,0 +1,36 @@
+import { Contract } from 'common/lib/contract'
+import { getBinaryProbPercent } from 'web/lib/firebase/contracts'
+import { richTextToString } from 'common/lib/util/parse'
+import { contractTextDetails } from 'web/components/contract/contract-details'
+
+export const getOpenGraphProps = (contract: Contract) => {
+ const {
+ resolution,
+ question,
+ creatorName,
+ creatorUsername,
+ outcomeType,
+ creatorAvatarUrl,
+ description: desc,
+ } = contract
+ const probPercent =
+ outcomeType === 'BINARY' ? getBinaryProbPercent(contract) : undefined
+
+ const stringDesc = typeof desc === 'string' ? desc : richTextToString(desc)
+
+ const description = resolution
+ ? `Resolved ${resolution}. ${stringDesc}`
+ : probPercent
+ ? `${probPercent} chance. ${stringDesc}`
+ : stringDesc
+
+ return {
+ question,
+ probability: probPercent,
+ metadata: contractTextDetails(contract),
+ creatorName,
+ creatorUsername,
+ creatorAvatarUrl,
+ description,
+ }
+}
diff --git a/web/lib/firebase/challenges.ts b/web/lib/firebase/challenges.ts
index 9a3e1972..c3931173 100644
--- a/web/lib/firebase/challenges.ts
+++ b/web/lib/firebase/challenges.ts
@@ -1,11 +1,11 @@
import {
collectionGroup,
+ doc,
orderBy,
query,
setDoc,
where,
} from 'firebase/firestore'
-import { doc } from 'firebase/firestore'
import { Challenge } from 'common/challenge'
import { customAlphabet } from 'nanoid'
import { coll, listenForValue, listenForValues } from './utils'
@@ -46,6 +46,8 @@ export async function createChallenge(data: {
slug,
creatorId: creator.id,
creatorUsername: creator.username,
+ creatorName: creator.name,
+ creatorAvatarUrl: creator.avatarUrl,
creatorAmount: amount,
contractSlug: contract.slug,
contractId: contract.id,
diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx
index ea3d5529..38877819 100644
--- a/web/pages/[username]/[contractSlug].tsx
+++ b/web/pages/[username]/[contractSlug].tsx
@@ -13,7 +13,6 @@ import { Spacer } from 'web/components/layout/spacer'
import { listUsers, User } from 'web/lib/firebase/users'
import {
Contract,
- getBinaryProbPercent,
getContractFromSlug,
tradingAllowed,
} from 'web/lib/firebase/contracts'
@@ -28,7 +27,6 @@ import { Leaderboard } from 'web/components/leaderboard'
import { resolvedPayout } from 'common/calculate'
import { formatMoney } from 'common/util/format'
import { ContractTabs } from 'web/components/contract/contract-tabs'
-import { contractTextDetails } from 'web/components/contract/contract-details'
import { useWindowSize } from 'web/hooks/use-window-size'
import Confetti from 'react-confetti'
import { NumericBetPanel } from '../../components/numeric-bet-panel'
@@ -43,8 +41,8 @@ import { AlertBox } from 'web/components/alert-box'
import { useTracking } from 'web/hooks/use-tracking'
import { CommentTipMap, useTipTxns } from 'web/hooks/use-tip-txns'
import { useLiquidity } from 'web/hooks/use-liquidity'
-import { richTextToString } from 'common/util/parse'
import { useSaveReferral } from 'web/hooks/use-save-referral'
+import { getOpenGraphProps } from 'web/components/contract/contract-card-preview'
export const getStaticProps = fromPropz(getStaticPropz)
export async function getStaticPropz(props: {
@@ -383,35 +381,3 @@ function ContractTopTrades(props: {
)
}
-
-const getOpenGraphProps = (contract: Contract) => {
- const {
- resolution,
- question,
- creatorName,
- creatorUsername,
- outcomeType,
- creatorAvatarUrl,
- description: desc,
- } = contract
- const probPercent =
- outcomeType === 'BINARY' ? getBinaryProbPercent(contract) : undefined
-
- const stringDesc = typeof desc === 'string' ? desc : richTextToString(desc)
-
- const description = resolution
- ? `Resolved ${resolution}. ${stringDesc}`
- : probPercent
- ? `${probPercent} chance. ${stringDesc}`
- : stringDesc
-
- return {
- question,
- probability: probPercent,
- metadata: contractTextDetails(contract),
- creatorName,
- creatorUsername,
- creatorAvatarUrl,
- description,
- }
-}
diff --git a/web/pages/challenges/[username]/[contractSlug]/[challengeSlug].tsx b/web/pages/challenges/[username]/[contractSlug]/[challengeSlug].tsx
index 99008b15..1c454b36 100644
--- a/web/pages/challenges/[username]/[contractSlug]/[challengeSlug].tsx
+++ b/web/pages/challenges/[username]/[contractSlug]/[challengeSlug].tsx
@@ -12,7 +12,7 @@ import { Spacer } from 'web/components/layout/spacer'
import { Row } from 'web/components/layout/row'
import { Challenge } from 'common/challenge'
-import { useChallenge } from 'web/lib/firebase/challenges'
+import { getChallengeUrl, useChallenge } from 'web/lib/firebase/challenges'
import { getPortfolioHistory, getUserByUsername } from 'web/lib/firebase/users'
import { PortfolioMetrics, User } from 'common/user'
import { Page } from 'web/components/page'
@@ -20,7 +20,7 @@ import { useUser, useUserById } from 'web/hooks/use-user'
import { AcceptChallengeButton } from 'web/components/challenges/accept-challenge-button'
import { Avatar } from 'web/components/avatar'
import { UserLink } from 'web/components/user-page'
-import { useEffect, useState } from 'react'
+import React, { useEffect, useState } from 'react'
import { BinaryOutcomeLabel } from 'web/components/outcome-label'
import { formatMoney } from 'common/util/format'
import { last } from 'lodash'
@@ -33,6 +33,9 @@ import {
PseudoNumericResolutionOrExpectation,
} from 'web/components/contract/contract-card'
import { ContractProbGraph } from 'web/components/contract/contract-prob-graph'
+import { SEO } from 'web/components/SEO'
+import { getOpenGraphProps } from 'web/components/contract/contract-card-preview'
+
export const getStaticProps = fromPropz(getStaticPropz)
export async function getStaticPropz(props: {
params: { username: string; contractSlug: string; challengeSlug: string }
@@ -88,23 +91,39 @@ export default function ChallengePage(props: {
)
}
- if (challenge.acceptances.length >= challenge.maxUses)
- return (
-
- )
+ const ogCardProps = getOpenGraphProps(contract)
+
return (
-
+
+ {ogCardProps && (
+
+ )}
+ {challenge.acceptances.length >= challenge.maxUses ? (
+
+ ) : (
+
+ )}
+
)
}
@@ -204,7 +223,7 @@ function ClosedChallengeContent(props: {
)
return (
-
+ <>
{showConfetti && (
-
+ >
)
}
@@ -390,7 +409,7 @@ function OpenChallengeContent(props: {
)
}
return (
-
+ <>
-
+ >
)
}