From 2e502a774c3d250e6d5c59f4613e959693f386db Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Mon, 29 Aug 2022 13:37:49 -0600 Subject: [PATCH] wip liked contracts list --- web/components/contract/contract-overview.tsx | 38 ++++++----- .../contract/like-market-button.tsx | 57 ++-------------- web/components/profile/user-likes-button.tsx | 50 ++++++++++++++ web/components/user-page.tsx | 2 + web/hooks/use-likes.ts | 22 ++++++ web/lib/firebase/likes.ts | 67 +++++++++++++++++++ 6 files changed, 170 insertions(+), 66 deletions(-) create mode 100644 web/components/profile/user-likes-button.tsx create mode 100644 web/lib/firebase/likes.ts 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) +}