Show old details on lg, don't unfill heart

This commit is contained in:
Ian Philips 2022-08-30 16:14:50 -06:00
parent 876abef040
commit 7c78c59c5d
13 changed files with 263 additions and 183 deletions

View File

@ -31,8 +31,7 @@ export * from './weekly-markets-emails'
export * from './reset-betting-streaks' export * from './reset-betting-streaks'
export * from './reset-weekly-emails-flag' export * from './reset-weekly-emails-flag'
export * from './on-update-contract-follow' export * from './on-update-contract-follow'
export * from './on-create-like' export * from './on-update-like'
export * from './on-delete-like'
// v2 // v2
export * from './health' export * from './health'

View File

@ -1,32 +0,0 @@
import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
import { Like } from '../../common/like'
import { getContract, log } from './utils'
import { uniq } from 'lodash'
const firestore = admin.firestore()
export const onDeleteLike = functions.firestore
.document('users/{userId}/likes/{likeId}')
.onDelete(async (change) => {
const like = change.data() as Like
if (like.type === 'contract') {
await removeContractLike(like)
}
})
const removeContractLike = async (like: Like) => {
const contract = await getContract(like.id)
if (!contract) {
log('Could not find contract')
return
}
const likedByUserIds = uniq(contract.likedByUserIds ?? [])
const newLikedByUserIds = likedByUserIds.filter(
(userId) => userId !== like.userId
)
await firestore.collection('contracts').doc(like.id).update({
likedByUserIds: newLikedByUserIds,
likedByUserCount: newLikedByUserIds.length,
})
}

View File

@ -19,14 +19,36 @@ export const onCreateLike = functions.firestore
} }
}) })
export const onUpdateLike = functions.firestore
.document('users/{userId}/likes/{likeId}')
.onUpdate(async (change, context) => {
const like = change.after.data() as Like
const prevLike = change.before.data() as Like
const { eventId } = context
if (like.type === 'contract' && like.tipTxnId !== prevLike.tipTxnId) {
await handleCreateLikeNotification(like, eventId)
await updateContractLikes(like)
}
})
export const onDeleteLike = functions.firestore
.document('users/{userId}/likes/{likeId}')
.onDelete(async (change) => {
const like = change.data() as Like
if (like.type === 'contract') {
await removeContractLike(like)
}
})
const updateContractLikes = async (like: Like) => { const updateContractLikes = async (like: Like) => {
const contract = await getContract(like.id) const contract = await getContract(like.id)
if (!contract) { if (!contract) {
log('Could not find contract') log('Could not find contract')
return return
} }
const likedByUserIds = uniq(contract.likedByUserIds ?? []) const likedByUserIds = uniq(
likedByUserIds.push(like.userId) (contract.likedByUserIds ?? []).concat(like.userId)
)
await firestore await firestore
.collection('contracts') .collection('contracts')
.doc(like.id) .doc(like.id)
@ -69,3 +91,19 @@ const handleCreateLikeNotification = async (like: Like, eventId: string) => {
tipTxnData tipTxnData
) )
} }
const removeContractLike = async (like: Like) => {
const contract = await getContract(like.id)
if (!contract) {
log('Could not find contract')
return
}
const likedByUserIds = uniq(contract.likedByUserIds ?? [])
const newLikedByUserIds = likedByUserIds.filter(
(userId) => userId !== like.userId
)
await firestore.collection('contracts').doc(like.id).update({
likedByUserIds: newLikedByUserIds,
likedByUserCount: newLikedByUserIds.length,
})
}

View File

