From 5776c65fe75653c34fa6517d37001a2a17afdb39 Mon Sep 17 00:00:00 2001 From: Iveta Date: Mon, 13 Jan 2025 15:49:11 -0500 Subject: [PATCH] Table pagination --- .../components/ContractInfo.tsx | 15 +++- .../components/ContractStorage.tsx | 3 + .../components/VersionHistory.tsx | 3 + src/components/DataTable/index.tsx | 83 ++++++++++++++++++- src/components/DataTable/styles.scss | 11 +++ src/query/external/useSEContracStorage.ts | 6 +- .../external/useSEContractVersionHistory.ts | 6 +- 7 files changed, 120 insertions(+), 7 deletions(-) diff --git a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx index 325ffc9c..7bf19d7b 100644 --- a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx +++ b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractInfo.tsx @@ -28,7 +28,16 @@ export const ContractInfo = ({ infoData: ContractInfoApiResponse; networkId: NetworkType; }) => { - const [activeTab, setActiveTab] = useState("contract-version-history"); + type ContractTabId = + | "contract-bindings" + | "contract-contract-info" + | "contract-source-code" + | "contract-contract-storage" + | "contract-version-history"; + + const [activeTab, setActiveTab] = useState( + "contract-version-history", + ); type ContractExplorerInfoField = { id: string; @@ -242,6 +251,7 @@ export const ContractInfo = ({ label: "Contract Storage", content: ( @@ -260,7 +271,7 @@ export const ContractInfo = ({ }} activeTabId={activeTab} onTabChange={(tabId) => { - setActiveTab(tabId); + setActiveTab(tabId as ContractTabId); }} /> diff --git a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractStorage.tsx b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractStorage.tsx index c5c11d22..de6ddce4 100644 --- a/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractStorage.tsx +++ b/src/app/(sidebar)/smart-contracts/contract-explorer/components/ContractStorage.tsx @@ -14,10 +14,12 @@ import { capitalizeString } from "@/helpers/capitalizeString"; import { ContractStorageResponseItem, NetworkType } from "@/types/types"; export const ContractStorage = ({ + isActive, contractId, networkId, totalEntriesCount, }: { + isActive: boolean; contractId: string; networkId: NetworkType; totalEntriesCount: number | undefined; @@ -28,6 +30,7 @@ export const ContractStorage = ({ isLoading: isStorageLoading, isFetching: isStorageFetching, } = useSEContractStorage({ + isActive, networkId, contractId, totalEntriesCount, diff --git a/src/app/(sidebar)/smart-contracts/contract-explorer/components/VersionHistory.tsx b/src/app/(sidebar)/smart-contracts/contract-explorer/components/VersionHistory.tsx index c3299483..7d585870 100644 --- a/src/app/(sidebar)/smart-contracts/contract-explorer/components/VersionHistory.tsx +++ b/src/app/(sidebar)/smart-contracts/contract-explorer/components/VersionHistory.tsx @@ -10,9 +10,11 @@ import { formatEpochToDate } from "@/helpers/formatEpochToDate"; import { ContractVersionHistoryResponseItem, NetworkType } from "@/types/types"; export const VersionHistory = ({ + isActive, contractId, networkId, }: { + isActive: boolean; contractId: string; networkId: NetworkType; }) => { @@ -22,6 +24,7 @@ export const VersionHistory = ({ isLoading: isVersionHistoryLoading, isFetching: isVersionHistoryFetching, } = useSEContractVersionHistory({ + isActive, networkId, contractId, }); diff --git a/src/components/DataTable/index.tsx b/src/components/DataTable/index.tsx index 948e2ff1..2b2c4444 100644 --- a/src/components/DataTable/index.tsx +++ b/src/components/DataTable/index.tsx @@ -1,5 +1,5 @@ -import { useState } from "react"; -import { Card, Icon } from "@stellar/design-system"; +import { useEffect, useState } from "react"; +import { Button, Card, Icon } from "@stellar/design-system"; import { Box } from "@/components/layout/Box"; import { DataTableCell, DataTableHeader, SortDirection } from "@/types/types"; @@ -18,9 +18,21 @@ export const DataTable = ({ tableData: T[]; formatDataRow: (item: T) => DataTableCell[]; }) => { + const PAGE_SIZE = 10; + const tableDataSize = tableData.length; + + // Sort by const [sortById, setSortById] = useState(""); const [sortByDir, setSortByDir] = useState("default"); + // Pagination + const [currentPage, setCurrentPage] = useState(1); + const [totalPageCount, setTotalPageCount] = useState(1); + + useEffect(() => { + setTotalPageCount(Math.ceil(tableDataSize / PAGE_SIZE)); + }, [tableDataSize]); + const getSortByProps = (th: DataTableHeader) => { if (th.isSortable) { return { @@ -52,11 +64,13 @@ export const DataTable = ({ setSortById(headerId); setSortByDir(sortDir); + setCurrentPage(1); }; const tableRowsData = (): DataTableCell[][] => { let sortedData = [...tableData]; + // Sort if (sortById) { if (["asc", "desc"].includes(sortByDir)) { // Asc @@ -74,12 +88,26 @@ export const DataTable = ({ return sortedData.map(formatDataRow); }; + const paginateData = (data: DataTableCell[][]): DataTableCell[][] => { + if (!data || data.length === 0) { + return []; + } + + const startIndex = Math.max(currentPage - 1, 0) * PAGE_SIZE; + const endIndex = startIndex + PAGE_SIZE; + + return data.slice(startIndex, endIndex); + }; + const customStyle = { "--DataTable-grid-template-columns": cssGridTemplateColumns, } as React.CSSProperties; + const displayData = paginateData(tableRowsData()); + return ( + {/* Table */}
@@ -104,7 +132,7 @@ export const DataTable = ({ - {tableRowsData().map((row, rowIdx) => { + {displayData.map((row, rowIdx) => { const rowKey = `${tableId}-row-${rowIdx}`; return ( @@ -131,6 +159,55 @@ export const DataTable = ({
+ + + {/* Pagination */} + + + + + +
{`Page ${currentPage} of ${totalPageCount}`}
+ + + + +
+
); }; diff --git a/src/components/DataTable/styles.scss b/src/components/DataTable/styles.scss index 19eb7bb2..3b897780 100644 --- a/src/components/DataTable/styles.scss +++ b/src/components/DataTable/styles.scss @@ -96,4 +96,15 @@ } } } + + &__pagination { + background-color: var(--sds-clr-gray-01); + border-radius: pxToRem(4px); + border: 1px solid var(--sds-clr-gray-06); + padding: pxToRem(3px) pxToRem(8px); + font-size: pxToRem(12px); + line-height: pxToRem(18px); + font-weight: var(--sds-fw-semi-bold); + color: var(--sds-clr-gray-12); + } } diff --git a/src/query/external/useSEContracStorage.ts b/src/query/external/useSEContracStorage.ts index b7f6e091..d7c18f59 100644 --- a/src/query/external/useSEContracStorage.ts +++ b/src/query/external/useSEContracStorage.ts @@ -6,10 +6,12 @@ import { ContractStorageResponseItem, NetworkType } from "@/types/types"; * StellarExpert API to get smart contract’s storage data */ export const useSEContractStorage = ({ + isActive, networkId, contractId, totalEntriesCount, }: { + isActive: boolean; networkId: NetworkType; contractId: string; totalEntriesCount: number | undefined; @@ -71,7 +73,9 @@ export const useSEContractStorage = ({ throw `Something went wrong. ${e}`; } }, - enabled: Boolean(networkId && contractId), + enabled: Boolean(isActive && networkId && contractId), + // Keep data for 30 seconds + staleTime: 1000 * 30, }); return query; diff --git a/src/query/external/useSEContractVersionHistory.ts b/src/query/external/useSEContractVersionHistory.ts index a03a42a1..095eea7e 100644 --- a/src/query/external/useSEContractVersionHistory.ts +++ b/src/query/external/useSEContractVersionHistory.ts @@ -6,9 +6,11 @@ import { ContractVersionHistoryResponseItem, NetworkType } from "@/types/types"; * StellarExpert API to get smart contract’s version history */ export const useSEContractVersionHistory = ({ + isActive, networkId, contractId, }: { + isActive: boolean; networkId: NetworkType; contractId: string; }) => { @@ -38,7 +40,9 @@ export const useSEContractVersionHistory = ({ throw `Something went wrong. ${e}`; } }, - enabled: Boolean(networkId && contractId), + enabled: Boolean(isActive && networkId && contractId), + // Keep data for 30 seconds + staleTime: 1000 * 30, }); return query;