@@ -8,9 +8,48 @@ import {
88} from "@/lib/graphql/generated";
99import { type PaginatedResponse } from "@/lib/api/types";
1010import { bountyKeys } from "@/lib/query/query-keys";
11+ import { formatPaginatedBounties } from "@/lib/utils/pagination";
1112
13+ /** Default number of bounties to fetch per page */
1214const DEFAULT_LIMIT = 20;
1315
16+ /**
17+ * Hook for fetching bounties with infinite scroll pagination from GraphQL API
18+ *
19+ * This hook uses React Query's `useInfiniteQuery` to manage paginated data fetching
20+ * with automatic pagination handling. It fetches the next page of results as needed
21+ * and maintains accumulated data across pages.
22+ *
23+ * The hook automatically manages:
24+ * - Pagination state (current page, items per page)
25+ * - Loading and error states
26+ * - Next/previous page determination
27+ * - Result accumulation and flattening
28+ *
29+ * @param params - Query parameters (page is omitted, determined by pagination)
30+ * @returns Infinite query result with pages array and pagination functions
31+ *
32+ * @example
33+ * const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteBounties({
34+ * limit: 20,
35+ * search: "security"
36+ * });
37+ *
38+ * const allBounties = data?.pages.flatMap(page => page.data) ?? [];
39+ *
40+ * return (
41+ * <InfiniteScroll
42+ * dataLength={allBounties.length}
43+ * next={fetchNextPage}
44+ * hasMore={hasNextPage ?? false}
45+ * loader={<Spinner />}
46+ * >
47+ * {allBounties.map(bounty => (
48+ * <BountyCard key={bounty.id} bounty={bounty} />
49+ * ))}
50+ * </InfiniteScroll>
51+ * );
52+ */
1453export function useInfiniteBounties(params?: Omit<BountyQueryInput, "page">) {
1554 return useInfiniteQuery<PaginatedResponse<BountyFieldsFragment>>({
1655 queryKey: bountyKeys.infinite(params),
@@ -25,16 +64,13 @@ export function useInfiniteBounties(params?: Omit<BountyQueryInput, "page">) {
2564 limit: params?.limit ?? DEFAULT_LIMIT,
2665 },
2766 })();
28- const data = response.bounties;
29- return {
30- data: data.bounties as BountyFieldsFragment[],
31- pagination: {
32- page: pageParam as number,
33- limit: data.limit,
34- total: data.total,
35- totalPages: data.limit > 0 ? Math.ceil(data.total / data.limit) : 0,
36- },
37- };
67+ const paginatedData = response.bounties;
68+ return formatPaginatedBounties(
69+ paginatedData.bounties as BountyFieldsFragment[],
70+ paginatedData.total,
71+ paginatedData.limit,
72+ pageParam as number,
73+ );
3874 },
3975 initialPageParam: 1,
4076 getNextPageParam: (lastPage) => {
0 commit comments