wip liked contracts list
This commit is contained in:
parent
559793d23b
commit
2e502a774c
|
@ -76,6 +76,8 @@ export const ContractOverview = (props: {
|
|||
<Row className="items-center justify-between gap-4 xl:hidden">
|
||||
<BinaryResolutionOrChance contract={contract} />
|
||||
{tradingAllowed(contract) && (
|
||||
<Row>
|
||||
<LikeMarketButton contract={contract} user={user} />
|
||||
<Col>
|
||||
<BetButton contract={contract as CPMMBinaryContract} />
|
||||
{!user && (
|
||||
|
@ -84,12 +86,15 @@ export const ContractOverview = (props: {
|
|||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Row>
|
||||
) : isPseudoNumeric ? (
|
||||
<Row className="items-center justify-between gap-4 xl:hidden">
|
||||
<PseudoNumericResolutionOrExpectation contract={contract} />
|
||||
{tradingAllowed(contract) && (
|
||||
<Row>
|
||||
<LikeMarketButton contract={contract} user={user} />
|
||||
<Col>
|
||||
<BetButton contract={contract} />
|
||||
{!user && (
|
||||
|
@ -98,6 +103,7 @@ export const ContractOverview = (props: {
|
|||
</div>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
)}
|
||||
</Row>
|
||||
) : (
|
||||
|
|
|
@ -3,20 +3,14 @@ import { Button } from 'web/components/button'
|
|||
import React from 'react'
|
||||
import { Contract } from 'common/contract'
|
||||
import { User } from 'common/user'
|
||||
import { collection, deleteDoc, doc, setDoc } from 'firebase/firestore'
|
||||
import { removeUndefinedProps } from 'common/util/object'
|
||||
import { track } from '@amplitude/analytics-browser'
|
||||
import { db } from 'web/lib/firebase/init'
|
||||
import { Like } from 'common/like'
|
||||
import { useUserLikes } from 'web/hooks/use-likes'
|
||||
import { transact } from 'web/lib/firebase/api'
|
||||
import toast from 'react-hot-toast'
|
||||
import { formatMoney } from 'common/util/format'
|
||||
|
||||
function getLikesCollection(userId: string) {
|
||||
return collection(db, 'users', userId, 'likes')
|
||||
}
|
||||
const LIKE_TIP_AMOUNT = 5
|
||||
import {
|
||||
LIKE_TIP_AMOUNT,
|
||||
likeContract,
|
||||
unLikeContract,
|
||||
} from 'web/lib/firebase/likes'
|
||||
|
||||
export function LikeMarketButton(props: {
|
||||
contract: Contract
|
||||
|
@ -30,48 +24,11 @@ export function LikeMarketButton(props: {
|
|||
|
||||
const onLike = async () => {
|
||||
if (likedContractIds?.includes(contract.id)) {
|
||||
const ref = doc(
|
||||
getLikesCollection(user.id),
|
||||
likes?.find((l) => l.contractId === contract.id)?.id
|
||||
)
|
||||
await deleteDoc(ref)
|
||||
await unLikeContract(user.id, contract.id)
|
||||
toast(`You removed this market from your likes`)
|
||||
|
||||
return
|
||||
}
|
||||
if (user.balance < LIKE_TIP_AMOUNT) {
|
||||
toast('You do not have enough M$ to like this market!')
|
||||
return
|
||||
}
|
||||
let result: any = {}
|
||||
if (LIKE_TIP_AMOUNT > 0) {
|
||||
result = await transact({
|
||||
amount: LIKE_TIP_AMOUNT,
|
||||
fromId: user.id,
|
||||
fromType: 'USER',
|
||||
toId: contract.creatorId,
|
||||
toType: 'USER',
|
||||
token: 'M$',
|
||||
category: 'TIP',
|
||||
data: { contractId: contract.id },
|
||||
description: `${user.name} liked contract ${contract.id} for M$ ${LIKE_TIP_AMOUNT} to ${contract.creatorId} `,
|
||||
})
|
||||
console.log('result', result)
|
||||
}
|
||||
// create new like in db under users collection
|
||||
const ref = doc(getLikesCollection(user.id))
|
||||
// contract slug and question are set via trigger
|
||||
const like = removeUndefinedProps({
|
||||
id: ref.id,
|
||||
userId: user.id,
|
||||
createdTime: Date.now(),
|
||||
contractId: contract.id,
|
||||
tipTxnId: result.txn.id,
|
||||
} as Like)
|
||||
track('like', {
|
||||
contractId: contract.id,
|
||||
})
|
||||
await setDoc(ref, like)
|
||||
await likeContract(user, contract)
|
||||
toast(`You tipped ${contract.creatorName} ${formatMoney(LIKE_TIP_AMOUNT)}!`)
|
||||
}
|
||||
|
||||
|
|
50
web/components/profile/user-likes-button.tsx
Normal file
50
web/components/profile/user-likes-button.tsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
import { User } from 'common/lib/user'
|
||||
import { useState } from 'react'
|
||||
import { TextButton } from 'web/components/text-button'
|
||||
import { Modal } from 'web/components/layout/modal'
|
||||
import { Col } from 'web/components/layout/col'
|
||||
import { useUserLikedContracts } from 'web/hooks/use-likes'
|
||||
import { SiteLink } from 'web/components/site-link'
|
||||
import { Row } from 'web/components/layout/row'
|
||||
import { XIcon } from '@heroicons/react/outline'
|
||||
import { unLikeContract } from 'web/lib/firebase/likes'
|
||||
import { contractPath } from 'web/lib/firebase/contracts'
|
||||
|
||||
export function UserLikesButton(props: { user: User }) {
|
||||
const { user } = props
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
const likedContracts = useUserLikedContracts(user.id)
|
||||
|
||||
return (
|
||||
<>
|
||||
<TextButton onClick={() => setIsOpen(true)}>
|
||||
<span className="font-semibold">{likedContracts?.length ?? ''}</span>{' '}
|
||||
Likes
|
||||
</TextButton>
|
||||
<Modal open={isOpen} setOpen={setIsOpen}>
|
||||
<Col className="rounded bg-white p-6">
|
||||
<span className={'mb-4 text-xl'}>Liked Markets</span>
|
||||
<Col className={'gap-4'}>
|
||||
{likedContracts?.map((likedContract) => (
|
||||
<Row key={likedContract.id} className={'justify-between gap-2'}>
|
||||
<SiteLink
|
||||
href={contractPath(likedContract)}
|
||||
className={'truncate text-indigo-700'}
|
||||
>
|
||||
{likedContract.question}
|
||||
</SiteLink>
|
||||
<XIcon
|
||||
className="ml-2 h-5 w-5 cursor-pointer"
|
||||
onClick={() => async () => {
|
||||
await unLikeContract(user.id, likedContract.id)
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
))}
|
||||
</Col>
|
||||
</Col>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -31,6 +31,7 @@ import { ENV_CONFIG } from 'common/envs/constants'
|
|||
import { BettingStreakModal } from 'web/components/profile/betting-streak-modal'
|
||||
import { REFERRAL_AMOUNT } from 'common/economy'
|
||||
import { LoansModal } from './profile/loans-modal'
|
||||
import { UserLikesButton } from 'web/components/profile/user-likes-button'
|
||||
|
||||
export function UserPage(props: { user: User }) {
|
||||
const { user } = props
|
||||
|
@ -273,6 +274,7 @@ export function UserPage(props: { user: User }) {
|
|||
<FollowersButton user={user} />
|
||||
<ReferralsButton user={user} />
|
||||
<GroupsButton user={user} />
|
||||
<UserLikesButton user={user} />
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import { listenForLikes } from 'web/lib/firebase/users'
|
||||
import { Like } from 'common/like'
|
||||
import { Contract } from 'common/lib/contract'
|
||||
import { getContractFromId } from 'web/lib/firebase/contracts'
|
||||
import { filterDefined } from 'common/util/array'
|
||||
|
||||
export const useUserLikes = (userId: string | undefined) => {
|
||||
const [contractIds, setContractIds] = useState<Like[] | undefined>()
|
||||
|
@ -11,3 +14,22 @@ export const useUserLikes = (userId: string | undefined) => {
|
|||
|
||||
return contractIds
|
||||
}
|
||||
export const useUserLikedContracts = (userId: string | undefined) => {
|
||||
const [contractIds, setContractIds] = useState<Like[] | undefined>()
|
||||
const [contracts, setContracts] = useState<Contract[] | undefined>()
|
||||
|
||||
useEffect(() => {
|
||||
if (userId) return listenForLikes(userId, setContractIds)
|
||||
}, [userId])
|
||||
|
||||
useEffect(() => {
|
||||
if (contractIds)
|
||||
Promise.all(
|
||||
contractIds.map(async (like) => {
|
||||
return await getContractFromId(like.contractId)
|
||||
})
|
||||
).then((contracts) => setContracts(filterDefined(contracts)))
|
||||
}, [contractIds])
|
||||
|
||||
return contracts
|
||||
}
|
||||
|
|
67
web/lib/firebase/likes.ts
Normal file
67
web/lib/firebase/likes.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import {
|
||||
collection,
|
||||
deleteDoc,
|
||||
doc,
|
||||
query,
|
||||
setDoc,
|
||||
where,
|
||||
} from 'firebase/firestore'
|
||||
import { db } from 'web/lib/firebase/init'
|
||||
import toast from 'react-hot-toast'
|
||||
import { transact } from 'web/lib/firebase/api'
|
||||
import { removeUndefinedProps } from 'common/lib/util/object'
|
||||
import { Like } from 'common/lib/like'
|
||||
import { track } from '@amplitude/analytics-browser'
|
||||
import { User } from 'common/user'
|
||||
import { Contract } from 'common/lib/contract'
|
||||
|
||||
export const LIKE_TIP_AMOUNT = 5
|
||||
|
||||
function getLikesCollection(userId: string) {
|
||||
return collection(db, 'users', userId, 'likes')
|
||||
}
|
||||
|
||||
export const unLikeContract = async (userId: string, contractId: string) => {
|
||||
const ref = await query(
|
||||
getLikesCollection(userId),
|
||||
where('contractId', '==', contractId)
|
||||
)
|
||||
const snapshot = await ref.get()
|
||||
return await deleteDoc(ref)
|
||||
}
|
||||
|
||||
export const likeContract = async (user: User, contract: Contract) => {
|
||||
if (user.balance < LIKE_TIP_AMOUNT) {
|
||||
toast('You do not have enough M$ to like this market!')
|
||||
return
|
||||
}
|
||||
let result: any = {}
|
||||
if (LIKE_TIP_AMOUNT > 0) {
|
||||
result = await transact({
|
||||
amount: LIKE_TIP_AMOUNT,
|
||||
fromId: user.id,
|
||||
fromType: 'USER',
|
||||
toId: contract.creatorId,
|
||||
toType: 'USER',
|
||||
token: 'M$',
|
||||
category: 'TIP',
|
||||
data: { contractId: contract.id },
|
||||
description: `${user.name} liked contract ${contract.id} for M$ ${LIKE_TIP_AMOUNT} to ${contract.creatorId} `,
|
||||
})
|
||||
console.log('result', result)
|
||||
}
|
||||
// create new like in db under users collection
|
||||
const ref = doc(getLikesCollection(user.id))
|
||||
// contract slug and question are set via trigger
|
||||
const like = removeUndefinedProps({
|
||||
id: ref.id,
|
||||
userId: user.id,
|
||||
createdTime: Date.now(),
|
||||
contractId: contract.id,
|
||||
tipTxnId: result.txn.id,
|
||||
} as Like)
|
||||
track('like', {
|
||||
contractId: contract.id,
|
||||
})
|
||||
await setDoc(ref, like)
|
||||
}
|
Loading…
Reference in New Issue
Block a user