From 565ded106378fc7a354860d23f50ad7f0605adf6 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Tue, 1 Feb 2022 12:06:42 -0600 Subject: [PATCH] Add folds links in market, hide tags behind Show tags toggle. --- web/components/contract-overview.tsx | 21 ++++++++++++--- web/components/fold-tag.tsx | 17 ++++++++++++ web/components/tags-input.tsx | 36 ++++++++++++++++++++----- web/components/tags-list.tsx | 34 +++++++++++++++++++++++ web/lib/firebase/folds.ts | 10 +++++++ web/pages/[username]/[contractSlug].tsx | 23 +++++++++++----- 6 files changed, 124 insertions(+), 17 deletions(-) create mode 100644 web/components/fold-tag.tsx diff --git a/web/components/contract-overview.tsx b/web/components/contract-overview.tsx index f3896db9..7e50cfe3 100644 --- a/web/components/contract-overview.tsx +++ b/web/components/contract-overview.tsx @@ -18,16 +18,19 @@ import { ContractFeed } from './contract-feed' import { TweetButton } from './tweet-button' import { Bet } from '../../common/bet' import { Comment } from '../../common/comment' -import { TagsInput } from './tags-input' +import { RevealableTagsInput } from './tags-input' import BetRow from './bet-row' +import { Fold } from '../../common/fold' +import { FoldTagList } from './tags-list' export const ContractOverview = (props: { contract: Contract bets: Bet[] comments: Comment[] + folds: Fold[] className?: string }) => { - const { contract, bets, comments, className } = props + const { contract, bets, comments, folds, className } = props const { resolution, creatorId, creatorName } = contract const { probPercent, truePool } = contractMetrics(contract) @@ -85,11 +88,21 @@ export const ContractOverview = (props: { - - + + + + + + + + 0 && 'mt-4')} + contract={contract} + /> + {/* Show a delete button for contracts without any trading */} diff --git a/web/components/fold-tag.tsx b/web/components/fold-tag.tsx new file mode 100644 index 00000000..3ecb2c22 --- /dev/null +++ b/web/components/fold-tag.tsx @@ -0,0 +1,17 @@ +import clsx from 'clsx' +import { Fold } from '../../common/fold' + +export function FoldTag(props: { fold: Fold }) { + const { fold } = props + const { name } = fold + return ( +
+ {name} +
+ ) +} diff --git a/web/components/tags-input.tsx b/web/components/tags-input.tsx index 5da8283b..98818008 100644 --- a/web/components/tags-input.tsx +++ b/web/components/tags-input.tsx @@ -1,11 +1,13 @@ +import clsx from 'clsx' import { useState } from 'react' import { parseWordsAsTags } from '../../common/util/parse' import { Contract, updateContract } from '../lib/firebase/contracts' +import { Col } from './layout/col' import { Row } from './layout/row' -import { TagsList } from './tags-list' +import { CompactTagsList } from './tags-list' -export function TagsInput(props: { contract: Contract }) { - const { contract } = props +export function TagsInput(props: { contract: Contract; className?: string }) { + const { contract, className } = props const { tags } = contract const [tagText, setTagText] = useState('') @@ -24,8 +26,8 @@ export function TagsInput(props: { contract: Contract }) { } return ( - - `#${tag}`)} /> + + `#${tag}`)} /> - + ) } + +export function RevealableTagsInput(props: { + contract: Contract + className?: string +}) { + const { contract, className } = props + const [hidden, setHidden] = useState(true) + + if (hidden) + return ( +
setHidden((hidden) => !hidden)} + > + Show tags +
+ ) + return +} diff --git a/web/components/tags-list.tsx b/web/components/tags-list.tsx index c8d0f815..cf6e6c5e 100644 --- a/web/components/tags-list.tsx +++ b/web/components/tags-list.tsx @@ -2,6 +2,7 @@ import clsx from 'clsx' import { Row } from './layout/row' import { Linkify } from './linkify' import { SiteLink } from './site-link' +import { Fold } from '../../common/fold' export function Hashtag(props: { tag: string; noLink?: boolean }) { const { tag, noLink } = props @@ -51,3 +52,36 @@ export function CompactTagsList(props: { tags: string[] }) {
) } + +export function FoldTag(props: { fold: Fold }) { + const { fold } = props + const { name } = fold + return ( + +
+ {name} +
+
+ ) +} + +export function FoldTagList(props: { folds: Fold[]; className?: string }) { + const { folds, className } = props + return ( + + {folds.length > 0 && ( + <> +
Communities
+ {folds.map((fold) => ( + + ))} + + )} +
+ ) +} diff --git a/web/lib/firebase/folds.ts b/web/lib/firebase/folds.ts index c5c172f1..2d3bef42 100644 --- a/web/lib/firebase/folds.ts +++ b/web/lib/firebase/folds.ts @@ -131,3 +131,13 @@ export function listenForFollow( setFollow(!!value) }) } + +export function getFoldsByTags(tags: string[]) { + if (tags.length === 0) return [] + + const lowercaseTags = tags.map((tag) => tag) + return getValues( + // TODO: split into multiple queries if tags.length > 10. + query(foldCollection, where('tags', 'array-contains-any', lowercaseTags)) + ) +} diff --git a/web/pages/[username]/[contractSlug].tsx b/web/pages/[username]/[contractSlug].tsx index 015506a8..6cd03df0 100644 --- a/web/pages/[username]/[contractSlug].tsx +++ b/web/pages/[username]/[contractSlug].tsx @@ -23,6 +23,8 @@ import { contractTextDetails } from '../../components/contract-card' import { Bet, listAllBets } from '../../lib/firebase/bets' import { Comment, listAllComments } from '../../lib/firebase/comments' import Custom404 from '../404' +import { getFoldsByTags } from '../../lib/firebase/folds' +import { Fold } from '../../../common/fold' export async function getStaticProps(props: { params: { username: string; contractSlug: string } @@ -31,18 +33,23 @@ export async function getStaticProps(props: { const contract = (await getContractFromSlug(contractSlug)) || null const contractId = contract?.id + const foldsPromise = getFoldsByTags(contract?.tags ?? []) + const [bets, comments] = await Promise.all([ - contractId ? listAllBets(contractId) : null, - contractId ? listAllComments(contractId) : null, + contractId ? listAllBets(contractId) : [], + contractId ? listAllComments(contractId) : [], ]) + const folds = await foldsPromise + return { props: { + contract, username, slug: contractSlug, - contract, bets, comments, + folds, }, revalidate: 60, // regenerate after a minute @@ -55,15 +62,16 @@ export async function getStaticPaths() { export default function ContractPage(props: { contract: Contract | null - bets: Bet[] | null - comments: Comment[] | null - slug: string username: string + bets: Bet[] + comments: Comment[] + slug: string + folds: Fold[] }) { const user = useUser() const contract = useContractWithPreload(props.slug, props.contract) - const { bets, comments } = props + const { bets, comments, folds } = props if (!contract) { return @@ -103,6 +111,7 @@ export default function ContractPage(props: { contract={contract} bets={bets ?? []} comments={comments ?? []} + folds={folds} />