diff options
Diffstat (limited to 'apps/web/lib/queries/use-custom-feed-timeline.ts')
| -rw-r--r-- | apps/web/lib/queries/use-custom-feed-timeline.ts | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/apps/web/lib/queries/use-custom-feed-timeline.ts b/apps/web/lib/queries/use-custom-feed-timeline.ts new file mode 100644 index 0000000..4224123 --- /dev/null +++ b/apps/web/lib/queries/use-custom-feed-timeline.ts @@ -0,0 +1,76 @@ +"use client" + +import { useInfiniteQuery } from "@tanstack/react-query" +import { createSupabaseBrowserClient } from "@/lib/supabase/client" +import { queryKeys } from "./query-keys" +import type { TimelineEntry } from "@/lib/types/timeline" + +const TIMELINE_PAGE_SIZE = 50 + +interface TimelineRow { + entry_id: string + feed_id: string + feed_title: string + custom_title: string | null + entry_title: string + entry_url: string + author: string | null + summary: string | null + image_url: string | null + published_at: string + is_read: boolean + is_saved: boolean + enclosure_url: string | null + enclosure_type: string | null +} + +function mapRowToTimelineEntry(row: TimelineRow): TimelineEntry { + return { + entryIdentifier: row.entry_id, + feedIdentifier: row.feed_id, + feedTitle: row.feed_title, + customTitle: row.custom_title, + entryTitle: row.entry_title, + entryUrl: row.entry_url, + author: row.author, + summary: row.summary, + imageUrl: row.image_url, + publishedAt: row.published_at, + isRead: row.is_read, + isSaved: row.is_saved, + enclosureUrl: row.enclosure_url, + enclosureType: row.enclosure_type, + } +} + +export function useCustomFeedTimeline(customFeedIdentifier: string | null) { + const supabaseClient = createSupabaseBrowserClient() + + return useInfiniteQuery({ + queryKey: queryKeys.customFeeds.timeline(customFeedIdentifier ?? ""), + queryFn: async ({ + pageParam, + }: { + pageParam: string | undefined + }) => { + const { data, error } = await supabaseClient.rpc( + "get_custom_feed_timeline", + { + p_custom_feed_id: customFeedIdentifier!, + p_result_limit: TIMELINE_PAGE_SIZE, + p_pagination_cursor: pageParam ?? undefined, + } + ) + + if (error) throw error + + return ((data as TimelineRow[]) ?? []).map(mapRowToTimelineEntry) + }, + initialPageParam: undefined as string | undefined, + getNextPageParam: (lastPage: TimelineEntry[]) => { + if (lastPage.length < TIMELINE_PAGE_SIZE) return undefined + return lastPage[lastPage.length - 1].publishedAt + }, + enabled: !!customFeedIdentifier, + }) +} |