Skip to content

Commit

Permalink
Merge pull request #220 from alleslabs/feat/txs-account-details
Browse files Browse the repository at this point in the history
feat: implement transaction table for account details page
  • Loading branch information
bkioshn committed Feb 24, 2023
2 parents 54d90b5 + f7731be commit 50953ac
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 32 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Features

- [#220](https://github.com/alleslabs/celatone-frontend/pull/220) Add transactions table for account details page
- [#222](https://github.com/alleslabs/celatone-frontend/pull/222) Add proposals of an account
- [#221](https://github.com/alleslabs/celatone-frontend/pull/221) Add codes of an account
- [#223](https://github.com/alleslabs/celatone-frontend/pull/223) Newer version of token card and format mechanism
Expand Down
10 changes: 8 additions & 2 deletions src/lib/components/table/TableTitle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ interface TableTitleProps {
title: string;
count: number;
helperText?: string;
mb?: number | string;
}

export const TableTitle = ({ title, count, helperText }: TableTitleProps) => (
<Box mb={6}>
export const TableTitle = ({
title,
count,
helperText,
mb = "6",
}: TableTitleProps) => (
<Box mb={mb}>
<Flex gap={2} h="29px" alignItems="center">
<Heading as="h6" variant="h6">
{title}
Expand Down
11 changes: 11 additions & 0 deletions src/lib/data/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,14 @@ export const typeUrlDict = {
};

export const DEFAULT_RPC_ERROR = "Invalid format, or Something went wrong";

export const DEFAULT_TX_FILTERS = {
isExecute: false,
isInstantiate: false,
isUpload: false,
isIbc: false,
isSend: false,
isMigrate: false,
isUpdateAdmin: false,
isClearAdmin: false,
};
18 changes: 5 additions & 13 deletions src/lib/model/account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// TODO - Refactor Past txs query
import { DEFAULT_TX_FILTERS } from "lib/data";
import { useTxQueryCount } from "lib/pages/past-txs/query/useTxQuery";
import { useCodeListCountByWalletAddress } from "lib/services/codeService";
import {
Expand All @@ -21,33 +22,24 @@ export const useAccountDetailsTableCounts = (walletAddress: HumanAddr) => {
useInstantiatedCountByUserQuery(walletAddress);
const { data: proposalsCount, refetch: refetchProposalsCount } =
useProposalsCountByWalletAddress(walletAddress);
const { data: countTxs, refetch: refetchCountTxs } = useTxQueryCount(
const { data: txsCount, refetch: refetchTxsCount } = useTxQueryCount(
walletAddress,
"",
{
isExecute: false,
isInstantiate: false,
isUpload: false,
isIbc: false,
isSend: false,
isMigrate: false,
isUpdateAdmin: false,
isClearAdmin: false,
}
DEFAULT_TX_FILTERS
);

return {
tableCounts: {
codesCount,
contractsAdminCount,
contractsCount,
countTxs,
txsCount,
proposalsCount,
},
refetchCodesCount,
refetchContractsAdminCount,
refetchContractsCount,
refetchCountTxs,
refetchTxsCount,
refetchProposalsCount,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {
Box,
Flex,
Grid,
Icon,
Tag,
Text,
useDisclosure,
} from "@chakra-ui/react";
import { useState } from "react";
import { MdCheck, MdClose, MdKeyboardArrowDown } from "react-icons/md";

import { RenderActionMessages } from "lib/components/action-msg/ActionMessages";
import { ExplorerLink } from "lib/components/ExplorerLink";
import { TableRow } from "lib/components/table";
import { AccordionTx } from "lib/components/table/AccordionTx";
import type { PastTransaction } from "lib/types";
import { dateFromNow, formatUTC } from "lib/utils";

interface TxsTableRowProps {
transaction: PastTransaction;
templateColumns: string;
}

export const TxsTableRow = ({
transaction,
templateColumns,
}: TxsTableRowProps) => {
const { isOpen, onToggle } = useDisclosure();
const isAccordion = transaction.messages.length > 1;
const [showCopyButton, setShowCopyButton] = useState(false);

return (
<Box w="full" minW="min-content">
<Grid
templateColumns={templateColumns}
onClick={isAccordion ? onToggle : undefined}
_hover={{ background: "pebble.900" }}
onMouseEnter={() => setShowCopyButton(true)}
onMouseLeave={() => setShowCopyButton(false)}
transition="all .25s ease-in-out"
cursor={isAccordion ? "pointer" : "default"}
>
<TableRow pl="16px">
<ExplorerLink
value={transaction.hash.toUpperCase()}
type="tx_hash"
canCopyWithHover
/>
</TableRow>
<TableRow>
<Icon
as={transaction.success ? MdCheck : MdClose}
fontSize="24px"
color={transaction.success ? "success.main" : "error.main"}
/>
</TableRow>
<TableRow>
<Flex gap={1} flexWrap="wrap">
<RenderActionMessages
transaction={transaction}
showCopyButton={showCopyButton}
/>
{transaction.isIbc && (
<Tag borderRadius="full" bg="honeydew.dark" color="pebble.900">
IBC
</Tag>
)}
</Flex>
</TableRow>
<TableRow>
<Flex direction="column" gap={1}>
{transaction.created ? (
<Flex direction="column" gap={1}>
<Text variant="body3">{formatUTC(transaction.created)}</Text>
<Text variant="body3" color="text.dark">
{`(${dateFromNow(transaction.created)})`}
</Text>
</Flex>
) : (
<Text variant="body3">N/A</Text>
)}
</Flex>
</TableRow>
<TableRow>
{isAccordion && (
<Icon
as={MdKeyboardArrowDown}
transform={isOpen ? "rotate(180deg)" : "rotate(0deg)"}
boxSize="24px"
color="pebble.600"
/>
)}
</TableRow>
</Grid>
{isAccordion && (
<Grid w="full" py={2} bg="pebble.900" hidden={!isOpen}>
{transaction.messages.map((msg, index) => (
<AccordionTx
key={index.toString() + msg.type}
allowFurtherAction={false}
message={msg}
/>
))}
</Grid>
)}
</Box>
);
};
182 changes: 182 additions & 0 deletions src/lib/pages/account-details/components/tables/transactions/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// TODO - Refactor: move common component out of pasttx
import { Box, Flex, Grid } from "@chakra-ui/react";
import type { ChangeEvent } from "react";
import { useState } from "react";

import { Loading } from "lib/components/Loading";
import { Pagination } from "lib/components/pagination";
import { usePaginator } from "lib/components/pagination/usePaginator";
import { EmptyState } from "lib/components/state/EmptyState";
import { TableContainer, TableHeader } from "lib/components/table";
import { TableTitle } from "lib/components/table/TableTitle";
import { ViewMore } from "lib/components/table/ViewMore";
import { DEFAULT_TX_FILTERS } from "lib/data";
import { FilterSelection } from "lib/pages/past-txs/components/FilterSelection";
import { useTxQuery } from "lib/pages/past-txs/query/useTxQuery";
import type { HumanAddr, Option, TxFilters } from "lib/types";

import { TxsTableRow } from "./TxsTableRow";

interface TransactionsTableProps {
walletAddress: HumanAddr;
scrollComponentId: string;
totalData: Option<number>;
refetchCount: () => void;
onViewMore?: () => void;
}

interface TransactionsTableBodyProps extends TransactionsTableProps {
filters: TxFilters;
filterSelected: string[];
}

const TransactionsTableBody = ({
walletAddress,
scrollComponentId,
totalData,
refetchCount,
onViewMore,
filters,
filterSelected,
}: TransactionsTableBodyProps) => {
const {
pagesQuantity,
currentPage,
setCurrentPage,
pageSize,
setPageSize,
offset,
} = usePaginator({
total: totalData,
initialState: {
pageSize: 10,
currentPage: 1,
isDisabled: false,
},
});

const { data: transactions, isLoading } = useTxQuery(
walletAddress,
"",
filters,
onViewMore ? 5 : pageSize,
offset
);

const onPageChange = (nextPage: number) => {
refetchCount();
setCurrentPage(nextPage);
};

const onPageSizeChange = (e: ChangeEvent<HTMLSelectElement>) => {
const size = Number(e.target.value);
refetchCount();
setPageSize(size);
setCurrentPage(1);
};

const templateColumns = "180px 70px minmax(360px, 1fr) max(250px) max(70px)";

if (isLoading) return <Loading />;

if (!transactions?.length && filterSelected.length > 0)
return (
<Flex
mt="20px"
py="64px"
direction="column"
borderY="1px solid"
borderColor="pebble.700"
>
<EmptyState
image="https://assets.alleslabs.dev/illustration/search-empty.svg"
message="No past transaction matches found with your input."
/>
</Flex>
);

if (!transactions?.length)
return (
<Flex
mt="20px"
py="64px"
direction="column"
borderY="1px solid"
borderColor="pebble.700"
>
<EmptyState message="This account did not submit any transactions before." />
</Flex>
);

return (
<>
<TableContainer>
<Grid templateColumns={templateColumns}>
<TableHeader>Transaction Hash</TableHeader>
<TableHeader />
<TableHeader>Messages</TableHeader>
<TableHeader>Timestamp</TableHeader>
<TableHeader />
</Grid>
{transactions.map((transaction) => (
<TxsTableRow
key={transaction.hash}
transaction={transaction}
templateColumns={templateColumns}
/>
))}
</TableContainer>
{totalData &&
(onViewMore
? totalData > 5 && <ViewMore onClick={onViewMore} />
: totalData > 10 && (
<Pagination
currentPage={currentPage}
pagesQuantity={pagesQuantity}
offset={offset}
totalData={totalData}
scrollComponentId={scrollComponentId}
pageSize={pageSize}
onPageChange={onPageChange}
onPageSizeChange={onPageSizeChange}
/>
))}
</>
);
};

export const TransactionsTable = (
transactionsTableProps: TransactionsTableProps
) => {
const [filters, setFilters] = useState<TxFilters>(DEFAULT_TX_FILTERS);

const handleSetFilters = (filter: string, bool: boolean) => {
setFilters((prevFilters) => ({ ...prevFilters, [filter]: bool }));
};

const filterSelected = Object.keys(filters).filter(
(key) => filters[key as keyof typeof filters]
);

const { totalData, onViewMore } = transactionsTableProps;
return (
<Box mt={12} mb={4}>
<Flex direction="row" justify="space-between" alignItems="center">
<TableTitle title="Transactions" count={totalData ?? 0} mb={0} />
{!onViewMore && (
<FilterSelection
result={filterSelected}
setResult={handleSetFilters}
boxWidth="400px"
placeholder="All"
/>
)}
</Flex>
<TransactionsTableBody
{...transactionsTableProps}
filters={filters}
filterSelected={filterSelected}
/>
</Box>
);
};
Loading

2 comments on commit 50953ac

@vercel
Copy link

@vercel vercel bot commented on 50953ac Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 50953ac Feb 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.