index.tsx raw
1 import { useStuff } from '@/hooks/useStuff'
2 import { cn } from '@/lib/utils'
3 import { useNostr } from '@/providers/NostrProvider'
4 import { useScreenSize } from '@/providers/ScreenSizeProvider'
5 import stuffStatsService from '@/services/stuff-stats.service'
6 import { Event } from 'nostr-tools'
7 import { useEffect, useState } from 'react'
8 import BookmarkButton from '../BookmarkButton'
9 import LikeButton from './LikeButton'
10 import Likes from './Likes'
11 import ReplyButton from './ReplyButton'
12 import RepostButton from './RepostButton'
13 import SeenOnButton from './SeenOnButton'
14 import TopZaps from './TopZaps'
15 import ZapButton from './ZapButton'
16
17 export default function StuffStats({
18 stuff,
19 className,
20 classNames,
21 fetchIfNotExisting = false,
22 displayTopZapsAndLikes = false,
23 onReplyClick
24 }: {
25 stuff: Event | string
26 className?: string
27 classNames?: {
28 buttonBar?: string
29 }
30 fetchIfNotExisting?: boolean
31 displayTopZapsAndLikes?: boolean
32 onReplyClick?: () => void
33 }) {
34 const { isSmallScreen } = useScreenSize()
35 const { pubkey } = useNostr()
36 const [loading, setLoading] = useState(false)
37 const { event } = useStuff(stuff)
38
39 useEffect(() => {
40 if (!fetchIfNotExisting) return
41 setLoading(true)
42 stuffStatsService.fetchStuffStats(stuff, pubkey).finally(() => setLoading(false))
43 }, [event, fetchIfNotExisting])
44
45 if (isSmallScreen) {
46 return (
47 <div className={cn('select-none', className)} data-stuff-stats>
48 {displayTopZapsAndLikes && (
49 <>
50 <TopZaps stuff={stuff} />
51 <Likes stuff={stuff} />
52 </>
53 )}
54 <div
55 className={cn(
56 'flex justify-between items-center h-5 [&_svg]:size-5',
57 loading ? 'animate-pulse' : '',
58 classNames?.buttonBar
59 )}
60 onClick={(e) => e.stopPropagation()}
61 >
62 <ReplyButton stuff={stuff} onReplyClick={onReplyClick} />
63 <RepostButton stuff={stuff} />
64 <LikeButton stuff={stuff} />
65 <ZapButton stuff={stuff} />
66 <BookmarkButton stuff={stuff} />
67 <SeenOnButton stuff={stuff} />
68 </div>
69 </div>
70 )
71 }
72
73 return (
74 <div className={cn('select-none', className)} data-stuff-stats>
75 {displayTopZapsAndLikes && (
76 <>
77 <TopZaps stuff={stuff} />
78 <Likes stuff={stuff} />
79 </>
80 )}
81 <div className="flex justify-between h-5 [&_svg]:size-4">
82 <div
83 className={cn('flex items-center', loading ? 'animate-pulse' : '')}
84 onClick={(e) => e.stopPropagation()}
85 >
86 <ReplyButton stuff={stuff} onReplyClick={onReplyClick} />
87 <RepostButton stuff={stuff} />
88 <LikeButton stuff={stuff} />
89 <ZapButton stuff={stuff} />
90 </div>
91 <div className="flex items-center" onClick={(e) => e.stopPropagation()}>
92 <BookmarkButton stuff={stuff} />
93 <SeenOnButton stuff={stuff} />
94 </div>
95 </div>
96 </div>
97 )
98 }
99