From fc8eb79b98bbea558bd614dc71dd66b72ab9b0c0 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sun, 17 Mar 2024 13:12:11 +0000 Subject: feature: Implemente pagination support --- apps/mobile/components/bookmarks/BookmarkList.tsx | 31 ++++++++++++-- apps/web/app/dashboard/lists/[listId]/page.tsx | 2 +- apps/web/app/dashboard/search/page.tsx | 2 +- apps/web/app/dashboard/tags/[tagName]/page.tsx | 2 +- .../components/dashboard/bookmarks/Bookmarks.tsx | 2 +- .../dashboard/bookmarks/BookmarksGrid.tsx | 47 ++++++++++++++++------ 6 files changed, 66 insertions(+), 20 deletions(-) (limited to 'apps') diff --git a/apps/mobile/components/bookmarks/BookmarkList.tsx b/apps/mobile/components/bookmarks/BookmarkList.tsx index e7b5e5f2..8a19c045 100644 --- a/apps/mobile/components/bookmarks/BookmarkList.tsx +++ b/apps/mobile/components/bookmarks/BookmarkList.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef, useState } from "react"; -import { Keyboard, Text, View } from "react-native"; +import { ActivityIndicator, Keyboard, Text, View } from "react-native"; import Animated, { LinearTransition } from "react-native-reanimated"; import { api } from "@/lib/trpc"; import { useScrollToTop } from "@react-navigation/native"; @@ -20,13 +20,26 @@ export default function BookmarkList({ const [refreshing, setRefreshing] = useState(false); const flatListRef = useRef(null); useScrollToTop(flatListRef); - const { data, isPending, isPlaceholderData } = - api.bookmarks.getBookmarks.useQuery(query); + const { + data, + isPending, + isPlaceholderData, + error, + fetchNextPage, + isFetchingNextPage, + } = api.bookmarks.getBookmarks.useInfiniteQuery(query, { + initialCursor: null, + getNextPageParam: (lastPage) => lastPage.nextCursor, + }); useEffect(() => { setRefreshing(isPending || isPlaceholderData); }, [isPending, isPlaceholderData]); + if (error) { + return {JSON.stringify(error)}; + } + if (isPending || !data) { return ; } @@ -51,11 +64,21 @@ export default function BookmarkList({ No Bookmarks } - data={data.bookmarks} + data={data.pages.flatMap((p) => p.bookmarks)} refreshing={refreshing} onRefresh={onRefresh} onScrollBeginDrag={Keyboard.dismiss} keyExtractor={(b) => b.id} + onEndReached={() => fetchNextPage()} + ListFooterComponent={ + isFetchingNextPage ? ( + + + + ) : ( + + ) + } /> ); } diff --git a/apps/web/app/dashboard/lists/[listId]/page.tsx b/apps/web/app/dashboard/lists/[listId]/page.tsx index b9a26053..a8ba4feb 100644 --- a/apps/web/app/dashboard/lists/[listId]/page.tsx +++ b/apps/web/app/dashboard/lists/[listId]/page.tsx @@ -43,7 +43,7 @@ export default async function ListPage({
); diff --git a/apps/web/app/dashboard/search/page.tsx b/apps/web/app/dashboard/search/page.tsx index 38099c18..62d42a43 100644 --- a/apps/web/app/dashboard/search/page.tsx +++ b/apps/web/app/dashboard/search/page.tsx @@ -24,7 +24,7 @@ function SearchComp() { {data ? ( b.id) }} - bookmarks={data.bookmarks} + bookmarks={data} /> ) : ( diff --git a/apps/web/app/dashboard/tags/[tagName]/page.tsx b/apps/web/app/dashboard/tags/[tagName]/page.tsx index dee29c5e..f06062c3 100644 --- a/apps/web/app/dashboard/tags/[tagName]/page.tsx +++ b/apps/web/app/dashboard/tags/[tagName]/page.tsx @@ -38,7 +38,7 @@ export default async function TagPage({
{tagName}
- +
); } diff --git a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx index 601b1627..96e5c067 100644 --- a/apps/web/components/dashboard/bookmarks/Bookmarks.tsx +++ b/apps/web/components/dashboard/bookmarks/Bookmarks.tsx @@ -35,7 +35,7 @@ export default async function Bookmarks({ {showDivider &&
} diff --git a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx index 644991bb..b689a192 100644 --- a/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx +++ b/apps/web/components/dashboard/bookmarks/BookmarksGrid.tsx @@ -1,6 +1,7 @@ "use client"; import { useMemo } from "react"; +import { ActionButton } from "@/components/ui/action-button"; import { api } from "@/lib/trpc"; import tailwindConfig from "@/tailwind.config"; import { Slot } from "@radix-ui/react-slot"; @@ -10,6 +11,7 @@ import resolveConfig from "tailwindcss/resolveConfig"; import type { ZBookmark, ZGetBookmarksRequest, + ZGetBookmarksResponse, } from "@hoarder/trpc/types/bookmarks"; import EditorCard from "./EditorCard"; @@ -55,24 +57,45 @@ export default function BookmarksGrid({ showEditorCard = false, }: { query: ZGetBookmarksRequest; - bookmarks: ZBookmark[]; + bookmarks: ZGetBookmarksResponse; showEditorCard?: boolean; + itemsPerPage?: number; }) { - const { data } = api.bookmarks.getBookmarks.useQuery(query, { - initialData: { bookmarks: initialBookmarks }, - }); + const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = + api.bookmarks.getBookmarks.useInfiniteQuery(query, { + initialData: () => ({ + pages: [initialBookmarks], + pageParams: [query.cursor], + }), + initialCursor: null, + getNextPageParam: (lastPage) => lastPage.nextCursor, + }); + const breakpointConfig = useMemo(() => getBreakpointConfig(), []); - if (data.bookmarks.length == 0) { + const bookmarks = data!.pages.flatMap((b) => b.bookmarks); + if (bookmarks.length == 0) { return

No bookmarks

; } return ( - - {showEditorCard && ( - - - + <> + + {showEditorCard && ( + + + + )} + {bookmarks.map((b) => renderBookmark(b))} + + {hasNextPage && ( + fetchNextPage()} + className="mx-auto w-min" + variant="ghost" + > + Load More + )} - {data.bookmarks.map((b) => renderBookmark(b))} - + ); } -- cgit v1.2.3-70-g09d2