diff --git a/web/components/contract/contract-overview.tsx b/web/components/contract/contract-overview.tsx
index 43536711..c3d93242 100644
--- a/web/components/contract/contract-overview.tsx
+++ b/web/components/contract/contract-overview.tsx
@@ -76,28 +76,34 @@ export const ContractOverview = (props: {
{tradingAllowed(contract) && (
-
-
- {!user && (
-
- (with play money!)
-
- )}
-
+
+
+
+
+ {!user && (
+
+ (with play money!)
+
+ )}
+
+
)}
) : isPseudoNumeric ? (
{tradingAllowed(contract) && (
-
-
- {!user && (
-
- (with play money!)
-
- )}
-
+
+
+
+
+ {!user && (
+
+ (with play money!)
+
+ )}
+
+
)}
) : (
diff --git a/web/components/contract/like-market-button.tsx b/web/components/contract/like-market-button.tsx
index ca4cf204..080f7c77 100644
--- a/web/components/contract/like-market-button.tsx
+++ b/web/components/contract/like-market-button.tsx
@@ -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)}!`)
}
diff --git a/web/components/profile/user-likes-button.tsx b/web/components/profile/user-likes-button.tsx
new file mode 100644
index 00000000..e3d171fc
--- /dev/null
+++ b/web/components/profile/user-likes-button.tsx
@@ -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 (
+ <>
+ setIsOpen(true)}>
+ {likedContracts?.length ?? ''}{' '}
+ Likes
+
+
+
+ Liked Markets
+
+ {likedContracts?.map((likedContract) => (
+
+
+ {likedContract.question}
+
+ async () => {
+ await unLikeContract(user.id, likedContract.id)
+ }}
+ />
+
+ ))}
+
+
+
+ >
+ )
+}
diff --git a/web/components/user-page.tsx b/web/components/user-page.tsx
index 5da3ebca..8312f16e 100644
--- a/web/components/user-page.tsx
+++ b/web/components/user-page.tsx
@@ -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 }) {
+
),
},
diff --git a/web/hooks/use-likes.ts b/web/hooks/use-likes.ts
index 755001fa..56230c66 100644
--- a/web/hooks/use-likes.ts
+++ b/web/hooks/use-likes.ts
@@ -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()
@@ -11,3 +14,22 @@ export const useUserLikes = (userId: string | undefined) => {
return contractIds
}
+export const useUserLikedContracts = (userId: string | undefined) => {
+ const [contractIds, setContractIds] = useState()
+ const [contracts, setContracts] = useState()
+
+ 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
+}
diff --git a/web/lib/firebase/likes.ts b/web/lib/firebase/likes.ts
new file mode 100644
index 00000000..62620e2a
--- /dev/null
+++ b/web/lib/firebase/likes.ts
@@ -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)
+}