From 353648566f523cbe9dee10662405451c1bb6f2ee Mon Sep 17 00:00:00 2001 From: Ian Philips Date: Tue, 27 Sep 2022 19:37:04 -0400 Subject: [PATCH] Add notification for bounty award as tip --- functions/src/create-notification.ts | 44 +++++++++++++++++++++++ functions/src/update-comment-bounty.ts | 18 ++++++++-- web/components/award-bounty-button.tsx | 5 ++- web/components/contract/contract-tabs.tsx | 4 +-- 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/functions/src/create-notification.ts b/functions/src/create-notification.ts index 038e0142..9bd73d05 100644 --- a/functions/src/create-notification.ts +++ b/functions/src/create-notification.ts @@ -1046,3 +1046,47 @@ export const createContractResolvedNotifications = async ( ) ) } + +export const createBountyNotification = async ( + fromUser: User, + toUserId: string, + amount: number, + idempotencyKey: string, + contract: Contract, + commentId?: string +) => { + const privateUser = await getPrivateUser(toUserId) + if (!privateUser) return + const { sendToBrowser } = getNotificationDestinationsForUser( + privateUser, + 'tip_received' + ) + if (!sendToBrowser) return + + const slug = commentId + const notificationRef = firestore + .collection(`/users/${toUserId}/notifications`) + .doc(idempotencyKey) + const notification: Notification = { + id: idempotencyKey, + userId: toUserId, + reason: 'tip_received', + createdTime: Date.now(), + isSeen: false, + sourceId: commentId ? commentId : contract.id, + sourceType: 'tip', + sourceUpdateType: 'created', + sourceUserName: fromUser.name, + sourceUserUsername: fromUser.username, + sourceUserAvatarUrl: fromUser.avatarUrl, + sourceText: amount.toString(), + sourceContractCreatorUsername: contract.creatorUsername, + sourceContractTitle: contract.question, + sourceContractSlug: contract.slug, + sourceSlug: slug, + sourceTitle: contract.question, + } + return await notificationRef.set(removeUndefinedProps(notification)) + + // maybe TODO: send email notification to comment creator +} diff --git a/functions/src/update-comment-bounty.ts b/functions/src/update-comment-bounty.ts index 7b193079..a609ca00 100644 --- a/functions/src/update-comment-bounty.ts +++ b/functions/src/update-comment-bounty.ts @@ -13,6 +13,7 @@ import { isProd } from './utils' import { CommentBountyDepositTxn, CommentBountyWithdrawalTxn } from 'common/txn' import { runTxn } from 'functions/src/transact' import { Comment } from 'common/comment' +import { createBountyNotification } from 'functions/src/create-notification' const bodySchema = z.object({ contractId: z.string(), @@ -78,7 +79,7 @@ export const awardcommentbounty = newEndpoint({}, async (req, auth) => { if (!isFinite(amount)) throw new APIError(400, 'Invalid amount') // run as transaction to prevent race conditions - return await firestore.runTransaction(async (transaction) => { + const res = await firestore.runTransaction(async (transaction) => { const userDoc = firestore.doc(`users/${auth.uid}`) const userSnap = await transaction.get(userDoc) if (!userSnap.exists) throw new APIError(400, 'User not found') @@ -138,8 +139,21 @@ export const awardcommentbounty = newEndpoint({}, async (req, auth) => { }) ) - return result + return { ...result, comment, contract, user } }) + if (res.txn?.id) { + const { comment, contract, user } = res + await createBountyNotification( + user, + comment.userId, + amount, + res.txn.id, + contract, + comment.id + ) + } + + return res }) const firestore = admin.firestore() diff --git a/web/components/award-bounty-button.tsx b/web/components/award-bounty-button.tsx index f746f594..865678c7 100644 --- a/web/components/award-bounty-button.tsx +++ b/web/components/award-bounty-button.tsx @@ -7,14 +7,13 @@ import { Row } from './layout/row' import { Contract } from 'common/contract' import { TextButton } from 'web/components/text-button' import { COMMENT_BOUNTY_AMOUNT } from 'common/economy' +import { formatMoney } from 'common/util/format' export function AwardBountyButton(prop: { comment: ContractComment contract: Contract }) { const { comment, contract } = prop - const { bountiesAwarded } = comment - const amountAwarded = bountiesAwarded ?? 0 const me = useUser() @@ -39,7 +38,7 @@ export function AwardBountyButton(prop: { return ( - Award + Award {formatMoney(COMMENT_BOUNTY_AMOUNT)} ) diff --git a/web/components/contract/contract-tabs.tsx b/web/components/contract/contract-tabs.tsx index f9462e41..39585b91 100644 --- a/web/components/contract/contract-tabs.tsx +++ b/web/components/contract/contract-tabs.tsx @@ -24,9 +24,9 @@ import { HOUSE_LIQUIDITY_PROVIDER_ID, } from 'common/antes' import { useIsMobile } from 'web/hooks/use-is-mobile' -import { formatMoney } from 'common/lib/util/format' +import { formatMoney } from 'common/util/format' import { Button } from 'web/components/button' -import { MINUTE_MS } from 'common/lib/util/time' +import { MINUTE_MS } from 'common/util/time' export function ContractTabs(props: { contract: Contract; bets: Bet[] }) { const { contract, bets } = props