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 } ); };