From e024b6ddccde3338ea8d91cefe066e0aa6e45c01 Mon Sep 17 00:00:00 2001 From: Nimsara Date: Fri, 21 Nov 2025 15:03:07 +0530 Subject: [PATCH] feat: implement load more functionality for transaction history --- src/app/api/transaction/list/route.ts | 14 +++--- src/app/dashboard/history/page.tsx | 71 +++++++++++++++++++++------ 2 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/app/api/transaction/list/route.ts b/src/app/api/transaction/list/route.ts index 3a033c2..322639c 100644 --- a/src/app/api/transaction/list/route.ts +++ b/src/app/api/transaction/list/route.ts @@ -22,13 +22,13 @@ export async function GET(request: Request) { // Get pagination parameters from URL const url = new URL(request.url); - const page = url.searchParams.get("page") || "1"; - const limit = url.searchParams.get("limit") || "10"; + const page = parseInt(url.searchParams.get("page") || "1"); + const limit = parseInt(url.searchParams.get("limit") || "10"); // Build API URL with pagination parameters const apiUrl = new URL(`${process.env.API_BASE_URL}/transaction/list`); - apiUrl.searchParams.set("page", page); - apiUrl.searchParams.set("limit", limit); + apiUrl.searchParams.set("page", String(page)); + apiUrl.searchParams.set("limit", String(limit)); // Make request to external API to get current user transactions const response = await fetch(apiUrl.toString(), { @@ -46,6 +46,7 @@ export async function GET(request: Request) { return NextResponse.json( { transactions: [], + nextCursor: null, message: "No transactions found", }, { status: 200 } @@ -62,11 +63,12 @@ export async function GET(request: Request) { ); } - const transactions = await response.json(); + const data = await response.json(); + const transactions = data.transactions || []; return NextResponse.json({ transactions, - message: "Transactions fetched successfully", + nextCursor: transactions.length === limit ? page + 1 : null, }); } catch (error) { console.error("❌ Error fetching current transactions:", error); diff --git a/src/app/dashboard/history/page.tsx b/src/app/dashboard/history/page.tsx index b997f1b..fd564ed 100644 --- a/src/app/dashboard/history/page.tsx +++ b/src/app/dashboard/history/page.tsx @@ -6,7 +6,7 @@ import type { ApiTransaction } from "@/lib/types"; import { cn } from "@/lib/cn"; import ListItemSkeleton from "@/components/skeletons/ListItemSkeleton"; import { formatDate, formatSatoshis } from "@/lib/formatters"; -import { useQuery } from "@tanstack/react-query"; +import { useInfiniteQuery } from "@tanstack/react-query"; import { queryKeys } from "@/lib/query-keys"; export default function HistoryPage() { @@ -16,14 +16,17 @@ export default function HistoryPage() { const [selectedTransaction, setSelectedTransaction] = useState(null); const { - data: apiTransactions = [], + data, error, isLoading, + fetchNextPage, + hasNextPage, + isFetchingNextPage, refetch, - } = useQuery({ + } = useInfiniteQuery({ queryKey: queryKeys.transactions, - queryFn: async () => { - const response = await fetch(`/api/transaction/list`, { + queryFn: async ({ pageParam = 1 }) => { + const response = await fetch(`/api/transaction/list?page=${pageParam}`, { headers: { "Content-Type": "application/json", Authorization: `Bearer ${authToken}`, @@ -35,21 +38,16 @@ export default function HistoryPage() { result.message || `Failed to fetch transactions: ${response.statusText}` ); } - // Handle different response structures - if (Array.isArray(result)) { - return result; - } - if (result.transactions) { - return Array.isArray(result.transactions) - ? result.transactions - : result.transactions?.transactions || []; - } - return []; + return result; }, + initialPageParam: 1, + getNextPageParam: (lastPage) => lastPage.nextCursor, enabled: !!authToken, staleTime: 1000 * 60 * 5, }); + const apiTransactions = data?.pages.flatMap((page) => page.transactions) ?? []; + const errorMessage = error instanceof Error ? error.message : null; // Get settlement status info @@ -316,6 +314,49 @@ export default function HistoryPage() { ))} + {/* Load More Button */} + {authToken && !errorMessage && apiTransactions.length > 0 && hasNextPage && ( +
+ +
+ )} + + {/* Transaction Summary */} + {authToken && !errorMessage && apiTransactions.length > 0 && ( +
+ Showing {apiTransactions.length} transaction{apiTransactions.length !== 1 ? "s" : ""} + {!hasNextPage && " (all loaded)"} +
+ )} + {/* Transaction Detail Modal */} {selectedTransaction && (