De-feedify contract bets list

This commit is contained in:
Marshall Polaris 2022-08-27 02:05:35 -07:00
parent 1e3a0ca3d9
commit 4cde587ae6
6 changed files with 68 additions and 111 deletions

View File

@ -123,12 +123,7 @@ export function ContractTopTrades(props: {
<> <>
<Title text="💸 Smartest money" className="!mt-0" /> <Title text="💸 Smartest money" className="!mt-0" />
<div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4"> <div className="relative flex items-start space-x-3 rounded-md bg-gray-50 px-2 py-4">
<FeedBet <FeedBet contract={contract} bet={betsById[topBetId]} />
contract={contract}
bet={betsById[topBetId]}
hideOutcome={false}
smallAvatar={false}
/>
</div> </div>
<div className="mt-2 text-sm text-gray-500"> <div className="mt-2 text-sm text-gray-500">
{topBettor?.name} made {formatMoney(profitById[topBetId] || 0)}! {topBettor?.name} made {formatMoney(profitById[topBetId] || 0)}!

View File

@ -2,7 +2,10 @@ import { Bet } from 'common/bet'
import { Contract } from 'common/contract' import { Contract } from 'common/contract'
import { ContractComment } from 'common/comment' import { ContractComment } from 'common/comment'
import { User } from 'common/user' import { User } from 'common/user'
import { ContractActivity } from '../feed/contract-activity' import {
ContractActivity,
ContractBetsActivity,
} from '../feed/contract-activity'
import { ContractBetsTable, BetsSummary } from '../bets-list' import { ContractBetsTable, BetsSummary } from '../bets-list'
import { Spacer } from '../layout/spacer' import { Spacer } from '../layout/spacer'
import { Tabs } from '../layout/tabs' import { Tabs } from '../layout/tabs'
@ -34,15 +37,10 @@ export function ContractTabs(props: {
const comments = updatedComments ?? props.comments const comments = updatedComments ?? props.comments
const betActivity = ( const betActivity = (
<ContractActivity <ContractBetsActivity
contract={contract} contract={contract}
bets={bets} bets={bets}
liquidityProvisions={liquidityProvisions} liquidityProvisions={liquidityProvisions}
comments={comments}
tips={tips}
user={user}
mode="bets"
betRowClassName="!mt-0 xl:hidden"
/> />
) )
@ -51,7 +49,6 @@ export function ContractTabs(props: {
<ContractActivity <ContractActivity
contract={contract} contract={contract}
bets={bets} bets={bets}
liquidityProvisions={liquidityProvisions}
comments={comments} comments={comments}
tips={tips} tips={tips}
user={user} user={user}
@ -69,7 +66,6 @@ export function ContractTabs(props: {
<ContractActivity <ContractActivity
contract={contract} contract={contract}
bets={bets} bets={bets}
liquidityProvisions={liquidityProvisions}
comments={comments} comments={comments}
tips={tips} tips={tips}
user={user} user={user}

View File

@ -7,18 +7,15 @@ import { ContractComment } from 'common/comment'
import { Contract, FreeResponseContract } from 'common/contract' import { Contract, FreeResponseContract } from 'common/contract'
import { User } from 'common/user' import { User } from 'common/user'
import { CommentTipMap } from 'web/hooks/use-tip-txns' import { CommentTipMap } from 'web/hooks/use-tip-txns'
import { LiquidityProvision } from 'common/liquidity-provision'
export type ActivityItem = export type ActivityItem =
| DescriptionItem | DescriptionItem
| QuestionItem | QuestionItem
| BetItem
| AnswerGroupItem | AnswerGroupItem
| CloseItem | CloseItem
| ResolveItem | ResolveItem
| CommentInputItem | CommentInputItem
| CommentThreadItem | CommentThreadItem
| LiquidityItem
type BaseActivityItem = { type BaseActivityItem = {
id: string id: string
@ -40,14 +37,6 @@ export type QuestionItem = BaseActivityItem & {
contractPath?: string contractPath?: string
} }
export type BetItem = BaseActivityItem & {
type: 'bet'
bet: Bet
hideOutcome: boolean
smallAvatar: boolean
hideComment?: boolean
}
export type CommentThreadItem = BaseActivityItem & { export type CommentThreadItem = BaseActivityItem & {
type: 'commentThread' type: 'commentThread'
parentComment: ContractComment parentComment: ContractComment
@ -73,14 +62,6 @@ export type ResolveItem = BaseActivityItem & {
type: 'resolve' type: 'resolve'
} }
export type LiquidityItem = BaseActivityItem & {
type: 'liquidity'
liquidity: LiquidityProvision
hideOutcome: boolean
smallAvatar: boolean
hideComment?: boolean
}
function getAnswerAndCommentInputGroups( function getAnswerAndCommentInputGroups(
contract: FreeResponseContract, contract: FreeResponseContract,
bets: Bet[], bets: Bet[],
@ -148,50 +129,16 @@ export function getSpecificContractActivityItems(
contract: Contract, contract: Contract,
bets: Bet[], bets: Bet[],
comments: ContractComment[], comments: ContractComment[],
liquidityProvisions: LiquidityProvision[],
tips: CommentTipMap, tips: CommentTipMap,
user: User | null | undefined, user: User | null | undefined,
options: { options: {
mode: 'comments' | 'bets' | 'free-response-comment-answer-groups' mode: 'comments' | 'free-response-comment-answer-groups'
} }
) { ) {
const { mode } = options const { mode } = options
let items = [] as ActivityItem[] let items = [] as ActivityItem[]
switch (mode) { switch (mode) {
case 'bets':
// Remove first bet (which is the ante):
if (contract.outcomeType === 'FREE_RESPONSE') bets = bets.slice(1)
items.push(
...bets.map((bet) => ({
type: 'bet' as const,
id: bet.id + '-' + bet.isSold,
bet,
contract,
hideOutcome: false,
smallAvatar: false,
hideComment: true,
}))
)
items.push(
...liquidityProvisions.map((liquidity) => ({
type: 'liquidity' as const,
id: liquidity.id,
contract,
liquidity,
hideOutcome: false,
smallAvatar: false,
}))
)
items = sortBy(items, (item) =>
item.type === 'bet'
? item.bet.createdTime
: item.type === 'liquidity'
? item.liquidity.createdTime
: undefined
)
break
case 'comments': { case 'comments': {
const nonFreeResponseComments = comments.filter((comment) => const nonFreeResponseComments = comments.filter((comment) =>
commentIsGeneralComment(comment, contract) commentIsGeneralComment(comment, contract)

View File

@ -4,25 +4,72 @@ import { Bet } from 'common/bet'
import { useBets } from 'web/hooks/use-bets' import { useBets } from 'web/hooks/use-bets'
import { getSpecificContractActivityItems } from './activity-items' import { getSpecificContractActivityItems } from './activity-items'
import { FeedItems } from './feed-items' import { FeedItems } from './feed-items'
import { FeedBet } from './feed-bets'
import { FeedLiquidity } from './feed-liquidity'
import { User } from 'common/user' import { User } from 'common/user'
import { useContractWithPreload } from 'web/hooks/use-contract' import { useContractWithPreload } from 'web/hooks/use-contract'
import { CommentTipMap } from 'web/hooks/use-tip-txns' import { CommentTipMap } from 'web/hooks/use-tip-txns'
import { LiquidityProvision } from 'common/liquidity-provision' import { LiquidityProvision } from 'common/liquidity-provision'
import { sortBy } from 'lodash'
import { Col } from 'web/components/layout/col'
export function ContractBetsActivity(props: {
contract: Contract
bets: Bet[]
liquidityProvisions: LiquidityProvision[]
}) {
const { contract, bets, liquidityProvisions } = props
// Remove first bet (which is the ante):
const displayedBets =
contract.outcomeType === 'FREE_RESPONSE' ? bets.slice(1) : bets
const items = [
...displayedBets.map((bet) => ({
type: 'bet' as const,
id: bet.id + '-' + bet.isSold,
bet,
})),
...liquidityProvisions.map((liquidity) => ({
type: 'liquidity' as const,
id: liquidity.id,
liquidity,
})),
]
const sortedItems = sortBy(items, (item) =>
item.type === 'bet'
? -item.bet.createdTime
: item.type === 'liquidity'
? -item.liquidity.createdTime
: undefined
)
return (
<Col className="gap-4">
{sortedItems.map((item) =>
item.type === 'bet' ? (
<FeedBet key={item.id} contract={contract} bet={item.bet} />
) : (
<FeedLiquidity key={item.id} liquidity={item.liquidity} />
)
)}
</Col>
)
}
export function ContractActivity(props: { export function ContractActivity(props: {
contract: Contract contract: Contract
bets: Bet[] bets: Bet[]
comments: ContractComment[] comments: ContractComment[]
liquidityProvisions: LiquidityProvision[]
tips: CommentTipMap tips: CommentTipMap
user: User | null | undefined user: User | null | undefined
mode: 'comments' | 'bets' | 'free-response-comment-answer-groups' mode: 'comments' | 'free-response-comment-answer-groups'
contractPath?: string contractPath?: string
className?: string className?: string
betRowClassName?: string betRowClassName?: string
}) { }) {
const { user, mode, tips, className, betRowClassName, liquidityProvisions } = const { user, mode, tips, className, betRowClassName } = props
props
const contract = useContractWithPreload(props.contract) ?? props.contract const contract = useContractWithPreload(props.contract) ?? props.contract
const comments = props.comments const comments = props.comments
@ -37,7 +84,6 @@ export function ContractActivity(props: {
contract, contract,
bets, bets,
comments, comments,
liquidityProvisions,
tips, tips,
user, user,
{ mode } { mode }

View File

@ -16,13 +16,8 @@ import { SiteLink } from 'web/components/site-link'
import { getChallenge, getChallengeUrl } from 'web/lib/firebase/challenges' import { getChallenge, getChallengeUrl } from 'web/lib/firebase/challenges'
import { Challenge } from 'common/challenge' import { Challenge } from 'common/challenge'
export function FeedBet(props: { export function FeedBet(props: { contract: Contract; bet: Bet }) {
contract: Contract const { contract, bet } = props
bet: Bet
hideOutcome: boolean
smallAvatar: boolean
}) {
const { contract, bet, hideOutcome, smallAvatar } = props
const { userId, createdTime } = bet const { userId, createdTime } = bet
const isBeforeJune2022 = dayjs(createdTime).isBefore('2022-06-01') const isBeforeJune2022 = dayjs(createdTime).isBefore('2022-06-01')
@ -33,21 +28,11 @@ export function FeedBet(props: {
const isSelf = user?.id === userId const isSelf = user?.id === userId
return ( return (
<Row className={'flex w-full items-center gap-2 pt-3'}> <Row className="flex w-full items-center gap-2 pt-3">
{isSelf ? ( {isSelf ? (
<Avatar <Avatar avatarUrl={user.avatarUrl} username={user.username} />
className={clsx(smallAvatar && 'ml-1')}
size={smallAvatar ? 'sm' : undefined}
avatarUrl={user.avatarUrl}
username={user.username}
/>
) : bettor ? ( ) : bettor ? (
<Avatar <Avatar avatarUrl={bettor.avatarUrl} username={bettor.username} />
className={clsx(smallAvatar && 'ml-1')}
size={smallAvatar ? 'sm' : undefined}
avatarUrl={bettor.avatarUrl}
username={bettor.username}
/>
) : ( ) : (
<EmptyAvatar className="mx-1" /> <EmptyAvatar className="mx-1" />
)} )}
@ -56,7 +41,6 @@ export function FeedBet(props: {
contract={contract} contract={contract}
isSelf={isSelf} isSelf={isSelf}
bettor={bettor} bettor={bettor}
hideOutcome={hideOutcome}
className="flex-1" className="flex-1"
/> />
</Row> </Row>

View File

@ -3,7 +3,6 @@ import { User } from 'common/user'
import { useUser, useUserById } from 'web/hooks/use-user' import { useUser, useUserById } from 'web/hooks/use-user'
import { Row } from 'web/components/layout/row' import { Row } from 'web/components/layout/row'
import { Avatar, EmptyAvatar } from 'web/components/avatar' import { Avatar, EmptyAvatar } from 'web/components/avatar'
import clsx from 'clsx'
import { formatMoney } from 'common/util/format' import { formatMoney } from 'common/util/format'
import { RelativeTimestamp } from 'web/components/relative-timestamp' import { RelativeTimestamp } from 'web/components/relative-timestamp'
import React from 'react' import React from 'react'
@ -11,10 +10,10 @@ import { UserLink } from '../user-page'
import { LiquidityProvision } from 'common/liquidity-provision' import { LiquidityProvision } from 'common/liquidity-provision'
export function FeedLiquidity(props: { export function FeedLiquidity(props: {
className?: string
liquidity: LiquidityProvision liquidity: LiquidityProvision
smallAvatar: boolean
}) { }) {
const { liquidity, smallAvatar } = props const { liquidity } = props
const { userId, createdTime } = liquidity const { userId, createdTime } = liquidity
const isBeforeJune2022 = dayjs(createdTime).isBefore('2022-06-01') const isBeforeJune2022 = dayjs(createdTime).isBefore('2022-06-01')
@ -26,21 +25,11 @@ export function FeedLiquidity(props: {
return ( return (
<> <>
<Row className={'flex w-full gap-2 pt-3'}> <Row className="flex w-full gap-2 pt-3">
{isSelf ? ( {isSelf ? (
<Avatar <Avatar avatarUrl={user.avatarUrl} username={user.username} />
className={clsx(smallAvatar && 'ml-1')}
size={smallAvatar ? 'sm' : undefined}
avatarUrl={user.avatarUrl}
username={user.username}
/>
) : bettor ? ( ) : bettor ? (
<Avatar <Avatar avatarUrl={bettor.avatarUrl} username={bettor.username} />
className={clsx(smallAvatar && 'ml-1')}
size={smallAvatar ? 'sm' : undefined}
avatarUrl={bettor.avatarUrl}
username={bettor.username}
/>
) : ( ) : (
<div className="relative px-1"> <div className="relative px-1">
<EmptyAvatar /> <EmptyAvatar />