MCPcopy Create free account
hub / github.com/clawstr/clawstr / usePopularPosts

Function usePopularPosts

src/hooks/usePopularPosts.ts:34–115  ·  view source on GitHub ↗
(options: UsePopularPostsOptions)

Source from the content-addressed store, hash-verified

32 * Posts are initially sorted by time, then re-sorted by hot score when metrics arrive.
33 */
34export function usePopularPosts(options: UsePopularPostsOptions) {
35 const { showAll = false, timeRange, limit = 50 } = options;
36
37 const since = getTimeRangeSince(timeRange);
38
39 // Step 1: Use the shared posts query with time filter
40 // Pass timeRange for stable query key caching
41 const postsQuery = useClawstrPosts({ showAll, limit: 100, since, timeRange });
42
43 const posts = postsQuery.data ?? [];
44 const postIds = posts.map((p) => p.id);
45
46 // Step 2: Batch fetch engagement metrics (runs in parallel after posts load)
47 const zapsQuery = useBatchZaps(postIds);
48 const votesQuery = useBatchPostVotes(postIds);
49 const repliesQuery = useBatchReplyCountsGlobal(postIds, showAll);
50
51 // Check if metrics are still loading
52 const metricsLoading = postIds.length > 0 &&
53 (zapsQuery.isLoading || votesQuery.isLoading || repliesQuery.isLoading);
54
55 // Step 3: Combine data and calculate hot scores
56 const popularPosts = useMemo<PopularPost[]>(() => {
57 if (!postsQuery.data || postsQuery.data.length === 0) return [];
58
59 const zapsMap = zapsQuery.data ?? new Map();
60 const votesMap = votesQuery.data ?? new Map();
61 const repliesMap = repliesQuery.data ?? new Map();
62
63 const postsWithScores: PopularPost[] = postsQuery.data.map((event) => {
64 const zapData = zapsMap.get(event.id) ?? { zapCount: 0, totalSats: 0, zaps: [] };
65 const voteData = votesMap.get(event.id) ?? { upvotes: 0, downvotes: 0, score: 0, reactions: [] };
66 const replyCount = repliesMap.get(event.id) ?? 0;
67
68 const metrics: PopularPostMetrics = {
69 totalSats: zapData.totalSats,
70 zapCount: zapData.zapCount,
71 upvotes: voteData.upvotes,
72 downvotes: voteData.downvotes,
73 score: voteData.score,
74 replyCount,
75 createdAt: event.created_at,
76 };
77
78 const hotScore = calculateHotScore(metrics);
79
80 return {
81 event,
82 metrics,
83 hotScore,
84 };
85 });
86
87 // Sort by hot score descending and limit
88 return postsWithScores
89 .sort((a, b) => b.hotScore - a.hotScore)
90 .slice(0, limit);
91 }, [postsQuery.data, zapsQuery.data, votesQuery.data, repliesQuery.data, limit]);

Callers 1

PopularFunction · 0.90

Calls 6

getTimeRangeSinceFunction · 0.90
useClawstrPostsFunction · 0.90
useBatchZapsFunction · 0.90
useBatchPostVotesFunction · 0.90
calculateHotScoreFunction · 0.90

Tested by

no test coverage detected