diff --git a/dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx b/dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx index ea95c22b7..5c409c3e9 100644 --- a/dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx +++ b/dapp/src/assets/icons/animated/ArrowUpRightAnimatedIcon.tsx @@ -1,6 +1,6 @@ import React from "react" import { ArrowUpRight } from "#/assets/icons" -import { Box, Icon } from "@chakra-ui/react" +import { Box, BoxProps, Icon } from "@chakra-ui/react" import { Variants, motion } from "framer-motion" import { chakraUnitToPx } from "#/theme/utils" @@ -34,18 +34,15 @@ const arrowBottomVariants: Variants = { }), } -type ArrowUpRightAnimatedIconProps = { +type ArrowUpRightAnimatedIconProps = BoxProps & { boxSize?: number - color?: string } -export function ArrowUpRightAnimatedIcon({ - boxSize = 4, - color = "brand.400", -}: ArrowUpRightAnimatedIconProps) { +export function ArrowUpRightAnimatedIcon(props: ArrowUpRightAnimatedIconProps) { + const { boxSize = 4, color = "inherit", ...restProps } = props const boxSizePx = chakraUnitToPx(boxSize) return ( - + {[ { id: "arrow-up", variants: arrowUpVariants }, { id: "arrow-bottom", variants: arrowBottomVariants }, diff --git a/dapp/src/assets/images/empty-state.png b/dapp/src/assets/images/empty-state.png new file mode 100644 index 000000000..cd7d93670 Binary files /dev/null and b/dapp/src/assets/images/empty-state.png differ diff --git a/dapp/src/components/TransactionHistory/Table/utils/pagination.tsx b/dapp/src/components/TransactionHistory/Table/utils/pagination.tsx index fe8983731..60e356197 100644 --- a/dapp/src/components/TransactionHistory/Table/utils/pagination.tsx +++ b/dapp/src/components/TransactionHistory/Table/utils/pagination.tsx @@ -19,6 +19,7 @@ export const PAGINATION_BUTTONS = [ }, ] +// TODO: move to top level `utils` directory export const getPaginationState = ( pageIndex: number, pageSize: number, diff --git a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx index 177035565..51f44bc03 100644 --- a/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx +++ b/dapp/src/components/TransactionModal/ActiveStakingStep/DepositBTCModal.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react" +import React, { useCallback, useEffect } from "react" import { useActionFlowTokenAmount, useAppDispatch, @@ -18,7 +18,7 @@ import Spinner from "#/components/shared/Spinner" import { TextMd } from "#/components/shared/Typography" import { CardAlert } from "#/components/shared/alerts" import { ONE_SEC_IN_MILLISECONDS } from "#/constants" -import { setStatus } from "#/store/action-flow" +import { setStatus, setTxHash } from "#/store/action-flow" const DELAY = ONE_SEC_IN_MILLISECONDS const TOAST_ID = TOAST_IDS.DEPOSIT_TRANSACTION_ERROR @@ -64,11 +64,17 @@ export default function DepositBTCModal() { const onDepositBTCError = useCallback(() => showError(), [showError]) - const { sendBitcoinTransaction } = useDepositBTCTransaction( + const { sendBitcoinTransaction, transactionHash } = useDepositBTCTransaction( onDepositBTCSuccess, onDepositBTCError, ) + useEffect(() => { + if (transactionHash) { + dispatch(setTxHash(transactionHash)) + } + }, [dispatch, transactionHash]) + const handledDepositBTC = useCallback(async () => { if (!tokenAmount?.amount || !btcAddress || !depositReceipt || !ethAccount) return diff --git a/dapp/src/components/TransactionModal/ModalContentWrapper.tsx b/dapp/src/components/TransactionModal/ModalContentWrapper.tsx index cf1ea28fe..8ff6d3477 100644 --- a/dapp/src/components/TransactionModal/ModalContentWrapper.tsx +++ b/dapp/src/components/TransactionModal/ModalContentWrapper.tsx @@ -2,6 +2,7 @@ import React from "react" import { useActionFlowStatus, useActionFlowTokenAmount, + useActionFlowTxHash, useActionFlowType, useRequestBitcoinAccount, useWalletContext, @@ -25,6 +26,7 @@ export default function ModalContentWrapper({ const status = useActionFlowStatus() const type = useActionFlowType() const tokenAmount = useActionFlowTokenAmount() + const txHash = useActionFlowTxHash() if (!btcAccount || !isSupportedBTCAddressType(btcAccount.address)) return ( @@ -39,8 +41,10 @@ export default function ModalContentWrapper({ if (status === PROCESS_STATUSES.LOADING) return - if (status === PROCESS_STATUSES.SUCCEEDED) - return + if (status === PROCESS_STATUSES.SUCCEEDED && txHash) + return ( + + ) if (status === PROCESS_STATUSES.FAILED) return diff --git a/dapp/src/components/TransactionModal/SuccessModal.tsx b/dapp/src/components/TransactionModal/SuccessModal.tsx index 0a2d84b6d..6a666a575 100644 --- a/dapp/src/components/TransactionModal/SuccessModal.tsx +++ b/dapp/src/components/TransactionModal/SuccessModal.tsx @@ -2,6 +2,7 @@ import React from "react" import { Button, HStack, + Icon, ModalBody, ModalFooter, ModalHeader, @@ -11,6 +12,9 @@ import { LoadingSpinnerSuccessIcon } from "#/assets/icons" import { useModal } from "#/hooks" import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" import { ACTION_FLOW_TYPES, ActionFlowType, TokenAmount } from "#/types" +import { useNavigate } from "react-router-dom" +import { routerPath } from "#/router/path" +import { IconArrowUpRight } from "@tabler/icons-react" import { TextMd } from "../shared/Typography" import Spinner from "../shared/Spinner" import BlockExplorerLink from "../shared/BlockExplorerLink" @@ -19,13 +23,13 @@ const CONTENT: Record< ActionFlowType, { header: string - renderBody: (tokenAmount: TokenAmount) => React.ReactNode + renderBody: (tokenAmount: TokenAmount, txHash: string) => React.ReactNode footer: string } > = { [ACTION_FLOW_TYPES.STAKE]: { header: "Deposit received", - renderBody: (tokenAmount) => ( + renderBody: (tokenAmount, txHash) => ( <> - {/* TODO: Use correct tx hash and update styles */} - + {/* TODO: Update styles */} + + + View on Mempool + + + ), footer: "The staking will continue in the background", @@ -63,10 +77,16 @@ const CONTENT: Record< type SuccessModalProps = { type: ActionFlowType tokenAmount: TokenAmount + txHash: string } -export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) { +export default function SuccessModal({ + type, + tokenAmount, + txHash, +}: SuccessModalProps) { const { closeModal } = useModal() + const navigate = useNavigate() const { header, footer, renderBody } = CONTENT[type] @@ -76,11 +96,19 @@ export default function SuccessModal({ type, tokenAmount }: SuccessModalProps) { - {renderBody(tokenAmount)} + {renderBody(tokenAmount, txHash)} - diff --git a/dapp/src/components/shared/Pagination/Pagination.tsx b/dapp/src/components/shared/Pagination/Pagination.tsx new file mode 100644 index 000000000..969d2eda5 --- /dev/null +++ b/dapp/src/components/shared/Pagination/Pagination.tsx @@ -0,0 +1,43 @@ +import React from "react" +import { PaginationContext } from "#/contexts" +import { StackProps, VStack } from "@chakra-ui/react" + +export type PaginationProps = Omit & { + data: T[] + pageSize?: number + defaultPage?: number +} + +function Pagination(props: PaginationProps) { + const { data, children, pageSize = 10, defaultPage = 0, ...restProps } = props + + const [page, setPage] = React.useState(defaultPage) + + const pageData = React.useMemo(() => { + const startIndex = page * pageSize + const endIndex = startIndex + pageSize + + return data.slice(startIndex, endIndex) + }, [data, page, pageSize]) + + const contextValue = React.useMemo( + () => ({ + pageSize, + page, + setPage, + totalSize: data.length, + pageData, + }), + [pageSize, page, data, pageData], + ) + + return ( + + + {children} + + + ) +} + +export default Pagination diff --git a/dapp/src/components/shared/Pagination/PaginationButton.tsx b/dapp/src/components/shared/Pagination/PaginationButton.tsx new file mode 100644 index 000000000..feb6c4d76 --- /dev/null +++ b/dapp/src/components/shared/Pagination/PaginationButton.tsx @@ -0,0 +1,43 @@ +import React from "react" +import { Icon, IconButton, IconButtonProps } from "@chakra-ui/react" +import { IconArrowLeft, IconArrowRight } from "@tabler/icons-react" +import { usePagination } from "#/hooks" + +type PaginationButtonProps = Omit & { + mode: "previous" | "next" +} + +function PaginationButton(props: PaginationButtonProps) { + const { mode, ...restProps } = props + const { page, setPage, totalSize, pageSize } = usePagination() + + const handleClick = () => setPage(mode === "next" ? page + 1 : page - 1) + const isDisabled = React.useMemo( + () => + mode === "next" ? page * pageSize + pageSize >= totalSize : page === 0, + [mode, page, pageSize, totalSize], + ) + + return ( + + } + aria-label={mode === "next" ? "Next" : "Previous"} + onClick={handleClick} + isDisabled={isDisabled} + {...restProps} + /> + ) +} + +export default PaginationButton diff --git a/dapp/src/components/shared/Pagination/PaginationPage.tsx b/dapp/src/components/shared/Pagination/PaginationPage.tsx new file mode 100644 index 000000000..bec5d8847 --- /dev/null +++ b/dapp/src/components/shared/Pagination/PaginationPage.tsx @@ -0,0 +1,75 @@ +import React from "react" +import { Box, Stack, StackProps, useToken } from "@chakra-ui/react" +import { useSize } from "@chakra-ui/react-use-size" +import { AnimatePresence, Transition, Variants, motion } from "framer-motion" +import { usePagination } from "#/hooks" + +const transition: Transition = { + type: "spring", + stiffness: 120, + damping: 16, + mass: 0.85, +} + +const variants: Variants = { + enter: ({ direction, spacing }) => ({ + x: `calc((100% + ${spacing}) * ${direction === "right" ? 1 : -1})`, + transition, + }), + center: { + x: 0, + transition, + }, + exit: ({ direction, spacing }) => ({ + x: `calc((100% + ${spacing}) * ${direction === "left" ? 1 : -1})`, + transition, + }), +} + +type PaginationPageProps = Omit & { + children: (pageData: T[]) => React.ReactNode + pageSpacing?: number | string +} + +function PaginationPage(props: PaginationPageProps) { + const { children, pageSpacing = 0, ...restProps } = props + const { page, pageData } = usePagination() + + const ref = React.useRef(null) + const { height } = useSize(ref) ?? { height: 0 } + + const previousPage = React.useRef(0) + React.useEffect(() => { + previousPage.current = page + }, [page]) + + const direction = page < previousPage.current ? "left" : "right" + const spacing = useToken("space", pageSpacing, "20%") + + return ( + + + + + {children(pageData as T[])} + + + + + ) +} + +export default PaginationPage diff --git a/dapp/src/components/shared/Pagination/PaginationStatus.tsx b/dapp/src/components/shared/Pagination/PaginationStatus.tsx new file mode 100644 index 000000000..d968bd013 --- /dev/null +++ b/dapp/src/components/shared/Pagination/PaginationStatus.tsx @@ -0,0 +1,28 @@ +import React from "react" +import { TextProps } from "@chakra-ui/react" +import { getPaginationState } from "#/components/TransactionHistory/Table/utils" +import { usePagination } from "#/hooks" +import { TextSm } from "../Typography" + +type PaginationStatusProps = TextProps & { + dataLabel?: string +} + +function PaginationStatus(props: PaginationStatusProps) { + const { dataLabel = "items", ...restProps } = props + const { page, pageSize, totalSize } = usePagination() + + const { rowMin: rangeStart, rowMax: rangeEnd } = getPaginationState( + page, + pageSize, + totalSize, + ) + + return ( + + Showing {rangeStart}-{rangeEnd} out of {totalSize} {dataLabel} + + ) +} + +export default PaginationStatus diff --git a/dapp/src/components/shared/Pagination/index.ts b/dapp/src/components/shared/Pagination/index.ts new file mode 100644 index 000000000..84337122b --- /dev/null +++ b/dapp/src/components/shared/Pagination/index.ts @@ -0,0 +1,4 @@ +export { default as Pagination } from "./Pagination" +export { default as PaginationStatus } from "./PaginationStatus" +export { default as PaginationPage } from "./PaginationPage" +export { default as PaginationButton } from "./PaginationButton" diff --git a/dapp/src/constants/chains.ts b/dapp/src/constants/chains.ts index 43d408d31..7574621b9 100644 --- a/dapp/src/constants/chains.ts +++ b/dapp/src/constants/chains.ts @@ -3,12 +3,12 @@ import { EthereumNetwork, BitcoinNetwork } from "@acre-btc/sdk" const BLOCK_EXPLORER_TESTNET = { ethereum: { title: "Etherscan", url: "https://sepolia.etherscan.io" }, - bitcoin: { title: "Mempool Space", url: "https://mempool.space/testnet" }, + bitcoin: { title: "Mempool", url: "https://mempool.space/testnet" }, } const BLOCK_EXPLORER_MAINNET = { ethereum: { title: "Etherscan", url: "https://etherscan.io" }, - bitcoin: { title: "Mempool Space", url: "https://mempool.space" }, + bitcoin: { title: "Mempool", url: "https://mempool.space" }, } export const BLOCK_EXPLORER: Record = diff --git a/dapp/src/contexts/PaginationContext.ts b/dapp/src/contexts/PaginationContext.ts new file mode 100644 index 000000000..170b4121f --- /dev/null +++ b/dapp/src/contexts/PaginationContext.ts @@ -0,0 +1,12 @@ +import React from "react" + +type PaginationContextType = { + pageSize: number + page: number + totalSize: number + setPage: React.Dispatch> + pageData: T[] +} | null + +export const PaginationContext = + React.createContext(null) diff --git a/dapp/src/contexts/index.tsx b/dapp/src/contexts/index.tsx index b4218417a..6edbbc898 100644 --- a/dapp/src/contexts/index.tsx +++ b/dapp/src/contexts/index.tsx @@ -4,3 +4,4 @@ export * from "./LedgerWalletAPIProvider" export * from "./DocsDrawerContext" export * from "./SidebarContext" export * from "./StakeFlowContext" +export * from "./PaginationContext" diff --git a/dapp/src/hooks/index.ts b/dapp/src/hooks/index.ts index 07fdc9e97..8f08a22d9 100644 --- a/dapp/src/hooks/index.ts +++ b/dapp/src/hooks/index.ts @@ -22,5 +22,6 @@ export * from "./useActivities" export * from "./useSize" export * from "./router" export * from "./useTransactionFee" +export * from "./usePagination" export * from "./useModal" export * from "./useTransactionModal" diff --git a/dapp/src/hooks/store/index.ts b/dapp/src/hooks/store/index.ts index 34a696f73..1cf08a580 100644 --- a/dapp/src/hooks/store/index.ts +++ b/dapp/src/hooks/store/index.ts @@ -7,5 +7,6 @@ export * from "./useActionFlowType" export * from "./useActionFlowStatus" export * from "./useActionFlowActiveStep" export * from "./useActionFlowTokenAmount" +export * from "./useActionFlowTxHash" export * from "./useCompletedActivities" export * from "./useLatestActivities" diff --git a/dapp/src/hooks/store/useActionFlowTxHash.ts b/dapp/src/hooks/store/useActionFlowTxHash.ts new file mode 100644 index 000000000..0dce7063e --- /dev/null +++ b/dapp/src/hooks/store/useActionFlowTxHash.ts @@ -0,0 +1,6 @@ +import { selectActionFlowTxHash } from "#/store/action-flow" +import { useAppSelector } from "./useAppSelector" + +export function useActionFlowTxHash() { + return useAppSelector(selectActionFlowTxHash) +} diff --git a/dapp/src/hooks/usePagination.ts b/dapp/src/hooks/usePagination.ts new file mode 100644 index 000000000..83f646fba --- /dev/null +++ b/dapp/src/hooks/usePagination.ts @@ -0,0 +1,10 @@ +import React from "react" +import { PaginationContext } from "#/contexts" + +export const usePagination = () => { + const context = React.useContext(PaginationContext) + if (!context) { + throw new Error("usePagination must be used within a PaginationProvider") + } + return context +} diff --git a/dapp/src/pages/DashboardPage/DashboardCard.tsx b/dapp/src/pages/DashboardPage/DashboardCard.tsx index ee6caf612..555e10f4c 100644 --- a/dapp/src/pages/DashboardPage/DashboardCard.tsx +++ b/dapp/src/pages/DashboardPage/DashboardCard.tsx @@ -1,23 +1,23 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ import React from "react" +import { BoostArrowIcon } from "#/assets/icons" +import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" +import IconTag from "#/components/shared/IconTag" +import { TextMd } from "#/components/shared/Typography" +import { useTransactionModal } from "#/hooks" +import { ACTION_FLOW_TYPES, AmountType } from "#/types" import { Button, - CardHeader, - CardBody, + ButtonProps, Card, + CardBody, + CardHeader, CardProps, - Tag, HStack, + Tag, VStack, - ButtonProps, } from "@chakra-ui/react" -import { TextMd } from "#/components/shared/Typography" -import IconTag from "#/components/shared/IconTag" -import { BoostArrowIcon } from "#/assets/icons" -import { CurrencyBalanceWithConversion } from "#/components/shared/CurrencyBalanceWithConversion" -import { ACTION_FLOW_TYPES, AmountType } from "#/types" import { ActivitiesList } from "#/components/shared/ActivitiesList" -import { useTransactionModal } from "#/hooks" +import TransactionHistory from "./TransactionHistory" const buttonStyles: ButtonProps = { size: "lg", @@ -40,7 +40,7 @@ export default function DashboardCard(props: DashboardCardProps) { const openDepositModal = useTransactionModal(ACTION_FLOW_TYPES.STAKE) return ( - + My position @@ -96,6 +96,7 @@ export default function DashboardCard(props: DashboardCardProps) { + ) diff --git a/dapp/src/pages/DashboardPage/DocsCard.tsx b/dapp/src/pages/DashboardPage/DocsCard.tsx index dafe74c04..b331af277 100644 --- a/dapp/src/pages/DashboardPage/DocsCard.tsx +++ b/dapp/src/pages/DashboardPage/DocsCard.tsx @@ -23,7 +23,7 @@ export function DocsCard(props: CardProps) { {...props} > - + Documentation Everything you need to know about our contracts. diff --git a/dapp/src/pages/DashboardPage/TransactionHistory.tsx b/dapp/src/pages/DashboardPage/TransactionHistory.tsx index cd80ee3bd..2aa60a1ab 100644 --- a/dapp/src/pages/DashboardPage/TransactionHistory.tsx +++ b/dapp/src/pages/DashboardPage/TransactionHistory.tsx @@ -1,41 +1,121 @@ import React from "react" import { - CardBody, + StackProps, + HStack, + VStack, Card, - CardProps, - Tabs, - TabList, - Tab, - TabPanels, - TabPanel, + CardBody, + Box, + Image, + VisuallyHidden, } from "@chakra-ui/react" -import { useWalletContext } from "#/hooks" -import AccountHistory from "#/components/TransactionHistory/Account" -import ProtocolHistory from "#/components/TransactionHistory/Protocol" +import { + Pagination, + PaginationButton, + PaginationPage, + PaginationStatus, +} from "#/components/shared/Pagination" +import { TextMd, TextSm } from "#/components/shared/Typography" +import { CurrencyBalance } from "#/components/shared/CurrencyBalance" +import emptyStateIllustration from "#/assets/images/empty-state.png" +import { displayBlockTimestamp } from "#/utils" +import { Activity } from "#/types" +import BlockExplorerLink from "#/components/shared/BlockExplorerLink" +import { IconArrowUpRight } from "@tabler/icons-react" +import { useCompletedActivities } from "#/hooks" -export default function TransactionHistory(props: CardProps) { - const { isConnected } = useWalletContext() +export default function TransactionHistory(props: StackProps) { + const completedActivities = useCompletedActivities() return ( - - - - - {isConnected && Account history} - Protocol history - - - {isConnected && ( - - - - )} - - - - - - - + + + Transactions + + + {completedActivities.length === 0 ? ( + + + You have no transactions yet! + + ) : ( + + + {(pageData: Activity[]) => + pageData.map(({ id, timestamp, type, txHash, amount }) => ( + + + + {displayBlockTimestamp(timestamp)} + + + + + {type} + + + + + + + + + + View transaction details + + + + )) + } + + + + + + + + + + + + )} + ) } diff --git a/dapp/src/store/action-flow/actionFlowSelectors.ts b/dapp/src/store/action-flow/actionFlowSelectors.ts index a814d6290..dd83e7517 100644 --- a/dapp/src/store/action-flow/actionFlowSelectors.ts +++ b/dapp/src/store/action-flow/actionFlowSelectors.ts @@ -13,3 +13,6 @@ export const selectActionFlowStatus = (state: RootState): ProcessStatus => export const selectActionFlowTokenAmount = ( state: RootState, ): TokenAmount | undefined => state.actionFlow.tokenAmount + +export const selectActionFlowTxHash = (state: RootState): string | undefined => + state.actionFlow.txHash diff --git a/dapp/src/store/action-flow/actionFlowSlice.ts b/dapp/src/store/action-flow/actionFlowSlice.ts index cf650d70c..31b670484 100644 --- a/dapp/src/store/action-flow/actionFlowSlice.ts +++ b/dapp/src/store/action-flow/actionFlowSlice.ts @@ -12,6 +12,7 @@ type ActionFlowState = { activeStep: number status: ProcessStatus tokenAmount?: TokenAmount + txHash?: string } const initialState: ActionFlowState = { @@ -19,6 +20,7 @@ const initialState: ActionFlowState = { activeStep: 1, status: PROCESS_STATUSES.IDLE, tokenAmount: undefined, + txHash: undefined, } export const actionFlowSlice = createSlice({ @@ -37,6 +39,9 @@ export const actionFlowSlice = createSlice({ setTokenAmount(state, action: PayloadAction) { state.tokenAmount = action.payload }, + setTxHash(state, action: PayloadAction) { + state.txHash = action.payload + }, goNextStep(state) { state.activeStep += 1 }, @@ -45,9 +50,16 @@ export const actionFlowSlice = createSlice({ state.activeStep = initialState.activeStep state.status = initialState.status state.tokenAmount = initialState.tokenAmount + state.txHash = initialState.txHash }, }, }) -export const { setType, setStatus, setTokenAmount, goNextStep, resetState } = - actionFlowSlice.actions +export const { + setType, + setStatus, + setTokenAmount, + setTxHash, + goNextStep, + resetState, +} = actionFlowSlice.actions diff --git a/dapp/src/store/wallet/walletSelector.ts b/dapp/src/store/wallet/walletSelector.ts index cf361c089..f77592b02 100644 --- a/dapp/src/store/wallet/walletSelector.ts +++ b/dapp/src/store/wallet/walletSelector.ts @@ -1,14 +1,17 @@ import { createSelector } from "@reduxjs/toolkit" -import { isActivityCompleted } from "#/utils" +import { isActivityCompleted, sortActivitiesByTimestamp } from "#/utils" import { RootState } from ".." export const selectLatestActivities = createSelector( (state: RootState) => state.wallet.latestActivities, - (latestActivities) => Object.values(latestActivities), + (latestActivities) => + sortActivitiesByTimestamp(Object.values(latestActivities)), ) export const selectCompletedActivities = createSelector( (state: RootState) => state.wallet.activities, (activities) => - activities.filter((activity) => isActivityCompleted(activity)), + sortActivitiesByTimestamp( + activities.filter((activity) => isActivityCompleted(activity)), + ), ) diff --git a/dapp/src/theme/Button.ts b/dapp/src/theme/Button.ts index 94a299791..192a48f80 100644 --- a/dapp/src/theme/Button.ts +++ b/dapp/src/theme/Button.ts @@ -120,14 +120,21 @@ export const buttonTheme: ComponentSingleStyleConfig = { pagination: { bg: "white", color: "grey.700", - border: "1px solid transparent", + ring: 0, + ringInset: "inset", + ringColor: "white", _hover: { - borderColor: "white", + color: "brand.400", bg: "opacity.white.6", + ring: 1, + }, + _active: { + ring: 1, + ringColor: "brand.400", }, _disabled: { - color: "grey.200", + color: "grey.300", bg: "white", opacity: 1, pointerEvents: "none", diff --git a/dapp/src/utils/activities.ts b/dapp/src/utils/activities.ts index d498dbf2a..cabe474c2 100644 --- a/dapp/src/utils/activities.ts +++ b/dapp/src/utils/activities.ts @@ -2,3 +2,8 @@ import { Activity } from "#/types" export const isActivityCompleted = (activity: Activity): boolean => activity.status === "completed" + +export const sortActivitiesByTimestamp = (activities: Activity[]): Activity[] => + activities.sort( + (activity1, activity2) => activity1.timestamp - activity2.timestamp, + ) diff --git a/dapp/src/utils/subgraphAPI.ts b/dapp/src/utils/subgraphAPI.ts index aede86138..e3f4bb50d 100644 --- a/dapp/src/utils/subgraphAPI.ts +++ b/dapp/src/utils/subgraphAPI.ts @@ -14,6 +14,7 @@ const mapToActivity = (activityData: ActivityDataResponse): Activity => { const status = events.some(({ type }) => type === "Finalized") ? "completed" : "pending" + const timestamp = parseInt(events[0].timestamp, 10) return {