Add notification for bounty award as tip
This commit is contained in:
		
							parent
							
								
									b8f9f791b9
								
							
						
					
					
						commit
						353648566f
					
				|  | @ -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
 | ||||
| } | ||||
|  |  | |||
|  | @ -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() | ||||
|  |  | |||
|  | @ -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 ( | ||||
|     <Row className={clsx('-ml-2 items-center gap-0.5', !canUp ? '-ml-6' : '')}> | ||||
|       <TextButton className={'font-bold'} onClick={submit}> | ||||
|         Award | ||||
|         Award {formatMoney(COMMENT_BOUNTY_AMOUNT)} | ||||
|       </TextButton> | ||||
|     </Row> | ||||
|   ) | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user