manifold/web/components/tipper.tsx

97 lines
2.7 KiB
TypeScript
Raw Normal View History

import { useEffect, useRef, useState } from 'react'
2022-10-02 17:55:58 +00:00
import toast from 'react-hot-toast'
import { debounce } from 'lodash'
import { Comment } from 'common/comment'
import { User } from 'common/user'
import { useUser } from 'web/hooks/use-user'
import { transact } from 'web/lib/firebase/api'
2022-06-21 15:36:44 +00:00
import { track } from 'web/lib/service/analytics'
import { TipButton } from './contract/tip-button'
import { Row } from './layout/row'
2022-10-01 20:57:47 +00:00
import { LIKE_TIP_AMOUNT } from 'common/like'
2022-10-02 17:55:58 +00:00
import { formatMoney } from 'common/util/format'
2022-09-21 22:25:54 +00:00
export function Tipper(prop: {
comment: Comment
myTip: number
totalTip: number
}) {
const { comment, myTip, totalTip } = prop
const me = useUser()
const [localTip, setLocalTip] = useState(myTip)
// listen for user being set
const initialized = useRef(false)
useEffect(() => {
if (myTip && !initialized.current) {
setLocalTip(myTip)
initialized.current = true
}
}, [myTip])
const total = totalTip - myTip + localTip
2022-10-01 21:10:17 +00:00
// declare debounced function only on first render
const [saveTip] = useState(() =>
debounce(async (user: User, comment: Comment, change: number) => {
if (change === 0) {
return
}
const contractId =
comment.commentType === 'contract' ? comment.contractId : undefined
const groupId =
comment.commentType === 'group' ? comment.groupId : undefined
const postId = comment.commentType === 'post' ? comment.postId : undefined
await transact({
amount: change,
fromId: user.id,
fromType: 'USER',
toId: comment.userId,
toType: 'USER',
token: 'M$',
category: 'TIP',
data: { commentId: comment.id, contractId, groupId, postId },
description: `${user.name} tipped M$ ${change} to ${comment.userName} for a comment`,
})
2022-06-21 15:36:44 +00:00
track('send comment tip', {
commentId: comment.id,
contractId,
groupId,
postId,
2022-06-21 15:36:44 +00:00
amount: change,
fromId: user.id,
toId: comment.userId,
})
}, 1500)
)
// instant save on unrender
useEffect(() => () => void saveTip.flush(), [saveTip])
const addTip = (delta: number) => {
setLocalTip(localTip + delta)
me && saveTip(me, comment, localTip - myTip + delta)
2022-10-02 17:55:58 +00:00
toast(`You tipped ${comment.userName} ${formatMoney(LIKE_TIP_AMOUNT)}!`)
}
2022-10-01 21:22:19 +00:00
const canUp =
me && comment.userId !== me.id && me.balance >= localTip + LIKE_TIP_AMOUNT
return (
<Row className="items-center gap-0.5">
<TipButton
2022-10-01 20:57:47 +00:00
tipAmount={LIKE_TIP_AMOUNT}
2022-10-01 21:10:17 +00:00
totalTipped={total}
2022-10-01 20:57:47 +00:00
onClick={() => addTip(+LIKE_TIP_AMOUNT)}
userTipped={localTip > 0}
disabled={!canUp}
isCompact
2022-09-21 22:25:54 +00:00
/>
</Row>
)
}