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