diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b2a14446..8941f14c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Features
+- [#821](https://github.com/alleslabs/celatone-frontend/pull/821) Add Validator's proposed blocks table
- [#818](https://github.com/alleslabs/celatone-frontend/pull/818) bonded tokens voting powers replacement with real data from api v1
- [#801](https://github.com/alleslabs/celatone-frontend/pull/801) Add validator detail ui structure
- [#817](https://github.com/alleslabs/celatone-frontend/pull/817) api v1 - validator voted proposals
diff --git a/src/lib/components/table/MobileCardTemplate.tsx b/src/lib/components/table/MobileCardTemplate.tsx
index 8a026f821..cdec92ad5 100644
--- a/src/lib/components/table/MobileCardTemplate.tsx
+++ b/src/lib/components/table/MobileCardTemplate.tsx
@@ -1,9 +1,9 @@
-import { Flex } from "@chakra-ui/react";
+import { Divider, Flex } from "@chakra-ui/react";
import type { ReactNode } from "react";
interface MobileCardTemplateProps {
topContent: ReactNode;
- middleContent: ReactNode;
+ middleContent?: ReactNode;
bottomContent?: ReactNode;
onClick?: () => void;
}
@@ -26,16 +26,19 @@ export const MobileCardTemplate = ({
{topContent}
-
- {middleContent}
-
+ {middleContent && (
+
+ {middleContent}
+
+ )}
+ {!middleContent && }
{bottomContent && {bottomContent}}
);
diff --git a/src/lib/components/table/ViewMore.tsx b/src/lib/components/table/ViewMore.tsx
index f549aaabb..79358c701 100644
--- a/src/lib/components/table/ViewMore.tsx
+++ b/src/lib/components/table/ViewMore.tsx
@@ -8,12 +8,14 @@ interface ViewMoreProps {
onClick: () => void;
borderRadius?: BorderProps["borderRadius"];
minH?: LayoutProps["minH"];
+ text?: string;
}
export const ViewMore = ({
onClick,
borderRadius = "0",
minH = "64px",
+ text = "View More",
}: ViewMoreProps) => (
diff --git a/src/lib/pages/blocks/components/BlocksTableHeader.tsx b/src/lib/pages/blocks/components/BlocksTableHeader.tsx
index 5be719987..0b72f8dde 100644
--- a/src/lib/pages/blocks/components/BlocksTableHeader.tsx
+++ b/src/lib/pages/blocks/components/BlocksTableHeader.tsx
@@ -6,11 +6,13 @@ import { TableHeader } from "lib/components/table";
interface BlocksTableHeaderProps {
templateColumns: GridProps["templateColumns"];
scrollComponentId: string;
+ hideProposer?: boolean;
}
export const BlocksTableHeader = ({
templateColumns,
scrollComponentId,
+ hideProposer = false,
}: BlocksTableHeaderProps) => (
Block Height
Block Hash
- Proposed by
+ {!hideProposer && Proposed by}
Transactions
Timestamp
diff --git a/src/lib/pages/blocks/components/BlocksTableMobileCard.tsx b/src/lib/pages/blocks/components/BlocksTableMobileCard.tsx
index 72b215a41..0a61cb149 100644
--- a/src/lib/pages/blocks/components/BlocksTableMobileCard.tsx
+++ b/src/lib/pages/blocks/components/BlocksTableMobileCard.tsx
@@ -9,9 +9,11 @@ import { dateFromNow, formatUTC, truncate } from "lib/utils";
interface BlocksTableMobileCardProps {
blockData: Block;
+ hideProposer?: boolean;
}
export const BlocksTableMobileCard = ({
blockData,
+ hideProposer = false,
}: BlocksTableMobileCardProps) => {
const navigate = useInternalNavigate();
return (
@@ -23,8 +25,8 @@ export const BlocksTableMobileCard = ({
})
}
topContent={
-
-
+
+
-
+
@@ -42,7 +44,14 @@ export const BlocksTableMobileCard = ({
-
+
+ }
+ middleContent={
+ !hideProposer &&
+ }
+ bottomContent={
+
+
-
- }
- middleContent={
-
-
-
- }
- bottomContent={
-
{formatUTC(blockData.timestamp)}
diff --git a/src/lib/pages/blocks/components/BlocksTableRow.tsx b/src/lib/pages/blocks/components/BlocksTableRow.tsx
index 53fa063ab..aacbbfaa1 100644
--- a/src/lib/pages/blocks/components/BlocksTableRow.tsx
+++ b/src/lib/pages/blocks/components/BlocksTableRow.tsx
@@ -11,11 +11,13 @@ import { dateFromNow, formatUTC, truncate } from "lib/utils";
interface BlocksTableRowProps {
templateColumns: GridProps["templateColumns"];
blockData: Block;
+ hideProposer?: boolean;
}
export const BlocksTableRow = ({
templateColumns,
blockData,
+ hideProposer = false,
}: BlocksTableRowProps) => {
const navigate = useInternalNavigate();
@@ -42,14 +44,18 @@ export const BlocksTableRow = ({
{blockData.height}
- {truncate(blockData.hash.toUpperCase())}
-
+ {truncate(blockData.hash.toUpperCase(), hideProposer ? [9, 9] : [6, 6])}
+ {!hideProposer && (
+
+
+
+ )}
{
- return (
-
-
-
-
-
-
-
-
+interface PerformanceProps {
+ validatorAddress: ValidatorAddr;
+}
+
+export const Performance = ({ validatorAddress }: PerformanceProps) => (
+
+
+
+
-
-
+
+
-
- );
-};
+
+
+
+
+
+);
diff --git a/src/lib/pages/validator-details/components/tables/ProposedBlocksTable.tsx b/src/lib/pages/validator-details/components/tables/ProposedBlocksTable.tsx
index 6b84a130f..de6cccb95 100644
--- a/src/lib/pages/validator-details/components/tables/ProposedBlocksTable.tsx
+++ b/src/lib/pages/validator-details/components/tables/ProposedBlocksTable.tsx
@@ -1,31 +1,126 @@
-import { Flex, Heading } from "@chakra-ui/react";
-
import { useMobile } from "lib/app-provider";
-import { MobileTitle } from "lib/components/table";
+import { Loading } from "lib/components/Loading";
+import { Pagination } from "lib/components/pagination";
+import { usePaginator } from "lib/components/pagination/usePaginator";
+import { EmptyState, ErrorFetching } from "lib/components/state";
+import {
+ MobileTableContainer,
+ TableContainer,
+ TableTitle,
+ ViewMore,
+} from "lib/components/table";
+import { BlocksTableHeader } from "lib/pages/blocks/components/BlocksTableHeader";
+import { BlocksTableMobileCard } from "lib/pages/blocks/components/BlocksTableMobileCard";
+import { BlocksTableRow } from "lib/pages/blocks/components/BlocksTableRow";
+import { useValidatorProposedBlocks } from "lib/services/validatorService";
+import type { ValidatorAddr } from "lib/types";
interface ProposedBlocksTableProps {
+ validatorAddress: ValidatorAddr;
onViewMore?: () => void;
}
+
+const TEMPLATE_COLUMNS = "150px minmax(160px, 1fr) 180px 280px";
+const scrollComponentId = "proposed-block-table-header";
+
export const ProposedBlocksTable = ({
+ validatorAddress,
onViewMore,
}: ProposedBlocksTableProps) => {
const isMobile = useMobile();
- const isMobileOverview = isMobile && !!onViewMore;
+
+ const {
+ pagesQuantity,
+ setTotalData,
+ currentPage,
+ setCurrentPage,
+ pageSize,
+ setPageSize,
+ offset,
+ } = usePaginator({
+ initialState: {
+ pageSize: 10,
+ currentPage: 1,
+ isDisabled: false,
+ },
+ });
+
+ const { data, isLoading, error } = useValidatorProposedBlocks(
+ validatorAddress,
+ onViewMore ? 5 : pageSize,
+ offset,
+ {
+ onSuccess: ({ total }) => setTotalData(total),
+ }
+ );
+
+ if (isLoading) return ;
+ if (error) return ;
+ if (!data?.total)
+ return (
+
+ );
+
return (
<>
- {isMobileOverview ? (
-
+
+ {isMobile ? (
+
+ {data.items.map((block) => (
+
+ ))}
+
) : (
-
-
- Recently Proposed Blocks
-
- {isMobile ? mobile table : table}
-
+
+
+ {data.items.map((block) => (
+
+ ))}
+
+ )}
+ {onViewMore && data.total > 5 && (
+
+ )}
+ {!onViewMore && data.total > 10 && (
+ {
+ const size = Number(e.target.value);
+ setPageSize(size);
+ setCurrentPage(1);
+ }}
+ />
)}
>
);
diff --git a/src/lib/pages/validator-details/components/validator-overview/index.tsx b/src/lib/pages/validator-details/components/validator-overview/index.tsx
index 0d06eb907..039b33f3d 100644
--- a/src/lib/pages/validator-details/components/validator-overview/index.tsx
+++ b/src/lib/pages/validator-details/components/validator-overview/index.tsx
@@ -57,7 +57,10 @@ export const ValidatorOverview = ({
onViewMore={onSelectBondedTokenChanges}
/>
)}
-
+
{/* TODO: change to conditions and remove line 72-74 */}
diff --git a/src/lib/pages/validator-details/index.tsx b/src/lib/pages/validator-details/index.tsx
index ccef1e725..253120464 100644
--- a/src/lib/pages/validator-details/index.tsx
+++ b/src/lib/pages/validator-details/index.tsx
@@ -96,7 +96,7 @@ const ValidatorDetailsBody = ({
-
+
{!move.enabled && (
diff --git a/src/lib/services/validatorService.ts b/src/lib/services/validatorService.ts
index 6783bfcde..c390dbea3 100644
--- a/src/lib/services/validatorService.ts
+++ b/src/lib/services/validatorService.ts
@@ -192,15 +192,22 @@ export const useValidatorDelegationRelatedTxs = (
export const useValidatorProposedBlocks = (
validatorAddress: ValidatorAddr,
limit: number,
- offset: number
+ offset: number,
+ options: Pick, "onSuccess"> = {}
) => {
const endpoint = useBaseApiRoute("validators");
return useQuery(
- [CELATONE_QUERY_KEYS.VALIDATOR_PROPOSED_BLOCKS, endpoint, validatorAddress],
+ [
+ CELATONE_QUERY_KEYS.VALIDATOR_PROPOSED_BLOCKS,
+ endpoint,
+ validatorAddress,
+ limit,
+ offset,
+ ],
async () =>
getValidatorProposedBlocks(endpoint, validatorAddress, limit, offset),
- { retry: 1 }
+ { retry: 1, ...options }
);
};