From 61a36fde746104b18c379e83b9dcacfcd9751edd Mon Sep 17 00:00:00 2001 From: Ignacio Date: Wed, 6 Mar 2024 12:16:43 +0800 Subject: [PATCH] feat: start with search and review modals --- src/features/core/components/base.tsx | 13 ++ src/features/staking/components/main-page.tsx | 1 - .../staking/components/modals/staking.tsx | 90 +++++--- .../staking/components/validators-table.tsx | 200 ++++++++++-------- 4 files changed, 190 insertions(+), 114 deletions(-) diff --git a/src/features/core/components/base.tsx b/src/features/core/components/base.tsx index 0cfce4b..f34917f 100644 --- a/src/features/core/components/base.tsx +++ b/src/features/core/components/base.tsx @@ -224,3 +224,16 @@ export const FloatingDropdown = ({ ); }; + +type SearchInputProps = React.DetailedHTMLProps< + React.InputHTMLAttributes, + HTMLInputElement +>; + +export const SearchInput = (props: SearchInputProps) => ( + +); diff --git a/src/features/staking/components/main-page.tsx b/src/features/staking/components/main-page.tsx index 9095701..81463bc 100644 --- a/src/features/staking/components/main-page.tsx +++ b/src/features/staking/components/main-page.tsx @@ -33,7 +33,6 @@ function StakingPage() { {isShowingDetails && canShowDetail && } - Validators diff --git a/src/features/staking/components/modals/staking.tsx b/src/features/staking/components/modals/staking.tsx index 00a0a35..2d7f19d 100644 --- a/src/features/staking/components/modals/staking.tsx +++ b/src/features/staking/components/modals/staking.tsx @@ -117,6 +117,68 @@ const StakingModal = () => { ); } + if (step === "review") { + return ( + <> +
+
+ REVIEW +
+
+ Get ready to stake your XION token with{" "} + {validator.description.moniker}. Press 'Confirm' to proceed. +
+
+
+ Staked Amount + {amountXION} + $24N +
+ {!!memo && ( +
+
{memo}
+
+ )} + + + ); + } + const getHasAmountError = () => !amountUSD || !availableTokens || @@ -135,33 +197,7 @@ const StakingModal = () => { ) return; - setIsLoading(true); - - const addresses: StakeAddresses = { - delegator: account.bech32Address, - validator: validator.operatorAddress, - }; - - stakeValidatorAction( - addresses, - getXionCoin(amountXIONParsed), - memo, - client, - staking, - ) - .then((fetchDataFn) => { - setStep("completed"); - - return fetchDataFn(); - }) - .catch(() => { - toast("Staking error", { - type: "error", - }); - }) - .finally(() => { - setIsLoading(false); - }); + setStep("review"); }; return ( diff --git a/src/features/staking/components/validators-table.tsx b/src/features/staking/components/validators-table.tsx index 3f51a38..be8d2cd 100644 --- a/src/features/staking/components/validators-table.tsx +++ b/src/features/staking/components/validators-table.tsx @@ -3,7 +3,12 @@ import BigNumber from "bignumber.js"; import { memo, useState } from "react"; -import { ButtonPill, NavLink } from "@/features/core/components/base"; +import { + ButtonPill, + NavLink, + SearchInput, + Title, +} from "@/features/core/components/base"; import { HeaderTitleBase } from "@/features/core/components/table"; import { useStaking } from "../context/hooks"; @@ -128,112 +133,135 @@ const HeaderTitle = HeaderTitleBase; const ValidatorsTable = () => { const { isConnected, staking } = useStaking(); const [sortMethod, setSortMethod] = useState("none"); + const [searchValue, setSearchValue] = useState(""); const { validators } = staking.state; if (!validators?.items.length) return null; - const sortedItems = validators.items.slice().sort((a, b) => { - if (sortMethod === "none") return 0; + const sortedItems = validators.items + .slice() + .sort((a, b) => { + if (sortMethod === "none") return 0; + + if (["voting-power-asc", "voting-power-desc"].includes(sortMethod)) { + const votingPowerA = getVotingPowerPerc(a.tokens, staking.state); + const votingPowerB = getVotingPowerPerc(b.tokens, staking.state); - if (["voting-power-asc", "voting-power-desc"].includes(sortMethod)) { - const votingPowerA = getVotingPowerPerc(a.tokens, staking.state); - const votingPowerB = getVotingPowerPerc(b.tokens, staking.state); + if (!votingPowerA || !votingPowerB) return 0; - if (!votingPowerA || !votingPowerB) return 0; + return sortMethod === "voting-power-asc" + ? votingPowerA - votingPowerB + : votingPowerB - votingPowerA; + } - return sortMethod === "voting-power-asc" - ? votingPowerA - votingPowerB - : votingPowerB - votingPowerA; - } + if (["commission-asc", "commission-desc"].includes(sortMethod)) { + const commissionA = parseFloat(a.commission.commissionRates.rate); + const commissionB = parseFloat(b.commission.commissionRates.rate); - if (["commission-asc", "commission-desc"].includes(sortMethod)) { - const commissionA = parseFloat(a.commission.commissionRates.rate); - const commissionB = parseFloat(b.commission.commissionRates.rate); + if (!commissionA || !commissionB) return 0; - if (!commissionA || !commissionB) return 0; + return sortMethod === "commission-asc" + ? commissionA - commissionB + : commissionB - commissionA; + } - return sortMethod === "commission-asc" - ? commissionA - commissionB - : commissionB - commissionA; - } + if (["name-asc", "name-desc"].includes(sortMethod)) { + const nameA = a.description.moniker.toLowerCase(); + const nameB = b.description.moniker.toLowerCase(); - if (["name-asc", "name-desc"].includes(sortMethod)) { - const nameA = a.description.moniker.toLowerCase(); - const nameB = b.description.moniker.toLowerCase(); + if (!nameA || !nameB) return 0; - if (!nameA || !nameB) return 0; + return sortMethod === "name-asc" + ? nameA.localeCompare(nameB) + : nameB.localeCompare(nameA); + } - return sortMethod === "name-asc" - ? nameA.localeCompare(nameB) - : nameB.localeCompare(nameA); - } + if (["staked-asc", "staked-desc"].includes(sortMethod)) { + const aTokens = new BigNumber(a.tokens); + const bTokens = new BigNumber(b.tokens); - if (["staked-asc", "staked-desc"].includes(sortMethod)) { - const aTokens = new BigNumber(a.tokens); - const bTokens = new BigNumber(b.tokens); + return sortMethod === "staked-asc" + ? aTokens.minus(bTokens).toNumber() + : bTokens.minus(aTokens).toNumber(); + } - return sortMethod === "staked-asc" - ? aTokens.minus(bTokens).toNumber() - : bTokens.minus(aTokens).toNumber(); - } + return 0; + }) + .filter((validator) => { + if (!searchValue) return true; - return 0; - }); + const moniker = validator.description.moniker.toLowerCase(); + const operatorAddress = validator.operatorAddress.toLowerCase(); + + return ( + moniker.includes(searchValue.toLowerCase()) || + operatorAddress.includes(searchValue.toLowerCase()) + ); + }); return ( -
-
-
- - Validator - - -
Staked Amount
-
- -
Commission
-
- +
+ Validators + setSearchValue(e.target.value)} + value={searchValue} + /> +
+
+
-
Voting Power
- +
+ + Validator + + +
Staked Amount
+
+ +
Commission
+
+ +
Voting Power
+
+
+ {sortedItems.map((validator) => ( + { + staking.dispatch( + setModalOpened({ + content: { validator }, + type: "delegate", + }), + ); + }} + staking={staking} + validator={validator} + /> + ))}
- {sortedItems.map((validator) => ( - { - staking.dispatch( - setModalOpened({ - content: { validator }, - type: "delegate", - }), - ); - }} - staking={staking} - validator={validator} - /> - ))} -
+ ); };