From e92674117786985ae3af9d5d22c2e909eeb21bf1 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 13:40:02 -0400 Subject: [PATCH 01/23] sitemap: remove non-public pages; sort by 24hr volume; make market page priority depend on volume --- web/pages/server-sitemap.xml.tsx | 22 ++++++++++++++-------- web/public/robots.txt | 2 +- web/public/sitemap-0.xml | 19 +++---------------- 3 files changed, 18 insertions(+), 25 deletions(-) diff --git a/web/pages/server-sitemap.xml.tsx b/web/pages/server-sitemap.xml.tsx index 8625860c..e8f77e58 100644 --- a/web/pages/server-sitemap.xml.tsx +++ b/web/pages/server-sitemap.xml.tsx @@ -1,20 +1,26 @@ +import _ from 'lodash' import { GetServerSideProps } from 'next' -import { getServerSideSitemap } from 'next-sitemap' +import { getServerSideSitemap, ISitemapField } from 'next-sitemap' + import { DOMAIN } from '../../common/envs/constants' +import { LiteMarket } from './api/v0/_types' export const getServerSideProps: GetServerSideProps = async (ctx) => { - // Fetching data from https://docs.manifold.markets/api + // Fetching data from https://manifold.markets/api const response = await fetch(`https://${DOMAIN}/api/v0/markets`) - const liteMarkets = await response.json() - const fields = liteMarkets.map((liteMarket: any) => ({ + const liteMarkets = (await response.json()) as LiteMarket[] + const sortedMarkets = _.sortBy(liteMarkets, (m) => -m.volume24Hours) + + const fields = sortedMarkets.map((market) => ({ // See https://www.sitemaps.org/protocol.html - loc: liteMarket.url, + loc: market.url, changefreq: 'hourly', - priority: 0.2, // Individual markets aren't that important + priority: market.volume24Hours + market.volume7Days > 100 ? 0.7 : 0.1, // TODO: Add `lastmod` aka last modified time - })) - return getServerSideSitemap(ctx, fields) + })) as ISitemapField[] + + return await getServerSideSitemap(ctx, fields) } // Default export to prevent next.js errors diff --git a/web/public/robots.txt b/web/public/robots.txt index 014904fd..adb6e505 100644 --- a/web/public/robots.txt +++ b/web/public/robots.txt @@ -6,5 +6,5 @@ Allow: / Host: https://manifold.markets # Sitemaps -Sitemap: https://manifold.markets/sitemap.xml Sitemap: https://manifold.markets/server-sitemap.xml +Sitemap: https://manifold.markets/sitemap.xml diff --git a/web/public/sitemap-0.xml b/web/public/sitemap-0.xml index 80d0d7e3..6378f587 100644 --- a/web/public/sitemap-0.xml +++ b/web/public/sitemap-0.xml @@ -1,19 +1,6 @@ -https://manifold.marketshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/abouthourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/accounthourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/add-fundshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/analyticshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/createhourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/embed/analyticshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/foldshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/homehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/landing-pagehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/leaderboardshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/make-predictionshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/marketshourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/profilehourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/simulatorhourly0.72022-03-24T16:51:19.526Z -https://manifold.markets/portfoliohourly0.72022-03-24T16:51:19.526Z +https://manifold.marketshourly0.7 +https://manifold.markets/marketshourly0.2 +https://manifold.markets/leaderboardshourly0.2 \ No newline at end of file From 5a5069a4198ab03d17fcc2198c2ec856dfd8003d Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 13:47:51 -0400 Subject: [PATCH 02/23] sitemap: market changefreq; homepage priority = 1 --- web/pages/server-sitemap.xml.tsx | 2 +- web/public/sitemap-0.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/pages/server-sitemap.xml.tsx b/web/pages/server-sitemap.xml.tsx index e8f77e58..9a3cdfe8 100644 --- a/web/pages/server-sitemap.xml.tsx +++ b/web/pages/server-sitemap.xml.tsx @@ -15,7 +15,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => { const fields = sortedMarkets.map((market) => ({ // See https://www.sitemaps.org/protocol.html loc: market.url, - changefreq: 'hourly', + changefreq: market.volume24Hours > 10 ? 'hourly' : 'daily', priority: market.volume24Hours + market.volume7Days > 100 ? 0.7 : 0.1, // TODO: Add `lastmod` aka last modified time })) as ISitemapField[] diff --git a/web/public/sitemap-0.xml b/web/public/sitemap-0.xml index 6378f587..3b4618fb 100644 --- a/web/public/sitemap-0.xml +++ b/web/public/sitemap-0.xml @@ -1,6 +1,6 @@ -https://manifold.marketshourly0.7 +https://manifold.marketshourly1.0 https://manifold.markets/marketshourly0.2 -https://manifold.markets/leaderboardshourly0.2 +https://manifold.markets/leaderboardsdaily0.2 \ No newline at end of file From d33913a11139965ebb535111aae14d1b22f917fb Mon Sep 17 00:00:00 2001 From: Marshall Polaris Date: Wed, 27 Apr 2022 13:15:14 -0700 Subject: [PATCH 03/23] A couple additions to help newbies out (#104) --- README.md | 10 +++++++--- web/README.md | 17 ++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 7416d3bd..56dceae0 100644 --- a/README.md +++ b/README.md @@ -25,8 +25,9 @@ Operations with complicated contracts (e.g. buying shares) are provided in a sep - `functions/`: Firebase cloud functions, for secure work (e.g. balances, Stripe payments, emails). Also contains in `functions/src/scripts/` some Typescript scripts that do ad hoc CLI interaction with Firebase. -- `common/`: Typescript library code shared between `web/` & `functions/`. Also contains in `common/envs` configuration for - the different environments (i.e. prod, dev, Manifold for Teams instances.) +- `common/`: Typescript library code shared between `web/` & `functions/`. If you want to look at how the market math + works, most of that's in here (it gets called from the `placeBet` and `sellBet` endpoints in `functions/`.) Also + contains in `common/envs` configuration for the different environments (i.e. prod, dev, Manifold for Teams instances.) - `og-image/`: The OpenGraph image generator; creates the preview images shown on Twitter/social media. @@ -34,7 +35,9 @@ Also: Our docs are currently in [a separate repo](https://github.com/manifoldmar ## Contributing -Since we are just now open-sourcing things, we will see how things go. Feel free to open issues, submit PRs, and chat about the process on Discord. We would prefer [small PRs][small-prs] that we can effectively evaluate and review -- maybe check in with us first if you are thinking to work on a big change. +Since we are just now open-sourcing things, we will see how things go. Feel free to open issues, submit PRs, and chat about the process on [Discord][discord]. We would prefer [small PRs][small-prs] that we can effectively evaluate and review -- maybe check in with us first if you are thinking to work on a big change. + +If you need additional access to any infrastructure in order to work on something (e.g. Vercel, Firebase) let us know about that on Discord as well. [vercel]: https://vercel.com/ [jamstack]: https://jamstack.org/ @@ -45,3 +48,4 @@ Since we are just now open-sourcing things, we will see how things go. Feel free [cloud-firestore]: https://firebase.google.com/docs/firestore [cloud-functions]: https://firebase.google.com/docs/functions [small-prs]: https://google.github.io/eng-practices/review/developer/small-cls.html +[discord]: https://discord.gg/eHQBNBqXuh diff --git a/web/README.md b/web/README.md index 8b3e65db..2bfd5056 100644 --- a/web/README.md +++ b/web/README.md @@ -2,13 +2,15 @@ ## Getting started -To run the development server, install [Yarn][yarn], and then in this directory: +To run the development server, install [Yarn 1.x][yarn], and then in this directory: 1. `yarn` to install all dependencies 2. `yarn dev:dev` starts a development web server, pointing at the development database 3. Your site will be available on http://localhost:3000 -Check package.json for other command-line tasks. (e.g. `yarn dev` will point the development server at the prod database. `yarn emulate` will run against a local emulated database, if you are serving it via `yarn serve` from the [`functions/` package][functions-readme].) +Check package.json for other command-line tasks. (e.g. `yarn dev` will point the development server at the prod +database. `yarn emulate` will run against a local emulated database, if you are serving it via `yarn serve` from the +[`functions/` package][functions-readme].) ## Tech stack @@ -24,16 +26,17 @@ branch (to production) and PR branches (to ephemeral staging servers that can be Parts of the file structure that directly map to HTTP endpoints are organized specially per Next.js's prescriptions: -### /public +### public/ These are static files that will be [served by Next verbatim][next-static-files]. -### /pages +### pages/ These are components that [Next's router][next-pages] is aware of and interprets as page roots per their filename, -e.g. the React component in pages/portfolio.tsx is rendered on the user portfolio page at /portfolio. +e.g. the React component in pages/portfolio.tsx is rendered on the user portfolio page at /portfolio. You should +look in here or in `components/` to find any specific piece of UI you are interested in working on. -### /pages/api +### pages/api/ Modules under this route are specially interpreted by Next/Vercel as [functions that will be hosted by Vercel][vercel-functions]. This is where the public Manifold HTTP API lives. @@ -52,7 +55,7 @@ integration][prettier-integrations] to format it in your editor. [nextjs]: https://nextjs.org [vercel]: https://vercel.com [tailwind]: https://tailwindcss.com -[yarn]: https://yarnpkg.com +[yarn]: https://classic.yarnpkg.com/lang/en/docs/install/ [prettier]: https://prettier.io [prettier-integrations]: https://prettier.io/docs/en/editors.html [next-static-files]: https://nextjs.org/docs/basic-features/static-file-serving From 8e514de28f99156cf1dbe1e51d739df0f465a642 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Wed, 27 Apr 2022 16:25:54 -0400 Subject: [PATCH 04/23] Add volume factor to feed --- web/hooks/use-algo-feed.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/web/hooks/use-algo-feed.ts b/web/hooks/use-algo-feed.ts index 543f484b..e8d6396b 100644 --- a/web/hooks/use-algo-feed.ts +++ b/web/hooks/use-algo-feed.ts @@ -151,6 +151,10 @@ function getContractsActivityScores( const activityCountScore = 0.5 + 0.5 * logInterpolation(0, 200, activtyCount) + const { volume7Days, volume } = contract + const combinedVolume = Math.log(volume7Days + 1) + Math.log(volume + 1) + const volumeScore = 0.5 + 0.5 * logInterpolation(4, 25, combinedVolume) + const lastBetTime = contractMostRecentBet[contract.id]?.createdTime ?? contract.createdTime const timeSinceLastBet = Date.now() - lastBetTime @@ -169,7 +173,11 @@ function getContractsActivityScores( const probScore = 0.5 + frac * 0.5 const score = - newCommentScore * activityCountScore * timeAgoScore * probScore + newCommentScore * + activityCountScore * + volumeScore * + timeAgoScore * + probScore // Map score to [0.5, 1] since no recent activty is not a deal breaker. const mappedScore = 0.5 + score / 2 From d9ee03a96ff1b3a7a1cab733154575c8cc422611 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 22:18:52 -0400 Subject: [PATCH 05/23] sendNewCommentEmail: handle sold shares for cfmm --- functions/src/emails.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 290aaecb..20cd002b 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -48,8 +48,8 @@ export const sendMarketResolutionEmail = async ( creatorName: creator.name, question: contract.question, outcome, - investment: `${Math.round(investment)}`, - payout: `${Math.round(payout)}`, + investment: `${Math.floor(investment)}`, + payout: `${Math.floor(payout)}`, url: `https://${DOMAIN}/${creator.username}/${contract.slug}`, } @@ -189,7 +189,9 @@ export const sendNewCommentEmail = async ( let betDescription = '' if (bet) { const { amount, sale } = bet - betDescription = `${sale ? 'sold' : 'bought'} M$ ${Math.round(amount)}` + betDescription = `${sale || amount < 0 ? 'sold' : 'bought'} ${formatMoney( + amount + )}` } const subject = `Comment on ${question}` From 45aa6646fa2cb863071486757bf0960f27ac6718 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Wed, 27 Apr 2022 23:34:50 -0400 Subject: [PATCH 06/23] sendNewCommentEmail: forgot abs value --- functions/src/emails.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/src/emails.ts b/functions/src/emails.ts index 20cd002b..c3b70734 100644 --- a/functions/src/emails.ts +++ b/functions/src/emails.ts @@ -190,7 +190,7 @@ export const sendNewCommentEmail = async ( if (bet) { const { amount, sale } = bet betDescription = `${sale || amount < 0 ? 'sold' : 'bought'} ${formatMoney( - amount + Math.abs(amount) )}` } From da153ceea92a3d20914fff26f77f5c9c8204bed9 Mon Sep 17 00:00:00 2001 From: mantikoros Date: Thu, 28 Apr 2022 10:47:18 -0400 Subject: [PATCH 07/23] bound initial probability to [0.1, 0.9] --- web/components/probability-selector.tsx | 22 +++++++++++++++++----- web/pages/create.tsx | 7 ++++++- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/web/components/probability-selector.tsx b/web/components/probability-selector.tsx index 2fc03787..74dab3c6 100644 --- a/web/components/probability-selector.tsx +++ b/web/components/probability-selector.tsx @@ -4,8 +4,11 @@ export function ProbabilitySelector(props: { probabilityInt: number setProbabilityInt: (p: number) => void isSubmitting?: boolean + minProb?: number + maxProb?: number }) { - const { probabilityInt, setProbabilityInt, isSubmitting } = props + const { probabilityInt, setProbabilityInt, isSubmitting, minProb, maxProb } = + props return ( @@ -15,19 +18,28 @@ export function ProbabilitySelector(props: { value={probabilityInt} className="input input-bordered input-md text-lg" disabled={isSubmitting} - min={1} - max={99} + min={minProb ?? 1} + max={maxProb ?? 99} onChange={(e) => setProbabilityInt(parseInt(e.target.value.substring(0, 2))) } + onBlur={() => + setProbabilityInt( + maxProb && probabilityInt > maxProb + ? maxProb + : minProb && probabilityInt < minProb + ? minProb + : probabilityInt + ) + } /> % setProbabilityInt(parseInt(e.target.value))} /> diff --git a/web/pages/create.tsx b/web/pages/create.tsx index b668fffb..4a4a07b5 100644 --- a/web/pages/create.tsx +++ b/web/pages/create.tsx @@ -106,11 +106,14 @@ export function NewContract(props: { question: string; tag?: string }) { setIsSubmitting(true) + const boundedProb = + initialProb > 90 ? 90 : initialProb < 10 ? 10 : initialProb + const result: any = await createContract({ question, outcomeType, description, - initialProb, + initialProb: boundedProb, ante, closeTime, tags, @@ -172,6 +175,8 @@ export function NewContract(props: { question: string; tag?: string }) { )} From 625308c19d6f59ea7ce4b92b01357d5256a60ef6 Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Thu, 28 Apr 2022 12:29:02 -0600 Subject: [PATCH 08/23] Readme: must be in dev for emulators to work --- functions/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/functions/README.md b/functions/README.md index 5f24a217..7601b7c8 100644 --- a/functions/README.md +++ b/functions/README.md @@ -34,9 +34,10 @@ Adapted from https://firebase.google.com/docs/functions/get-started ## Developing locally +0. `$ firebase use dev` if you haven't already 1. `$ yarn serve` to spin up the emulators - The Emulator UI is at http://localhost:4000; the functions are hosted on :5001. - Note: You have to kill and restart emulators when you change code; no hot reload =( + 1. The Emulator UI is at http://localhost:4000; the functions are hosted on :5001. + Note: You have to kill and restart emulators when you change code; no hot reload =( 2. `$ yarn dev:emulate` in `/web` to connect to emulators with the frontend 1. Note: emulated database is cleared after every shutdown From 2e17f9f91786fac6dc408f4fdd8c45a48a56ff63 Mon Sep 17 00:00:00 2001 From: Austin Chen Date: Thu, 28 Apr 2022 18:45:26 -0400 Subject: [PATCH 09/23] Add a "Show more..." button when there are more contracts --- web/components/contract/contracts-list.tsx | 40 ++++++++++++++-------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/web/components/contract/contracts-list.tsx b/web/components/contract/contracts-list.tsx index 1850cf0b..d6bef2e7 100644 --- a/web/components/contract/contracts-list.tsx +++ b/web/components/contract/contracts-list.tsx @@ -25,15 +25,16 @@ export function ContractsGrid(props: { showCloseTime?: boolean }) { const { showCloseTime } = props + const PAGE_SIZE = 100 + const [page, setPage] = useState(1) const [resolvedContracts, activeContracts] = _.partition( props.contracts, (c) => c.isResolved ) - const contracts = [...activeContracts, ...resolvedContracts].slice( - 0, - MAX_CONTRACTS_DISPLAYED - ) + const allContracts = [...activeContracts, ...resolvedContracts] + const showMore = allContracts.length > PAGE_SIZE * page + const contracts = allContracts.slice(0, PAGE_SIZE * page) if (contracts.length === 0) { return ( @@ -47,16 +48,27 @@ export function ContractsGrid(props: { } return ( -
    - {contracts.map((contract) => ( - - ))} -
+ <> +
    + {contracts.map((contract) => ( + + ))} +
+ {/* Show a link that increases the page num when clicked */} + {showMore && ( + + )} + ) } From 4ec59be46f0dbbaf4cac1b757181217b34b197f9 Mon Sep 17 00:00:00 2001 From: Boa Date: Thu, 28 Apr 2022 17:01:50 -0600 Subject: [PATCH 10/23] Free daily market (#107) * Allow users a free daily market * Show confetti on recent created market * remove unused import * remove comment * Did create market -> hook, capitalize buttons * Check for confetti with interval * Just check once * Capitalize create market button on feed --- functions/src/create-contract.ts | 12 +++++++-- web/components/feed-create.tsx | 2 +- web/components/nav/sidebar.tsx | 20 ++++++++++++--- web/hooks/use-has-created-contract-today.ts | 27 +++++++++++++++++++++ web/package.json | 1 + web/pages/[username]/[contractSlug].tsx | 23 ++++++++++++++++++ web/pages/create.tsx | 18 ++++++++++---- yarn.lock | 12 +++++++++ 8 files changed, 104 insertions(+), 11 deletions(-) create mode 100644 web/hooks/use-has-created-contract-today.ts diff --git a/functions/src/create-contract.ts b/functions/src/create-contract.ts index 16a416b1..e45e7497 100644 --- a/functions/src/create-contract.ts +++ b/functions/src/create-contract.ts @@ -1,7 +1,6 @@ import * as functions from 'firebase-functions' import * as admin from 'firebase-admin' import * as _ from 'lodash' - import { chargeUser, getUser } from './utils' import { Binary, @@ -109,7 +108,16 @@ export const createContract = functions tags ?? [] ) - if (ante) await chargeUser(creator.id, ante) + // uses utc time on server: + const today = new Date().setHours(0, 0, 0, 0) + const userContractsCreatedTodaySnapshot = await firestore + .collection(`contracts`) + .where('creatorId', '==', userId) + .where('createdTime', '>=', today) + .get() + const isFree = userContractsCreatedTodaySnapshot.size === 0 + + if (!isFree && ante) await chargeUser(creator.id, ante) await contractRef.create(contract) diff --git a/web/components/feed-create.tsx b/web/components/feed-create.tsx index d184e035..0a0c6902 100644 --- a/web/components/feed-create.tsx +++ b/web/components/feed-create.tsx @@ -141,7 +141,7 @@ export default function FeedCreate(props: { {/* Show a fake "Create Market" button, which gets replaced with the NewContract one*/} {!isExpanded && (
-
diff --git a/web/components/nav/sidebar.tsx b/web/components/nav/sidebar.tsx index 67e8ae29..576cea87 100644 --- a/web/components/nav/sidebar.tsx +++ b/web/components/nav/sidebar.tsx @@ -19,6 +19,7 @@ import { firebaseLogin, firebaseLogout } from '../../lib/firebase/users' import { ManifoldLogo } from './manifold-logo' import { MenuButton } from './menu' import { getNavigationOptions, ProfileSummary } from './profile-menu' +import { useHasCreatedContractToday } from '../../hooks/use-has-created-contract-today' const navigation = [ { name: 'Home', href: '/home', icon: HomeIcon }, @@ -96,6 +97,7 @@ export default function Sidebar() { const user = useUser() let folds = useFollowedFolds(user) || [] folds = _.sortBy(folds, 'followCount').reverse() + const deservesDailyFreeMarket = !useHasCreatedContractToday(user) const navigationOptions = user === null ? signedOutNavigation : navigation const mobileNavigationOptions = @@ -159,10 +161,22 @@ export default function Sidebar() { /> + {deservesDailyFreeMarket ? ( +
+ Use your daily free market! 🎉 +
+ ) : ( +
+ )} + {user && ( - - - +
+ + + +
)} ) diff --git a/web/hooks/use-has-created-contract-today.ts b/web/hooks/use-has-created-contract-today.ts new file mode 100644 index 00000000..653049d2 --- /dev/null +++ b/web/hooks/use-has-created-contract-today.ts @@ -0,0 +1,27 @@ +import { listContracts } from '../lib/firebase/contracts' +import { useEffect, useState } from 'react' +import dayjs from 'dayjs' +import { User } from '../../common/user' + +export const useHasCreatedContractToday = (user: User | null | undefined) => { + const [hasCreatedContractToday, setHasCreatedContractToday] = useState(false) + + useEffect(() => { + // Uses utc time like the server. + const todayAtMidnight = dayjs.utc().startOf('day').valueOf() + + async function listUserContractsForToday() { + if (!user) return + + const contracts = await listContracts(user.id) + const todayContracts = contracts.filter( + (contract) => contract.createdTime > todayAtMidnight + ) + setHasCreatedContractToday(todayContracts.length > 0) + } + + listUserContractsForToday() + }, [user]) + + return hasCreatedContractToday +} diff --git a/web/package.json b/web/package.json index 04f11245..84077a19 100644 --- a/web/package.json +++ b/web/package.json @@ -30,6 +30,7 @@ "lodash": "4.17.21", "next": "12.1.2", "react": "17.0.2", + "react-confetti": "^6.0.1", "react-dom": "17.0.2", "react-expanding-textarea": "2.3.5" }, diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx index 642de0ca..6e6e4523 100644 --- a/web/pages/[username]/[contractSlug].tsx +++ b/web/pages/[username]/[contractSlug].tsx @@ -33,6 +33,8 @@ import { ContractTabs } from '../../components/contract/contract-tabs' import { FirstArgument } from '../../../common/util/types' import { DPM, FreeResponse, FullContract } from '../../../common/contract' import { contractTextDetails } from '../../components/contract/contract-details' +import { useWindowSize } from '../../hooks/use-window-size' +import Confetti from 'react-confetti' export const getStaticProps = fromPropz(getStaticPropz) export async function getStaticPropz(props: { @@ -86,9 +88,21 @@ export function ContractPageContent(props: FirstArgument) { const { backToHome } = props const user = useUser() + const { width, height } = useWindowSize() const contract = useContractWithPreload(props.contract) const { bets, comments } = props + const [showConfetti, setShowConfetti] = useState(false) + + useEffect(() => { + const shouldSeeConfetti = !!( + user && + contract && + contract.creatorId === user.id && + Date.now() - contract.createdTime < 10 * 1000 + ) + setShowConfetti(shouldSeeConfetti) + }, [contract, user]) // Sort for now to see if bug is fixed. comments.sort((c1, c2) => c1.createdTime - c2.createdTime) @@ -119,6 +133,15 @@ export function ContractPageContent(props: FirstArgument) { return ( + {showConfetti && ( + + )} + {ogCardProps && ( { // if (ante === null && creator) { // const initialAnte = creator.balance < 100 ? MINIMUM_ANTE : 100 @@ -246,10 +250,14 @@ export function NewContract(props: { question: string; tag?: string }) { text={`Cost to create your market. This amount is used to subsidize trading.`} /> - -
{formatMoney(ante)}
- - {ante > balance && ( + {deservesDailyFreeMarket ? ( +
FREE
+ ) : ( +
+ {formatMoney(ante)} +
+ )} + {!deservesDailyFreeMarket && ante > balance && (
Insufficient balance