Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ const SwapAndBridge = lazyWithRetry(
() => import(/* webpackChunkName: "RewardStaking" */ "./views/SwapAndBridge")
);
const DepositStatus = lazyWithRetry(() => import("./views/DepositStatus"));
const Transaction = lazyWithRetry(
() => import(/* webpackChunkName: "Transaction" */ "./views/Transaction")
);

function useRoutes() {
const [enableACXBanner, setEnableACXBanner] = useState(true);
Expand Down Expand Up @@ -113,6 +116,11 @@ const Routes: React.FC = () => {
<Suspense fallback={<BouncingDotsLoader />}>
<Switch>
<Route exact path="/transactions" component={Transactions} />
<Route
exact
path="/transaction/:depositTxnRef"
component={Transaction}
/>
<Route exact path="/pool" component={LiquidityPool} />
<Route
exact
Expand Down
49 changes: 49 additions & 0 deletions src/components/DepositsTable/AnimatedColorOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import styled from "@emotion/styled";
import { AnimatePresence, motion } from "framer-motion";
import { COLORS } from "utils";

type AnimationProps = {
initial?: Record<string, any>;
animate?: Record<string, any>;
exit?: Record<string, any>;
transition?: Record<string, any>;
};

type OverlayConfig = {
depositId: string;
color: "aqua" | "white";
animation: AnimationProps;
};

type Props = {
overlay: OverlayConfig | null;
};

export function AnimatedColorOverlay({ overlay }: Props) {
const props = overlay;
if (!props) return null;

const { depositId, color, animation } = props;

return (
<AnimatePresence>
<ColorOverlay
key={`overlay-${depositId}`}
className="color-overlay"
color={color}
{...animation}
/>
</AnimatePresence>
);
}

const ColorOverlay = styled(motion.div)<{ color: "aqua" | "yellow" | "white" }>`
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: ${({ color }) => COLORS[color]};
pointer-events: none;
z-index: 0;
`;
39 changes: 35 additions & 4 deletions src/components/DepositsTable/DataRow.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import styled from "@emotion/styled";
import { motion } from "framer-motion";
import { useHistory } from "react-router-dom";

import { Deposit } from "hooks/useDeposits";
import { COLORS, getConfig } from "utils";

Check warning on line 6 in src/components/DepositsTable/DataRow.tsx

View workflow job for this annotation

GitHub Actions / format-and-lint

'getConfig' is defined but never used

import { HeaderCells, ColumnKey } from "./HeadRow";
import { ColumnKey, HeaderCells } from "./HeadRow";
import { AssetCell } from "./cells/AssetCell";
import { AmountCell } from "./cells/AmountCell";
import { RouteCell } from "./cells/RouteCell";
Expand All @@ -17,6 +19,9 @@
import { RewardsCell } from "./cells/RewardsCell";
import { ActionsCell } from "./cells/ActionsCell";
import { useTokenFromAddress } from "hooks/useToken";
import { TimeAgoCell } from "./cells/TimeAgoCell";
import { useDepositRowAnimation } from "./hooks/useDepositRowAnimation";
import { AnimatedColorOverlay } from "./AnimatedColorOverlay";

type Props = {
deposit: Deposit;
Expand All @@ -35,6 +40,9 @@
disabledColumns = [],
onClickSpeedUp,
}: Props) {
const history = useHistory();
const { rowAnimation, overlayProps } = useDepositRowAnimation(deposit);

const swapToken = useTokenFromAddress(
deposit.swapToken?.address || "",
deposit.sourceChainId
Expand All @@ -51,13 +59,17 @@
deposit.destinationChainId
);

// Hide unsupported or unknown token deposits
if (!inputToken) {
return null;
}

const handleRowClick = () => {
history.push(`/transaction/${deposit.depositTxHash}`);
};

return (
<StyledRow>
<StyledRow onClick={handleRowClick} {...rowAnimation}>
<AnimatedColorOverlay overlay={overlayProps} />
{isColumnDisabled(disabledColumns, "asset") ? null : (
<AssetCell
inputToken={inputToken}
Expand Down Expand Up @@ -100,20 +112,39 @@
{isColumnDisabled(disabledColumns, "rewards") ? null : (
<RewardsCell deposit={deposit} width={headerCells.rewards.width} />
)}
{isColumnDisabled(disabledColumns, "timeAgo") ? null : (
<TimeAgoCell deposit={deposit} width={headerCells.timeAgo.width} />
)}
{isColumnDisabled(disabledColumns, "actions") ? null : (
<ActionsCell deposit={deposit} onClickSpeedUp={onClickSpeedUp} />
)}
</StyledRow>
);
}

const StyledRow = styled.tr`
const StyledRow = styled(motion.tr)`
position: relative;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap: 16px;
padding: 0px 24px;
border-width: 0px 1px 1px 1px;
border-style: solid;
border-color: ${COLORS["grey-600"]};
cursor: pointer;
overflow: hidden;
transform-origin: top;
transition: background-color 0.2s;

&:hover {
background-color: ${COLORS["grey-500"]};
}

& > td,
& > div:not(.color-overlay) {
position: relative;
z-index: 1;
}
`;
5 changes: 5 additions & 0 deletions src/components/DepositsTable/HeadRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ export const headerCells = {
label: "Rewards",
width: 128,
},
timeAgo: {
label: "Time",
width: 84,
},
actions: {
label: "",
width: 64,
Expand Down Expand Up @@ -102,6 +106,7 @@ const StyledHead = styled.thead``;
const StyledRow = styled.tr`
display: flex;
height: 40px;
justify-content: space-between;
align-items: center;
padding: 0px 24px;
gap: 16px;
Expand Down
38 changes: 21 additions & 17 deletions src/components/DepositsTable/PaginatedDepositsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Props = DepositsTableProps & {
initialPageSize?: number;
pageSizes?: number[];
displayPageNumbers?: boolean;
hasNoResults: boolean;
};

const DEFAULT_PAGE_SIZES = [10, 25, 50];
Expand All @@ -24,6 +25,7 @@ export function PaginatedDepositsTable({
totalCount,
pageSizes = DEFAULT_PAGE_SIZES,
displayPageNumbers = true,
hasNoResults,
...depositsTableProps
}: Props) {
const paginateValues = paginate({
Expand All @@ -36,23 +38,25 @@ export function PaginatedDepositsTable({
return (
<>
<DepositsTable {...depositsTableProps} />
<PaginationWrapper>
<Pagination
displayPageNumbers={displayPageNumbers}
onPageChange={onPageChange}
onPageSizeChange={onPageSizeChange}
pageList={paginateValues.pageList}
activeIndex={paginateValues.activeIndex}
disableBack={paginateValues.disableBack}
disableForward={paginateValues.disableForward}
hideStart={paginateValues.hideStart}
hideEnd={paginateValues.hideEnd}
lastPage={paginateValues.lastPage}
currentPage={currentPage}
pageSize={currentPageSize}
pageSizes={pageSizes}
/>
</PaginationWrapper>
{!hasNoResults && (
<PaginationWrapper>
<Pagination
displayPageNumbers={displayPageNumbers}
onPageChange={onPageChange}
onPageSizeChange={onPageSizeChange}
pageList={paginateValues.pageList}
activeIndex={paginateValues.activeIndex}
disableBack={paginateValues.disableBack}
disableForward={paginateValues.disableForward}
hideStart={paginateValues.hideStart}
hideEnd={paginateValues.hideEnd}
lastPage={paginateValues.lastPage}
currentPage={currentPage}
pageSize={currentPageSize}
pageSizes={pageSizes}
/>
</PaginationWrapper>
)}
</>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/DepositsTable/cells/ActionsCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ export function ActionsCell({ deposit, onClickSpeedUp }: Props) {
<ZapIconPersistent onClick={handleClickSpeedUp} />
) : null;

if (!speedUp && !slowRelayInfo) {
// This might be wrong. We want to show the actions if either sppedup or slowRelayInfo is there
return null;
}

return (
<StyledActionsCell>
<Blur />
Expand Down
9 changes: 6 additions & 3 deletions src/components/DepositsTable/cells/StatusCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,21 @@ function FilledStatusCell({ deposit, width }: Props) {
function PendingStatusCell({ width, deposit }: Props) {
const { isDelayed, isProfitable, isExpired } = useDepositStatus(deposit);

// On all transactions page, always show "Processing..." instead of "Fee too low"
const showAsProcessing = deposit.hideFeeTooLow || isProfitable;

return (
<StyledPendingStatusCell width={width}>
<Text
color={
(isProfitable && !isDelayed) || isExpired ? "light-200" : "yellow"
(showAsProcessing && !isDelayed) || isExpired ? "light-200" : "yellow"
}
>
{isExpired
? "Expired"
: isDelayed
? "Delayed"
: isProfitable
: showAsProcessing
? "Processing..."
: "Fee too low"}
</Text>
Expand All @@ -90,7 +93,7 @@ function PendingStatusCell({ width, deposit }: Props) {
>
<StyledInfoIcon />
</Tooltip>
) : isProfitable ? (
) : showAsProcessing ? (
<StyledLoadingIcon />
) : (
<Tooltip
Expand Down
48 changes: 48 additions & 0 deletions src/components/DepositsTable/cells/TimeAgoCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import styled from "@emotion/styled";
import { DateTime } from "luxon";
import { useEffect, useState } from "react";

import { Text } from "components/Text";
import { Deposit } from "hooks/useDeposits";

import { BaseCell } from "./BaseCell";
import { getTimeAgoText } from "./getTimeAgoText";

export function TimeAgoCell({
deposit,
width,
}: {
deposit: Deposit;
width: number;
}) {
const [timeAgoText, setTimeAgoText] = useState(() =>
getTimeAgoText(deposit.depositTime)
);

// Update every second for live time updates
useEffect(() => {
const interval = setInterval(() => {
setTimeAgoText(getTimeAgoText(deposit.depositTime));
}, 1000);
return () => clearInterval(interval);
}, [deposit.depositTime]);

const fullDateTime = DateTime.fromSeconds(deposit.depositTime).toFormat(
"dd LLL yyyy, hh:mm:ss a"
);

return (
<StyledTimeAgoCell width={width} title={fullDateTime}>
<Text color="light-200" size="sm">
{timeAgoText}
</Text>
</StyledTimeAgoCell>
);
}

const StyledTimeAgoCell = styled(BaseCell)`
display: flex;
align-items: center;
position: relative;
cursor: help;
`;
19 changes: 19 additions & 0 deletions src/components/DepositsTable/cells/getTimeAgoText.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DateTime } from "luxon";

export function getTimeAgoText(seconds: number): string {
const now = DateTime.now();
const depositTime = DateTime.fromSeconds(seconds);
const diff = now.diff(depositTime, ["minutes", "seconds"]).toObject();

const totalSeconds = Math.floor(diff.seconds || 0);
const totalMinutes = Math.floor((diff.minutes || 0) + totalSeconds / 60);

if (totalMinutes === 0) {
return "just now";
} else if (totalMinutes < 3) {
return `${totalMinutes}m ago`;
} else {
// After 3 minutes, show the actual date/time
return depositTime.toFormat("dd LLL, hh:mm a");
}
}
Loading
Loading