TransactionsList.tsx raw
1 import { LucideIcon, ZapIcon } from "lucide-react";
2 import { useRef, useState } from "react";
3 import { CustomPagination } from "src/components/CustomPagination";
4 import EmptyState from "src/components/EmptyState";
5 import Loading from "src/components/Loading";
6 import TransactionItem from "src/components/TransactionItem";
7 import { LIST_TRANSACTIONS_LIMIT } from "src/constants";
8 import {
9 getTransactionsUrl,
10 hasActiveTransactionFilters,
11 useTransactions,
12 } from "src/hooks/useTransactions";
13 import useTransactionFiltersStore from "src/state/TransactionFiltersStore";
14
15 type TransactionsListProps = {
16 appId?: number;
17 emptyIcon?: LucideIcon;
18 emptyTitle?: string;
19 emptyDescription?: string;
20 emptyVariant?: "dashed" | "muted" | "none";
21 };
22
23 function TransactionsList({
24 appId,
25 emptyIcon = ZapIcon,
26 emptyTitle = "No lightning payments yet",
27 emptyDescription = "Your payments will appear here as you start using your wallet.",
28 emptyVariant,
29 }: TransactionsListProps) {
30 const [page, setPage] = useState(1);
31 const { filters } = useTransactionFiltersStore();
32
33 // Reset pagination during render when the filters or app change, so no
34 // request is made for a page that may not exist under the new list.
35 const [prevListIdentity, setPrevListIdentity] = useState({ appId, filters });
36 if (
37 prevListIdentity.appId !== appId ||
38 prevListIdentity.filters !== filters
39 ) {
40 setPrevListIdentity({ appId, filters });
41 setPage(1);
42 }
43
44 const transactionListRef = useRef<HTMLDivElement>(null);
45 const transactionListKey = getTransactionsUrl(
46 appId,
47 LIST_TRANSACTIONS_LIMIT,
48 page,
49 filters
50 );
51 const { data: transactionData, isLoading } = useTransactions(
52 appId,
53 false,
54 LIST_TRANSACTIONS_LIMIT,
55 page,
56 filters
57 );
58 const transactions = transactionData?.transactions || [];
59 const totalCount = transactionData?.totalCount || 0;
60 const hasActiveFilters = hasActiveTransactionFilters(filters);
61
62 const handlePageChange = (page: number) => {
63 setPage(page);
64 transactionListRef.current?.scrollIntoView({
65 behavior: "smooth",
66 block: "start",
67 });
68 };
69
70 if (isLoading || !transactionData) {
71 return <Loading />;
72 }
73
74 return (
75 <div ref={transactionListRef} className="flex flex-col flex-1">
76 {!transactions.length ? (
77 <EmptyState
78 icon={emptyIcon}
79 title={hasActiveFilters ? "No matching payments" : emptyTitle}
80 description={
81 hasActiveFilters
82 ? "Try changing your filters to see more payments."
83 : emptyDescription
84 }
85 variant={emptyVariant}
86 />
87 ) : (
88 <>
89 {transactions?.map((tx) => {
90 return (
91 <TransactionItem
92 key={tx.id}
93 tx={tx}
94 transactionListKey={transactionListKey}
95 />
96 );
97 })}
98 <CustomPagination
99 limit={LIST_TRANSACTIONS_LIMIT}
100 totalCount={totalCount}
101 page={page}
102 handlePageChange={handlePageChange}
103 />
104 </>
105 )}
106 </div>
107 );
108 }
109
110 export default TransactionsList;
111