2022-10-14 06:47:51 +00:00
import { useState } from 'react'
2022-10-02 17:55:58 +00:00
import toast from 'react-hot-toast'
2022-10-01 20:51:08 +00:00
2022-06-18 03:28:16 +00:00
import { Comment } from 'common/comment'
import { User } from 'common/user'
import { useUser } from 'web/hooks/use-user'
2022-07-10 22:03:15 +00:00
import { transact } from 'web/lib/firebase/api'
2022-06-21 15:36:44 +00:00
import { track } from 'web/lib/service/analytics'
2022-10-01 20:51:08 +00:00
import { TipButton } from './contract/tip-button'
2022-06-18 03:28:16 +00:00
import { Row } from './layout/row'
2022-10-14 06:47:51 +00:00
import { LIKE_TIP_AMOUNT , TIP_UNDO_DURATION } from 'common/like'
2022-10-02 17:55:58 +00:00
import { formatMoney } from 'common/util/format'
2022-10-14 06:47:51 +00:00
import { Button } from './button'
import clsx from 'clsx'
2022-09-21 22:25:54 +00:00
2022-10-05 06:16:56 +00:00
export function Tipper ( prop : {
comment : Comment
myTip : number
totalTip : number
} ) {
const { comment , myTip , totalTip } = prop
2022-06-18 03:28:16 +00:00
2022-10-14 06:47:51 +00:00
// This is a temporary tipping amount before it actually gets confirmed. This is so tha we dont accidentally tip more than you have
const [ tempTip , setTempTip ] = useState ( 0 )
2022-06-18 03:28:16 +00:00
2022-10-14 06:47:51 +00:00
const me = useUser ( )
2022-10-01 21:10:17 +00:00
2022-10-14 06:47:51 +00:00
const [ saveTip ] = useState (
( ) = > async ( user : User , comment : Comment , change : number ) = > {
2022-06-18 03:28:16 +00:00
if ( change === 0 ) {
return
}
2022-08-19 08:06:40 +00:00
const contractId =
comment . commentType === 'contract' ? comment.contractId : undefined
const groupId =
comment . commentType === 'group' ? comment.groupId : undefined
2022-09-07 22:09:20 +00:00
const postId = comment . commentType === 'post' ? comment.postId : undefined
2022-06-18 03:28:16 +00:00
await transact ( {
amount : change ,
fromId : user.id ,
fromType : 'USER' ,
toId : comment.userId ,
toType : 'USER' ,
token : 'M$' ,
category : 'TIP' ,
2022-09-07 22:09:20 +00:00
data : { commentId : comment.id , contractId , groupId , postId } ,
2022-06-18 03:28:16 +00:00
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 ,
2022-08-19 08:06:40 +00:00
contractId ,
groupId ,
2022-09-07 22:09:20 +00:00
postId ,
2022-06-21 15:36:44 +00:00
amount : change ,
fromId : user.id ,
toId : comment.userId ,
} )
2022-10-14 06:47:51 +00:00
}
2022-06-18 03:28:16 +00:00
)
2022-08-10 06:05:56 +00:00
const addTip = ( delta : number ) = > {
2022-10-14 07:20:32 +00:00
setTempTip ( ( tempTip ) = > tempTip + delta )
2022-10-14 06:47:51 +00:00
const timeoutId = setTimeout ( ( ) = > {
me &&
saveTip ( me , comment , delta )
2022-10-14 07:20:32 +00:00
. then ( ( ) = > setTempTip ( ( tempTip ) = > tempTip - delta ) )
2022-10-14 06:47:51 +00:00
. catch ( ( e ) = > console . error ( e ) )
} , TIP_UNDO_DURATION + 1000 )
toast . custom (
( ) = > (
< TipToast
userName = { comment . userName }
onUndoClick = { ( ) = > {
clearTimeout ( timeoutId )
2022-10-14 07:20:32 +00:00
setTempTip ( ( tempTip ) = > tempTip - delta )
2022-10-14 06:47:51 +00:00
} }
/ >
) ,
{ duration : TIP_UNDO_DURATION }
)
2022-06-18 03:28:16 +00:00
}
2022-10-01 21:22:19 +00:00
const canUp =
2022-10-14 06:47:51 +00:00
me && comment . userId !== me . id && me . balance - tempTip >= LIKE_TIP_AMOUNT
2022-10-01 20:51:08 +00:00
2022-06-18 03:28:16 +00:00
return (
< Row className = "items-center gap-0.5" >
2022-10-01 20:51:08 +00:00
< TipButton
2022-10-01 20:57:47 +00:00
tipAmount = { LIKE_TIP_AMOUNT }
2022-10-14 06:47:51 +00:00
totalTipped = { totalTip }
2022-10-01 20:57:47 +00:00
onClick = { ( ) = > addTip ( + LIKE_TIP_AMOUNT ) }
2022-10-14 06:47:51 +00:00
userTipped = { tempTip > 0 || myTip > 0 }
2022-10-01 20:51:08 +00:00
disabled = { ! canUp }
isCompact
2022-09-21 22:25:54 +00:00
/ >
2022-06-18 03:28:16 +00:00
< / Row >
)
}
2022-10-14 06:47:51 +00:00
export function TipToast ( props : { userName : string ; onUndoClick : ( ) = > void } ) {
const { userName , onUndoClick } = props
const [ cancelled , setCancelled ] = useState ( false )
// There is a strange bug with toast where sometimes if you interact with one popup, the others will not dissappear at the right time, overriding it for now with this
const [ timedOut , setTimedOut ] = useState ( false )
setTimeout ( ( ) = > {
setTimedOut ( true )
} , TIP_UNDO_DURATION )
if ( timedOut ) {
return < > < / >
}
return (
< div className = "relative overflow-hidden rounded-lg bg-white drop-shadow-md" >
< div
className = { clsx (
'animate-progress-loading absolute bottom-0 z-10 h-1 w-full bg-indigo-600' ,
cancelled ? 'hidden' : ''
) }
/ >
< Row className = "text-greyscale-6 items-center gap-4 px-4 py-2 text-sm" >
< div className = { clsx ( cancelled ? 'hidden' : 'inline' ) } >
Tipping { userName } { formatMoney ( LIKE_TIP_AMOUNT ) } . . .
< / div >
< div className = { clsx ( 'py-1' , cancelled ? 'inline' : 'hidden' ) } >
Cancelled tipping
< / div >
< Button
className = { clsx ( cancelled ? 'hidden' : 'inline' ) }
size = "xs"
color = "gray-outline"
onClick = { ( ) = > {
onUndoClick ( )
setCancelled ( true )
} }
disabled = { cancelled }
>
Cancel
< / Button >
< / Row >
< / div >
)
}