From 7588fc272bd615d9204ce026cf1e167cff017e05 Mon Sep 17 00:00:00 2001 From: Diogo Ferreira Date: Wed, 12 Jun 2024 16:22:19 +0100 Subject: [PATCH] Simplify confirm stack (#182) * - simplify confirm modal * - show TX instead of transaction on orders table on mobile * - rename StackInfo to StackDigest - Move StackDigest above orders * refactor StackModal - extract StackFrequencyAndDates - Rename StackOrdersProgress and move related orders componentd there * update github action node, bun versions --- .github/workflows/CI.yml | 10 +- .../stack-modal/StackFrequencyAndDates.tsx | 54 ++++++++ .../app/components/stack-modal/StackModal.tsx | 123 ++++++------------ ...ckProgress.tsx => StackOrdersProgress.tsx} | 47 ++++--- .../stack-modal/StackOrdersTable.tsx | 12 +- .../components/stackbox/ConfirmStackModal.tsx | 11 +- packages/app/utils/token.ts | 4 +- 7 files changed, 148 insertions(+), 113 deletions(-) create mode 100644 packages/app/components/stack-modal/StackFrequencyAndDates.tsx rename packages/app/components/stack-modal/{StackProgress.tsx => StackOrdersProgress.tsx} (60%) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2d78c43d..9658269a 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,15 +22,15 @@ jobs: runs-on: ubuntu-latest steps: - name: 🧑🏻‍💻 Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: 🥷 Setup node and bun - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 + with: + node-version: 21.1.0 - uses: oven-sh/setup-bun@v1 with: - node-version: lts/hydrogen - check-latest: true - + bun-version: latest - name: 🎪 Install dependencies run: bun install --immutable diff --git a/packages/app/components/stack-modal/StackFrequencyAndDates.tsx b/packages/app/components/stack-modal/StackFrequencyAndDates.tsx new file mode 100644 index 00000000..2dc62a5f --- /dev/null +++ b/packages/app/components/stack-modal/StackFrequencyAndDates.tsx @@ -0,0 +1,54 @@ +import { + StackOrderProps, + stackIsComplete, + stackIsFinishedWithFunds, + totalOrderSlotsDone, +} from "@/models"; +import { BodyText } from "@/ui"; +import { formatFrequencyHours, formatTimestampToDateWithTime } from "@/utils"; +import { ReactNode } from "react"; + +const StackDetail = ({ + title, + children, +}: { + title: string; + children: ReactNode; +}) => ( +
+ + {title} + + {children} +
+); + +export const StackFrequencyAndDates = ({ stackOrder }: StackOrderProps) => { + const orderSlots = stackOrder.orderSlots; + const firstSlot = orderSlots[0]; + const lastSlot = orderSlots[orderSlots.length - 1]; + const nextSlot = orderSlots[totalOrderSlotsDone(stackOrder)]; + + return ( +
+ + {formatTimestampToDateWithTime(firstSlot)} + + + {formatTimestampToDateWithTime(lastSlot)} + + + Every {formatFrequencyHours(Number(stackOrder.interval))} + + + {stackIsComplete(stackOrder) + ? "Complete" + : stackIsFinishedWithFunds(stackOrder) + ? "Finished with funds" + : stackOrder.cancelledAt + ? "Cancelled" + : formatTimestampToDateWithTime(nextSlot)} + +
+ ); +}; diff --git a/packages/app/components/stack-modal/StackModal.tsx b/packages/app/components/stack-modal/StackModal.tsx index 2b0cc1cd..715e0704 100644 --- a/packages/app/components/stack-modal/StackModal.tsx +++ b/packages/app/components/stack-modal/StackModal.tsx @@ -1,10 +1,10 @@ "use client"; import Link from "next/link"; -import { ReactNode, useState } from "react"; +import { useState } from "react"; import { cx } from "class-variance-authority"; -import { orderPairSymbolsText, totalOrderSlotsDone } from "@/models/order"; +import { orderPairSymbolsText } from "@/models/order"; import { Modal, ModalFooter, @@ -13,40 +13,40 @@ import { ModalContent, BodyText, ModalHeader, - TitleText, ModalBaseProps, DialogContent, DialogFooterActions, Dialog, } from "@/ui"; -import { - formatFrequencyHours, - formatTimestampToDateWithTime, -} from "@/utils/datetime"; + import { StackOrder, StackOrderProps, calculateStackAveragePrice, - totalStackOrdersDone, totalStacked, totalFundsUsed, stackIsFinishedWithFunds, stackIsComplete, stackRemainingFunds, } from "@/models/stack-order"; -import { formatTokenValue } from "@/utils/token"; -import { getDCAOrderContract } from "@stackly/sdk"; -import { getExplorerLink } from "@/utils/transaction"; -import { useEthersSigner } from "@/utils/ethers"; + import { DialogConfirmTransactionLoading, FromToStackTokenPair, TokenLogoPair, + TransactionLink, } from "@/components"; -import { StackProgress } from "@/components/stack-modal/StackProgress"; -import { StackOrdersTable } from "@/components/stack-modal/StackOrdersTable"; + +import { StackOrdersProgress } from "@/components/stack-modal/StackOrdersProgress"; +import { StackFrequencyAndDates } from "@/components/stack-modal/StackFrequencyAndDates"; + +import { formatTokenValue } from "@/utils/token"; +import { getDCAOrderContract } from "@stackly/sdk"; +import { getExplorerLink } from "@/utils/transaction"; +import { useEthersSigner } from "@/utils/ethers"; + import { ModalId, useModalContext, useNetworkContext } from "@/contexts"; -import { TransactionLink } from "./TransactionLink"; + import { Transaction } from "@/models/stack"; interface StackModalProps extends ModalBaseProps { @@ -75,11 +75,6 @@ export const StackModal = ({ const [cancellationTx, setCancellationTx] = useState(); - const orderSlots = stackOrder.orderSlots; - const firstSlot = orderSlots[0]; - const lastSlot = orderSlots[orderSlots.length - 1]; - const nextSlot = orderSlots[totalOrderSlotsDone(stackOrder)]; - const stackRemainingFundsWithTokenText = `${stackRemainingFunds( stackOrder )} ${stackOrder.sellToken.symbol}`; @@ -183,43 +178,15 @@ export const StackModal = ({ -
- - {formatTimestampToDateWithTime(firstSlot)} - - - {formatTimestampToDateWithTime(lastSlot)} - - - Every {formatFrequencyHours(Number(stackOrder.interval))} - - - {stackIsComplete(stackOrder) - ? "Complete" - : stackIsFinishedWithFunds(stackOrder) - ? "Finished with funds" - : stackOrder.cancelledAt - ? "Cancelled" - : formatTimestampToDateWithTime(nextSlot)} - -
+
- {stackIsFinishedWithFunds(stackOrder) && ( -
- -
- )} +
- - Orders - - - - {totalStackOrdersDone(stackOrder) > 0 && ( - - )} + +
( +const StackDigest = ({ stackOrder }: StackOrderProps) => (
(
); -const HasRemainingFundsAlertMessage = ({ - remainingFundsWithSymbol, -}: { - remainingFundsWithSymbol: string; -}) => ( -
- - This contract has {remainingFundsWithSymbol} remaining funds. - -
-); +interface WarningHasRemainingFundsProps extends StackOrderProps { + stackRemainingFundsWithTokenText: string; +} -const StackDetail = ({ - title, - children, -}: { - title: string; - children: ReactNode; -}) => ( -
- - {title} - - {children} -
-); +const WarningHasRemainingFunds = ({ + stackOrder, + stackRemainingFundsWithTokenText, +}: WarningHasRemainingFundsProps) => { + if (!stackIsFinishedWithFunds(stackOrder)) return; + + return ( +
+
+ + This contract has {stackRemainingFundsWithTokenText} remaining funds. + +
+
+ ); +}; diff --git a/packages/app/components/stack-modal/StackProgress.tsx b/packages/app/components/stack-modal/StackOrdersProgress.tsx similarity index 60% rename from packages/app/components/stack-modal/StackProgress.tsx rename to packages/app/components/stack-modal/StackOrdersProgress.tsx index 9c65d214..99c80679 100644 --- a/packages/app/components/stack-modal/StackProgress.tsx +++ b/packages/app/components/stack-modal/StackOrdersProgress.tsx @@ -4,7 +4,7 @@ import { totalOrderSlotsDone, } from "@/models/order"; import { OrdersProgressBar } from "@/components/OrdersProgressBar"; -import { BodyText } from "@/ui"; +import { BodyText, TitleText } from "@/ui"; import { TokenIcon } from "@/components/TokenIcon"; import { StackOrderProps, @@ -14,26 +14,37 @@ import { stackIsComplete, } from "@/models/stack-order"; import { formatTokenValue } from "@/utils/token"; +import { StackOrdersTable } from "@/components/stack-modal/StackOrdersTable"; -export const StackProgress = ({ stackOrder }: StackOrderProps) => ( -
-
- -
- - Total funds used:{" "} - - {formatTokenValue(totalFundsUsed(stackOrder), 2)}{" "} - of{" "} - {totalFundsAmountWithTokenText(stackOrder)} - - - +export const StackOrdersProgress = ({ stackOrder }: StackOrderProps) => ( + <> +
+ + Orders + +
+
+ +
+ + Total funds used:{" "} + + {formatTokenValue(totalFundsUsed(stackOrder), 2)}{" "} + of{" "} + {totalFundsAmountWithTokenText(stackOrder)} + + + +
+
+ +
- - -
+ {totalStackOrdersDone(stackOrder) > 0 && ( + + )} + ); const TotalStackEstimationText = ({ stackOrder }: StackOrderProps) => { diff --git a/packages/app/components/stack-modal/StackOrdersTable.tsx b/packages/app/components/stack-modal/StackOrdersTable.tsx index 8f8ac4dd..9d9f2798 100644 --- a/packages/app/components/stack-modal/StackOrdersTable.tsx +++ b/packages/app/components/stack-modal/StackOrdersTable.tsx @@ -44,7 +44,10 @@ export const StackOrdersTable = ({ stackOrder }: StackOrderProps) => { - Transaction + + Transaction + Tx + Time @@ -127,7 +130,12 @@ const TableCowBody = ({ target="_blank" href={cowExplorerUrl(chainId, cowOrder.uid)} > - {addressShortner(cowOrder.uid)} + + {addressShortner(cowOrder.uid, 2)} + + + {addressShortner(cowOrder.uid)} + diff --git a/packages/app/components/stackbox/ConfirmStackModal.tsx b/packages/app/components/stackbox/ConfirmStackModal.tsx index 69666a7a..f6de8fe2 100644 --- a/packages/app/components/stackbox/ConfirmStackModal.tsx +++ b/packages/app/components/stackbox/ConfirmStackModal.tsx @@ -207,7 +207,10 @@ export const ConfirmStackModal = ({ {amountPerOrder} {fromToken.symbol} - , every {FREQUENCY_OPTIONS[frequency]} +
+ + every {FREQUENCY_OPTIONS[frequency]} +
@@ -220,15 +223,13 @@ export const ConfirmStackModal = ({ {format(endTime, "dd MMM yy, HH:mm")}
- - Total funds to be used - + Total funds {amount} {fromToken.symbol}
- Stack fee + Fee 0.25%
diff --git a/packages/app/utils/token.ts b/packages/app/utils/token.ts index c8f1cb4e..24eab965 100644 --- a/packages/app/utils/token.ts +++ b/packages/app/utils/token.ts @@ -1,5 +1,5 @@ -export const addressShortner = (address: string) => - address.slice(0, 4) + "..." + address.slice(-4); +export const addressShortner = (address: string, elements: number = 4) => + address.slice(0, elements) + "..." + address.slice(-elements); export const formatTokenValue = ( value: number | string,