@ -16,7 +16,7 @@ import { Contract, updateContract } from 'web/lib/firebase/contracts'
import { DateTimeTooltip } from '../datetime-tooltip' import { DateTimeTooltip } from '../datetime-tooltip'
import { fromNow } from 'web/lib/util/time' import { fromNow } from 'web/lib/util/time'
import { Avatar } from '../avatar' import { Avatar } from '../avatar'
import { useState } from 'react' import React, { useState } from 'react'
import { ContractInfoDialog } from './contract-info-dialog' import { ContractInfoDialog } from './contract-info-dialog'
import { Bet } from 'common/bet' import { Bet } from 'common/bet'
import NewContractBadge from '../new-contract-badge' import NewContractBadge from '../new-contract-badge'
@ -35,6 +35,8 @@ import { contractMetrics } from 'common/contract-details'
import { User } from 'common/user' import { User } from 'common/user'
import { UserLink } from 'web/components/user-link' import { UserLink } from 'web/components/user-link'
import { FeaturedContractBadge } from 'web/components/contract/featured-contract-badge' import { FeaturedContractBadge } from 'web/components/contract/featured-contract-badge'
import { Tooltip } from 'web/components/tooltip'
import { useWindowSize } from 'web/hooks/use-window-size'
export type ShowTime = 'resolve-date' | 'close-date' export type ShowTime = 'resolve-date' | 'close-date'
@ -152,6 +154,8 @@ export function ContractDetails(props: {
groupLinks?.sort((a, b) => a.createdTime - b.createdTime)[0] ?? null groupLinks?.sort((a, b) => a.createdTime - b.createdTime)[0] ?? null
const user = useUser() const user = useUser()
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const { width } = useWindowSize()
const isMobile = (width ?? 0) < 768
const groupInfo = ( const groupInfo = (
<Row> <Row>
@ -178,6 +182,7 @@ export function ContractDetails(props: {
className="whitespace-nowrap" className="whitespace-nowrap"
name={creatorName} name={creatorName}
username={creatorUsername} username={creatorUsername}
short={isMobile}
/> />
)} )}
{!disabled && <UserFollowButton userId={creatorId} small />} {!disabled && <UserFollowButton userId={creatorId} small />}
@ -228,7 +233,7 @@ export function ContractDetails(props: {
</Modal> </Modal>
{(!!closeTime || !!resolvedDate) && ( {(!!closeTime || !!resolvedDate) && (
<Row className="items-center gap-1"> <Row className="hidden items-center gap-1 md:inline-flex">
{resolvedDate && contract.resolutionTime ? ( {resolvedDate && contract.resolutionTime ? (
<> <>
<ClockIcon className="h-5 w-5" /> <ClockIcon className="h-5 w-5" />
@ -255,17 +260,81 @@ export function ContractDetails(props: {
)} )}
{user && ( {user && (
<> <>
<Row className="items-center gap-1"> <Row className="hidden items-center gap-1 md:inline-flex">
<DatabaseIcon className="h-5 w-5" /> <DatabaseIcon className="h-5 w-5" />
<div className="whitespace-nowrap">{volumeLabel}</div> <div className="whitespace-nowrap">{volumeLabel}</div>
</Row> </Row>
{!disabled && <ContractInfoDialog contract={contract} bets={bets} />} {!disabled && (
<ContractInfoDialog
contract={contract}
bets={bets}
className={'hidden md:inline-flex'}
/>
)}
</> </>
)} )}
</Row> </Row>
) )
} }
export function ExtraMobileContractDetails(props: {
contract: Contract
user: User | null | undefined
forceShowVolume?: boolean
}) {
const { contract, user, forceShowVolume } = props
const { resolvedDate } = contractMetrics(contract)
const volumeTranslation =
contract.volume > 1000 ? 'High' : contract.volume > 200 ? 'Medium' : 'Low'
return (
<Row
className={clsx(
'items-center justify-around md:hidden',
user ? 'w-full' : ''
)}
>
{resolvedDate && contract.resolutionTime ? (
<Col className={'items-center text-sm'}>
<Row className={'text-gray-500'}>
<DateTimeTooltip
text="Market resolved:"
time={contract.resolutionTime}
>
{resolvedDate}
</DateTimeTooltip>
</Row>
<Row className={'text-gray-400'}>Ended</Row>
</Col>
) : (
!resolvedDate &&
contract.closeTime && (
<Col className={'items-center text-sm'}>
<Row className={'text-gray-500'}>
<DateTimeTooltip text="Market closes:" time={contract.closeTime}>
<EditableCloseDate
closeTime={contract.closeTime}
contract={contract}
isCreator={contract.creatorId === user?.id}
/>
</DateTimeTooltip>
</Row>
<Row className={'text-gray-400'}>Ends</Row>
</Col>
)
)}
{(user || forceShowVolume) && (
<Col className={'items-center text-sm '}>
<Tooltip text={formatMoney(contract.volume)}>
<Row className={'text-gray-500'}>{volumeTranslation}</Row>
</Tooltip>
<Row className={'text-gray-400'}>Activity</Row>
</Col>
)}
</Row>
)
}
function EditableCloseDate(props: { function EditableCloseDate(props: {
closeTime: number closeTime: number
contract: Contract contract: Contract
@ -340,28 +409,24 @@ function EditableCloseDate(props: {
<DateTimeTooltip <DateTimeTooltip
text={closeTime > Date.now() ? 'Trading ends:' : 'Trading ended:'} text={closeTime > Date.now() ? 'Trading ends:' : 'Trading ended:'}
time={closeTime} time={closeTime}
className={isCreator ? 'cursor-pointer' : ''}
> >
{isSameYear <span onClick={() => isCreator && setIsEditingCloseTime(true)}>
? dayJsCloseTime.format('MMM D') {isSameYear
: dayJsCloseTime.format('MMM D, YYYY')} ? dayJsCloseTime.format('MMM D')
{isSameDay && <> ({fromNow(closeTime)})</>} : dayJsCloseTime.format('MMM D, YYYY')}
{isSameDay && <> ({fromNow(closeTime)})</>}
</span>
</DateTimeTooltip> </DateTimeTooltip>
)} )}
{isCreator && {isCreator && isEditingCloseTime && (
(isEditingCloseTime ? ( <Row className={'mt-2 items-center justify-end'}>
<button className="btn btn-xs" onClick={onSave}> <button className="btn btn-xs" onClick={onSave}>
Done Done
</button> </button>
) : ( </Row>
<Button )}
size={'xs'}
color={'gray-white'}
onClick={() => setIsEditingCloseTime(true)}
>
<PencilIcon className="!container mr-0.5 mb-0.5 inline h-4 w-4" />
</Button>
))}
</> </>
) )
} }

View File

@ -22,8 +22,12 @@ import ShortToggle from '../widgets/short-toggle'
export const contractDetailsButtonClassName = export const contractDetailsButtonClassName =
'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500' 'group flex items-center rounded-md px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-100 text-gray-400 hover:text-gray-500'
export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) { export function ContractInfoDialog(props: {
const { contract, bets } = props contract: Contract
bets: Bet[]
className?: string
}) {
const { contract, bets, className } = props
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [featured, setFeatured] = useState( const [featured, setFeatured] = useState(
@ -69,7 +73,7 @@ export function ContractInfoDialog(props: { contract: Contract; bets: Bet[] }) {
return ( return (
<> <>
<button <button
className={contractDetailsButtonClassName} className={clsx(contractDetailsButtonClassName, className)}
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
> >
<DotsHorizontalIcon <DotsHorizontalIcon

View File

@ -18,10 +18,9 @@ import BetButton from '../bet-button'
import { AnswersGraph } from '../answers/answers-graph' import { AnswersGraph } from '../answers/answers-graph'
import { Contract, CPMMBinaryContract } from 'common/contract' import { Contract, CPMMBinaryContract } from 'common/contract'
import { ContractDescription } from './contract-description' import { ContractDescription } from './contract-description'
import { ContractDetails } from './contract-details' import { ContractDetails, ExtraMobileContractDetails } from './contract-details'
import { NumericGraph } from './numeric-graph' import { NumericGraph } from './numeric-graph'
import { ShareRow } from './share-row' import { ExtraContractActionsRow } from 'web/components/contract/extra-contract-actions-row'
import { LikeMarketButton } from 'web/components/contract/like-market-button'
export const ContractOverview = (props: { export const ContractOverview = (props: {
contract: Contract contract: Contract
@ -40,17 +39,16 @@ export const ContractOverview = (props: {
return ( return (
<Col className={clsx('mb-6', className)}> <Col className={clsx('mb-6', className)}>
<Col className="gap-3 px-2 sm:gap-4"> <Col className="gap-3 px-2 sm:gap-4">
<ContractDetails
contract={contract}
user={user}
bets={bets}
isCreator={isCreator}
/>
<Row className="justify-between gap-4"> <Row className="justify-between gap-4">
<div className="text-2xl text-indigo-700 md:text-3xl"> <Col className="gap-2 text-2xl text-indigo-700 md:text-3xl">
<Linkify text={question} /> <Linkify text={question} />
</div> </Col>
{(outcomeType === 'FREE_RESPONSE' ||
outcomeType === 'MULTIPLE_CHOICE') &&
!resolution && (
<div className={'sm:hidden'}>
<LikeMarketButton contract={contract} user={user} />
</div>
)}
<Row className={'hidden gap-3 xl:flex'}> <Row className={'hidden gap-3 xl:flex'}>
{isBinary && ( {isBinary && (
<BinaryResolutionOrChance <BinaryResolutionOrChance
@ -79,11 +77,9 @@ export const ContractOverview = (props: {
{isBinary ? ( {isBinary ? (
<Row className="items-center justify-between gap-4 xl:hidden"> <Row className="items-center justify-between gap-4 xl:hidden">
<BinaryResolutionOrChance contract={contract} /> <BinaryResolutionOrChance contract={contract} />
<ExtraMobileContractDetails contract={contract} user={user} />
{tradingAllowed(contract) && ( {tradingAllowed(contract) && (
<Row> <Row>
<div className={'sm:hidden'}>
<LikeMarketButton contract={contract} user={user} />
</div>
<Col> <Col>
<BetButton contract={contract as CPMMBinaryContract} /> <BetButton contract={contract as CPMMBinaryContract} />
{!user && ( {!user && (
@ -98,11 +94,9 @@ export const ContractOverview = (props: {
) : isPseudoNumeric ? ( ) : isPseudoNumeric ? (
<Row className="items-center justify-between gap-4 xl:hidden"> <Row className="items-center justify-between gap-4 xl:hidden">
<PseudoNumericResolutionOrExpectation contract={contract} /> <PseudoNumericResolutionOrExpectation contract={contract} />
<ExtraMobileContractDetails contract={contract} user={user} />
{tradingAllowed(contract) && ( {tradingAllowed(contract) && (
<Row> <Row>
<div className={'sm:hidden'}>
<LikeMarketButton contract={contract} user={user} />
</div>
<Col> <Col>
<BetButton contract={contract} /> <BetButton contract={contract} />
{!user && ( {!user && (
@ -130,13 +124,6 @@ export const ContractOverview = (props: {
<NumericResolutionOrExpectation contract={contract} /> <NumericResolutionOrExpectation contract={contract} />
</Row> </Row>
)} )}
<ContractDetails
contract={contract}
bets={bets}
isCreator={isCreator}
user={user}
/>
</Col> </Col>
<div className={'my-1 md:my-2'}></div> <div className={'my-1 md:my-2'}></div>
{(isBinary || isPseudoNumeric) && ( {(isBinary || isPseudoNumeric) && (
@ -144,10 +131,17 @@ export const ContractOverview = (props: {
)}{' '} )}{' '}
{(outcomeType === 'FREE_RESPONSE' || {(outcomeType === 'FREE_RESPONSE' ||
outcomeType === 'MULTIPLE_CHOICE') && ( outcomeType === 'MULTIPLE_CHOICE') && (
<AnswersGraph contract={contract} bets={bets} /> <Col className={'mb-1 gap-y-2'}>
<AnswersGraph contract={contract} bets={bets} />
<ExtraMobileContractDetails
contract={contract}
user={user}
forceShowVolume={true}
/>
</Col>
)} )}
{outcomeType === 'NUMERIC' && <NumericGraph contract={contract} />} {outcomeType === 'NUMERIC' && <NumericGraph contract={contract} />}
<ShareRow user={user} contract={contract} /> <ExtraContractActionsRow user={user} contract={contract} bets={bets} />
<ContractDescription <ContractDescription
className="px-2" className="px-2"
contract={contract} contract={contract}

View File

@ -0,0 +1,58 @@
import clsx from 'clsx'
import { ShareIcon } from '@heroicons/react/outline'
import { Row } from '../layout/row'
import { Contract } from 'web/lib/firebase/contracts'
import { useState } from 'react'
import { Button } from 'web/components/button'
import { User } from 'common/user'
import { ShareModal } from './share-modal'
import { FollowMarketButton } from 'web/components/follow-market-button'
import { LikeMarketButton } from 'web/components/contract/like-market-button'
import { ContractInfoDialog } from 'web/components/contract/contract-info-dialog'
import { Bet } from 'common/bet'
import { Col } from 'web/components/layout/col'
export function ExtraContractActionsRow(props: {
contract: Contract
bets: Bet[]
user: User | undefined | null
}) {
const { user, contract, bets } = props
const [isShareOpen, setShareOpen] = useState(false)
return (
<Row className={'mt-0.5 justify-around sm:mt-2 lg:justify-start'}>
<Button
size="lg"
color="gray-white"
className={'flex'}
onClick={() => {
setShareOpen(true)
}}
>
<Col className={'items-center sm:flex-row'}>
<ShareIcon
className={clsx('h-[24px] w-5 sm:mr-2')}
aria-hidden="true"
/>
<span>Share</span>
</Col>
<ShareModal
isOpen={isShareOpen}
setOpen={setShareOpen}
contract={contract}
user={user}
/>
</Button>
<FollowMarketButton contract={contract} user={user} />
<LikeMarketButton contract={contract} user={user} />
<Col className={'justify-center md:hidden'}>
<ContractInfoDialog contract={contract} bets={bets} />
</Col>
</Row>
)
}

View File

@ -6,10 +6,11 @@ import { User } from 'common/user'
import { useUserLikes } from 'web/hooks/use-likes' import { useUserLikes } from 'web/hooks/use-likes'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { formatMoney } from 'common/util/format' import { formatMoney } from 'common/util/format'
import { likeContract, unLikeContract } from 'web/lib/firebase/likes' import { likeContract } from 'web/lib/firebase/likes'
import { LIKE_TIP_AMOUNT } from 'common/like' import { LIKE_TIP_AMOUNT } from 'common/like'
import clsx from 'clsx' import clsx from 'clsx'
import { Row } from 'web/components/layout/row' import { Col } from 'web/components/layout/col'
import { firebaseLogin } from 'web/lib/firebase/users'
export function LikeMarketButton(props: { export function LikeMarketButton(props: {
contract: Contract contract: Contract
@ -18,16 +19,12 @@ export function LikeMarketButton(props: {
const { contract, user } = props const { contract, user } = props
const likes = useUserLikes(user?.id) const likes = useUserLikes(user?.id)
const likedContractIds = likes const userLikedContractIds = likes
?.filter((l) => l.type === 'contract') ?.filter((l) => l.type === 'contract')
.map((l) => l.id) .map((l) => l.id)
if (!user) return <div />
const onLike = async () => { const onLike = async () => {
if (likedContractIds?.includes(contract.id)) { if (!user) return firebaseLogin()
await unLikeContract(user.id, contract.id)
return
}
await likeContract(user, contract) await likeContract(user, contract)
toast(`You tipped ${contract.creatorName} ${formatMoney(LIKE_TIP_AMOUNT)}!`) toast(`You tipped ${contract.creatorName} ${formatMoney(LIKE_TIP_AMOUNT)}!`)
} }
@ -39,18 +36,19 @@ export function LikeMarketButton(props: {
color={'gray-white'} color={'gray-white'}
onClick={onLike} onClick={onLike}
> >
<Row className={'gap-0 sm:gap-2'}> <Col className={'gap-0 sm:flex-row sm:gap-x-2'}>
<HeartIcon <HeartIcon
className={clsx( className={clsx(
'h-6 w-6', 'h-6 w-6',
likedContractIds?.includes(contract.id) || user &&
(!likes && contract.likedByUserIds?.includes(user.id)) (userLikedContractIds?.includes(contract.id) ||
(!likes && contract.likedByUserIds?.includes(user.id)))
? 'fill-red-500 text-red-500' ? 'fill-red-500 text-red-500'
: '' : ''
)} )}
/> />
<span className={'hidden sm:block'}>Tip</span> <span>Tip</span>
</Row> </Col>
</Button> </Button>
) )
} }

View File

@ -12,12 +12,15 @@ import { TweetButton } from '../tweet-button'
import { DuplicateContractButton } from '../copy-contract-button' import { DuplicateContractButton } from '../copy-contract-button'
import { Button } from '../button' import { Button } from '../button'
import { copyToClipboard } from 'web/lib/util/copy' import { copyToClipboard } from 'web/lib/util/copy'
import { track } from 'web/lib/service/analytics' import { track, withTracking } from 'web/lib/service/analytics'
import { ENV_CONFIG } from 'common/envs/constants' import { ENV_CONFIG } from 'common/envs/constants'
import { User } from 'common/user' import { User } from 'common/user'
import { SiteLink } from '../site-link' import { SiteLink } from '../site-link'
import { formatMoney } from 'common/util/format' import { formatMoney } from 'common/util/format'
import { REFERRAL_AMOUNT } from 'common/economy' import { REFERRAL_AMOUNT } from 'common/economy'
import { CreateChallengeModal } from 'web/components/challenges/create-challenge-modal'
import { useState } from 'react'
import { CHALLENGES_ENABLED } from 'common/challenge'
export function ShareModal(props: { export function ShareModal(props: {
contract: Contract contract: Contract
@ -26,8 +29,13 @@ export function ShareModal(props: {
setOpen: (open: boolean) => void setOpen: (open: boolean) => void
}) { }) {
const { contract, user, isOpen, setOpen } = props const { contract, user, isOpen, setOpen } = props
const { outcomeType, resolution } = contract
const [openCreateChallengeModal, setOpenCreateChallengeModal] =
useState(false)
const linkIcon = <LinkIcon className="mr-2 h-6 w-6" aria-hidden="true" /> const linkIcon = <LinkIcon className="mr-2 h-6 w-6" aria-hidden="true" />
const showChallenge =
user && outcomeType === 'BINARY' && !resolution && CHALLENGES_ENABLED
const shareUrl = `https://${ENV_CONFIG.domain}${contractPath(contract)}${ const shareUrl = `https://${ENV_CONFIG.domain}${contractPath(contract)}${
user?.username && contract.creatorUsername !== user?.username user?.username && contract.creatorUsername !== user?.username
@ -46,7 +54,6 @@ export function ShareModal(props: {
</SiteLink>{' '} </SiteLink>{' '}
if a new user signs up using the link! if a new user signs up using the link!
</p> </p>
<Button <Button
size="2xl" size="2xl"
color="gradient" color="gradient"
@ -61,8 +68,31 @@ export function ShareModal(props: {
> >
{linkIcon} Copy link {linkIcon} Copy link
</Button> </Button>
{showChallenge && (
<Row className="z-0 justify-start gap-4 self-center"> <Button
size="lg"
color="gray-white"
className={'mb-2 flex max-w-xs self-center'}
onClick={withTracking(
() => setOpenCreateChallengeModal(true),
'click challenge button'
)}
>
<span> Challenge a friend</span>
<CreateChallengeModal
isOpen={openCreateChallengeModal}
setOpen={(open) => {
if (!open) {
setOpenCreateChallengeModal(false)
setOpen(false)
} else setOpenCreateChallengeModal(open)
}}
user={user}
contract={contract}
/>
</Button>
)}
<Row className="z-0 flex-wrap justify-center gap-4 self-center">
<TweetButton <TweetButton
className="self-start" className="self-start"
tweetText={getTweetText(contract, shareUrl)} tweetText={getTweetText(contract, shareUrl)}

View File

@ -1,73 +0,0 @@
import clsx from 'clsx'
import { ShareIcon } from '@heroicons/react/outline'
import { Row } from '../layout/row'
import { Contract } from 'web/lib/firebase/contracts'
import { useState } from 'react'
import { Button } from 'web/components/button'
import { CreateChallengeModal } from '../challenges/create-challenge-modal'
import { User } from 'common/user'
import { CHALLENGES_ENABLED } from 'common/challenge'
import { ShareModal } from './share-modal'
import { withTracking } from 'web/lib/service/analytics'
import { FollowMarketButton } from 'web/components/follow-market-button'
import { LikeMarketButton } from 'web/components/contract/like-market-button'
export function ShareRow(props: {
contract: Contract
user: User | undefined | null
}) {
const { user, contract } = props
const { outcomeType, resolution } = contract
const showChallenge =
user && outcomeType === 'BINARY' && !resolution && CHALLENGES_ENABLED
const [isOpen, setIsOpen] = useState(false)
const [isShareOpen, setShareOpen] = useState(false)
return (
<Row className="mt-0.5 sm:mt-2">
<Button
size="lg"
color="gray-white"
className={'flex'}
onClick={() => {
setShareOpen(true)
}}
>
<ShareIcon className={clsx('mr-2 h-[24px] w-5')} aria-hidden="true" />
Share
<ShareModal
isOpen={isShareOpen}
setOpen={setShareOpen}
contract={contract}
user={user}
/>
</Button>
{showChallenge && (
<Button
size="lg"
color="gray-white"
onClick={withTracking(
() => setIsOpen(true),
'click challenge button'
)}
>
Challenge
<CreateChallengeModal
isOpen={isOpen}
setOpen={setIsOpen}
user={user}
contract={contract}
/>
</Button>
)}
<FollowMarketButton contract={contract} user={user} />
<div className={'hidden sm:block'}>
<LikeMarketButton contract={contract} user={user} />
</div>
</Row>
)
}

View File

@ -13,7 +13,7 @@ import { firebaseLogin, updateUser } from 'web/lib/firebase/users'
import { track } from 'web/lib/service/analytics' import { track } from 'web/lib/service/analytics'
import { FollowMarketModal } from 'web/components/contract/follow-market-modal' import { FollowMarketModal } from 'web/components/contract/follow-market-modal'
import { useState } from 'react' import { useState } from 'react'
import { Row } from 'web/components/layout/row' import { Col } from 'web/components/layout/col'
export const FollowMarketButton = (props: { export const FollowMarketButton = (props: {
contract: Contract contract: Contract
@ -55,15 +55,15 @@ export const FollowMarketButton = (props: {
}} }}
> >
{followers?.includes(user?.id ?? 'nope') ? ( {followers?.includes(user?.id ?? 'nope') ? (
<Row className={'gap-2'}> <Col className={'items-center gap-x-2 sm:flex-row'}>
<EyeOffIcon className={clsx('h-6 w-6')} aria-hidden="true" /> <EyeOffIcon className={clsx('h-6 w-6')} aria-hidden="true" />
Unwatch Unwatch
</Row> </Col>
) : ( ) : (
<Row className={'gap-2'}> <Col className={'items-center gap-x-2 sm:flex-row'}>
<EyeIcon className={clsx('h-6 w-6')} aria-hidden="true" /> <EyeIcon className={clsx('h-6 w-6')} aria-hidden="true" />
Watch Watch
</Row> </Col>
)} )}
<FollowMarketModal <FollowMarketModal
open={open} open={open}

View File

@ -11,7 +11,7 @@ function shortenName(name: string) {
const firstName = name.split(' ')[0] const firstName = name.split(' ')[0]
const maxLength = 10 const maxLength = 10
const shortName = const shortName =
firstName.length >= 3 firstName.length >= 4
? firstName.length < maxLength ? firstName.length < maxLength
? firstName ? firstName
: firstName.substring(0, maxLength - 3) + '...' : firstName.substring(0, maxLength - 3) + '...'

View File

@ -107,9 +107,8 @@ export function ContractEmbed(props: { contract: Contract; bets: Bet[] }) {
<Row className="items-center justify-between gap-4 px-2"> <Row className="items-center justify-between gap-4 px-2">
<ContractDetails <ContractDetails
contract={contract} contract={contract}
bets={bets}
isCreator={false}
user={null} user={null}
bets={bets}
disabled disabled
/> />