From f60a6879396ac13e644f2d19ddd0f255c6e14952 Mon Sep 17 00:00:00 2001 From: Carlos Andres Perez Ubeda Date: Thu, 9 Jan 2025 11:41:34 -0600 Subject: [PATCH 1/2] feat(finance-quick-transfer): enhance slider validation logic - src/sections/finance/components/finance-quick-transfer.tsx: - Add `canContinue` state to disable transfer when exceeding max amount. - Update slider `color` to show a warning for invalid values. - Remove unnecessary `focusOnSelect` in slider settings. - Implement `handleCarouselClick` to enable active item selection. - Adjust blur/input/slider change handlers to update `canContinue` state. - Disable transfer button if `canContinue` is false. --- .../components/finance-quick-transfer.tsx | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/sections/finance/components/finance-quick-transfer.tsx b/src/sections/finance/components/finance-quick-transfer.tsx index d0f7aed9..7bd941a2 100644 --- a/src/sections/finance/components/finance-quick-transfer.tsx +++ b/src/sections/finance/components/finance-quick-transfer.tsx @@ -35,7 +35,7 @@ import FinanceSearchProfileModal from '@src/sections/finance/components/finance- const STEP = 50; const MIN_AMOUNT = 0; -const AVATAR_SIZE = 40; +// const AVATAR_SIZE = 40; interface Props extends CardProps { title?: string; @@ -72,6 +72,7 @@ export default function FinanceQuickTransfer({ const [initialized, setInitialized] = useState(false); const [list, setList] = useState(initialList ?? []); const [amount, setAmount] = useState(0); + const [canContinue, setCanContinue] = useState(true); const confirm = useBoolean(); const MAX_AMOUNT = balance; @@ -107,7 +108,6 @@ export default function FinanceQuickTransfer({ centerMode: true, swipeToSlide: true, infinite: true, - focusOnSelect: true, centerPadding: '0px', rows: 1, slidesToShow: list?.length > 7 ? 7 : (list?.length ?? 1), @@ -153,7 +153,7 @@ export default function FinanceQuickTransfer({ if (currentProfile?.ownedBy?.address) { const profileId = currentProfile.id const address = currentProfile.ownedBy.address; - + setWalletAddress(address); dispatch(storeAddress({ address, profileId })); } @@ -198,25 +198,31 @@ export default function FinanceQuickTransfer({ // Handle changes in the slider const handleChangeSlider = useCallback((_event: Event, newValue: number | number[]) => { setAmount(newValue as number); - }, []); + if(newValue < MAX_AMOUNT) { + setCanContinue(true); + } + }, [MAX_AMOUNT]); // Handle changes in the input for the amount const handleChangeInput = useCallback((event: React.ChangeEvent) => { setAmount(Number(event.target.value)); - - // Send the focus back to the input field, this is a workaround for the slider carousel - setTimeout(() => { - event.target.focus(); - }, 25); - + if(Number(event.target.value) < MAX_AMOUNT) { + setCanContinue(true); + }else{ + setCanContinue(false); + } }, []); // Validate the amount on blur const handleBlur = useCallback(() => { + if(amount < MAX_AMOUNT) { + setCanContinue(true); + } + if (amount < 0) { setAmount(0); } else if (amount > MAX_AMOUNT) { - setAmount(MAX_AMOUNT); + setCanContinue(false); } }, [amount, MAX_AMOUNT]); @@ -228,6 +234,11 @@ export default function FinanceQuickTransfer({ dispatch(storeAddress({ address: '', profileId: '' })); }; + // Handle onClick for carousel items + const handleCarouselClick = (index: number) => { + carousel.setCurrentIndex(index); + }; + // If the stored address changes or if we typed a valid custom address, check if it exists in the carousel useEffect(() => { // Attempt to match the stored address + profileId @@ -318,7 +329,7 @@ export default function FinanceQuickTransfer({ }} > {list?.map((profile, index) => ( - + handleCarouselClick(index)}> Transfer Now From 05289307495da69be521ce813d95f470935d6740 Mon Sep 17 00:00:00 2001 From: jadapema Date: Thu, 9 Jan 2025 11:48:52 -0600 Subject: [PATCH 2/2] feat: change aproach of withdraw to select destination on tabs --- src/hooks/use-metamask.ts | 2 +- src/hooks/use-withdraw.ts | 4 +- .../finance-deposit-from-metamask.tsx | 4 +- .../finance/components/finance-deposit.tsx | 10 ++- .../components/finance-quick-transfer.tsx | 3 +- .../finance-withdraw-from-metamask.tsx | 10 ++- .../finance-withdraw-from-smart-account.tsx | 3 - .../finance/components/finance-withdraw.tsx | 64 +++---------------- 8 files changed, 28 insertions(+), 72 deletions(-) diff --git a/src/hooks/use-metamask.ts b/src/hooks/use-metamask.ts index ffffbceb..f5f6c247 100644 --- a/src/hooks/use-metamask.ts +++ b/src/hooks/use-metamask.ts @@ -28,5 +28,5 @@ export const useMetaMask = () => { } }; - return { address, connecting, connect }; + return { address, connecting, connect, setAddress }; }; diff --git a/src/hooks/use-withdraw.ts b/src/hooks/use-withdraw.ts index 66a26a5f..f1d1bcbf 100644 --- a/src/hooks/use-withdraw.ts +++ b/src/hooks/use-withdraw.ts @@ -1,13 +1,13 @@ import { useState } from 'react'; import { useSelector } from 'react-redux'; -import { encodeFunctionData, parseUnits } from 'viem'; +import { Address, encodeFunctionData, parseUnits } from 'viem'; import LedgerVaultAbi from '@src/config/abi/LedgerVault.json'; import { GLOBAL_CONSTANTS } from '@src/config-global'; import { useWeb3Session } from '@src/hooks/use-web3-session.ts'; import { ERRORS } from '@notifications/errors.ts'; interface WithdrawParams { - recipient: string; + recipient: Address; amount: number; } diff --git a/src/sections/finance/components/finance-deposit-from-metamask.tsx b/src/sections/finance/components/finance-deposit-from-metamask.tsx index 85b12c58..9f52d0e0 100644 --- a/src/sections/finance/components/finance-deposit-from-metamask.tsx +++ b/src/sections/finance/components/finance-deposit-from-metamask.tsx @@ -18,12 +18,12 @@ interface FinanceDepositFromMetamaskProps { const FinanceDepositFromMetamask: FC = ({ onClose }) => { const sessionData = useSelector((state: any) => state.auth.session); const depositHook = useDepositMetamask(); - const { address, connecting, connect } = useMetaMask(); + const { address, connecting, connect, setAddress } = useMetaMask(); if (connecting) return ; if (!address) return ; - return ; + return ; }; export default FinanceDepositFromMetamask; diff --git a/src/sections/finance/components/finance-deposit.tsx b/src/sections/finance/components/finance-deposit.tsx index a91100e4..2f275cee 100644 --- a/src/sections/finance/components/finance-deposit.tsx +++ b/src/sections/finance/components/finance-deposit.tsx @@ -47,6 +47,11 @@ interface FinanceDepositProps { * Callback for closing the modal / dialog. */ onClose: () => void; + + /** + * Callback to change the new address. + */ + onChangeWallet?: (address: Address) => void; } /** @@ -57,7 +62,7 @@ interface FinanceDepositProps { * - `depositHook` (generic or Metamask deposit hook) * - `onClose` */ -const FinanceDeposit: FC = ({ address, recipient, depositHook, onClose }) => { +const FinanceDeposit: FC = ({ address, recipient, depositHook, onClose, onChangeWallet }) => { const [amount, setAmount] = useState(); const [helperText, setHelperText] = useState(""); const { balance } = useGetMmcContractBalance(address); @@ -152,7 +157,7 @@ const FinanceDeposit: FC = ({ address, recipient, depositHo sx={{ mt: 1 }} fullWidth autoFocus - label="Amount to withdraw" + label="Amount to deposit" type="number" value={amount} onChange={handleAmountChange} @@ -170,6 +175,7 @@ const FinanceDeposit: FC = ({ address, recipient, depositHo balance={balance ?? 0} label={'Confirm'} onConfirmAction={handleConfirmDeposit} + onChangeWallet={onChangeWallet} onCloseAction={onClose} /> diff --git a/src/sections/finance/components/finance-quick-transfer.tsx b/src/sections/finance/components/finance-quick-transfer.tsx index 7bd941a2..dce5a3cd 100644 --- a/src/sections/finance/components/finance-quick-transfer.tsx +++ b/src/sections/finance/components/finance-quick-transfer.tsx @@ -23,7 +23,7 @@ import Box from '@mui/material/Box'; import CardHeader from '@mui/material/CardHeader'; import { CardProps } from '@mui/material/Card'; -// Project components +// LOCAL IMPORTS import { useBoolean } from '@src/hooks/use-boolean'; import Carousel, { CarouselArrows, useCarousel } from '@src/components/carousel'; import NeonPaper from '@src/sections/publication/NeonPaperContainer.tsx'; @@ -35,7 +35,6 @@ import FinanceSearchProfileModal from '@src/sections/finance/components/finance- const STEP = 50; const MIN_AMOUNT = 0; -// const AVATAR_SIZE = 40; interface Props extends CardProps { title?: string; diff --git a/src/sections/finance/components/finance-withdraw-from-metamask.tsx b/src/sections/finance/components/finance-withdraw-from-metamask.tsx index d57777f0..bd6b9c9d 100644 --- a/src/sections/finance/components/finance-withdraw-from-metamask.tsx +++ b/src/sections/finance/components/finance-withdraw-from-metamask.tsx @@ -3,25 +3,23 @@ import { FC } from 'react'; // LOCAL IMPORTS import { useMetaMask } from '@src/hooks/use-metamask'; -import { useWithdrawMetamask } from '@src/hooks/use-withdraw-metamask'; -import { useGetVaultBalance } from '@src/hooks/use-get-vault-balance'; import FinanceWithdraw from '@src/sections/finance/components/finance-withdraw'; import FinanceMetamaskLoader from '@src/sections/finance/components/finance-metamask-loader.tsx'; import FinanceMetamaskButton from '@src/sections/finance/components/finance-metamask-button.tsx'; +import { useWithdraw } from '@src/hooks/use-withdraw.ts'; interface FinanceWithdrawFromMetamaskProps { onClose: () => void; } const FinanceWithdrawFromMetamask: FC = ({ onClose }) => { - const withdrawHook = useWithdrawMetamask(); - const { address, connecting, connect } = useMetaMask(); - const { balance } = useGetVaultBalance(address); + const withdrawHook = useWithdraw(); + const { address, connecting, connect, setAddress } = useMetaMask(); if (connecting) return ; if (!address) return ; - return ; + return ; }; export default FinanceWithdrawFromMetamask; diff --git a/src/sections/finance/components/finance-withdraw-from-smart-account.tsx b/src/sections/finance/components/finance-withdraw-from-smart-account.tsx index f734892e..8c0a4eb9 100644 --- a/src/sections/finance/components/finance-withdraw-from-smart-account.tsx +++ b/src/sections/finance/components/finance-withdraw-from-smart-account.tsx @@ -1,6 +1,5 @@ import { FC } from 'react'; import { useWithdraw } from '@src/hooks/use-withdraw'; -import { useGetBalance } from '@src/hooks/use-get-balance'; import { useSelector } from 'react-redux'; import FinanceWithdraw from './finance-withdraw'; @@ -11,14 +10,12 @@ interface FinanceWithdrawFromSmartAccountProps { const FinanceWithdrawFromSmartAccount: FC = ({ onClose }) => { const sessionData = useSelector((state: any) => state.auth.session); const userAddress = sessionData?.address; - const { balance } = useGetBalance(); const withdrawHook = useWithdraw(); return ( ); diff --git a/src/sections/finance/components/finance-withdraw.tsx b/src/sections/finance/components/finance-withdraw.tsx index 821add00..73f75d97 100644 --- a/src/sections/finance/components/finance-withdraw.tsx +++ b/src/sections/finance/components/finance-withdraw.tsx @@ -1,3 +1,4 @@ +// REACT IMPORTS import { FC, useCallback, useEffect, useState } from 'react'; // VIEM IMPORTS @@ -14,7 +15,6 @@ import FinanceDialogsActions from '@src/sections/finance/components/finance-dial import TextMaxLine from '@src/components/text-max-line'; import { formatBalanceNumber } from '@src/utils/format-number'; import BoxRow from '@src/sections/finance/components/box-row'; -import { isValidAddress } from '@src/sections/finance/components/finance-quick-transfer'; import { UseWithdrawHook } from '@src/hooks/use-withdraw.ts'; import { truncateAddress } from '@src/utils/wallet.ts'; @@ -23,25 +23,25 @@ import { notifyError, notifySuccess, notifyWarning } from '@notifications/intern import { ERRORS } from '@notifications/errors'; import { WARNING } from '@notifications/warnings'; import { SUCCESS } from '@notifications/success'; +import { useGetBalance } from '@src/hooks/use-get-balance.ts'; // ---------------------------------------------------------------------- interface FinanceWithdrawProps { - address?: Address; // The connected wallet address + address: Address; // The connected wallet address withdrawHook: UseWithdrawHook; // Generic withdraw hook - balance: number | null; // Current user balance onClose: () => void; // Callback to close the modal/dialog + onChangeWallet?: (address: Address) => void; // Callback to change the new address. } // ---------------------------------------------------------------------- -const FinanceWithdraw: FC = ({ address, withdrawHook, balance, onClose }) => { +const FinanceWithdraw: FC = ({ address, withdrawHook, onClose, onChangeWallet }) => { const [amount, setAmount] = useState(); - const [destinationAddress, setDestinationAddress] = useState(''); - const [addressError, setAddressError] = useState(false); const [amountError, setAmountError] = useState(false); - const [amountHelperText, setAmountHelperText] = useState(''); // Dynamic helper text for amount + const [amountHelperText, setAmountHelperText] = useState(''); const [localLoading, setLocalLoading] = useState(false); + const { balance } = useGetBalance(); const { withdraw, loading: withdrawLoading, error } = withdrawHook; const RainbowEffect = localLoading || withdrawLoading ? NeonPaper : Box; @@ -54,17 +54,13 @@ const FinanceWithdraw: FC = ({ address, withdrawHook, bala const handleConfirmWithdraw = useCallback(async () => { if (!amount) return; - if (!destinationAddress || addressError) { - notifyWarning(WARNING.INVALID_WALLET_ADDRESS); - return; - } if (amount <= 0 || amount > (balance ?? 0)) { notifyWarning(WARNING.INVALID_WITHDRAW_AMOUNT); return; } try { setLocalLoading(true); - await withdraw({ amount, recipient: destinationAddress }); + await withdraw({ amount, recipient: address }); notifySuccess(SUCCESS.WITHDRAW_SUCCESSFULLY); onClose(); } catch (err: any) { @@ -72,7 +68,7 @@ const FinanceWithdraw: FC = ({ address, withdrawHook, bala } finally { setLocalLoading(false); } - }, [amount, destinationAddress, balance, withdraw, addressError, onClose]); + }, [amount, balance]); const handleAmountChange = (event: React.ChangeEvent) => { const value = Number(event.target.value); @@ -90,12 +86,6 @@ const FinanceWithdraw: FC = ({ address, withdrawHook, bala setAmountHelperText(errorMessage); }; - const handleInputChange = (event: React.ChangeEvent) => { - const value = event.target.value; - setDestinationAddress(value); - setAddressError(!isValidAddress(value)); - }; - return ( <> = ({ address, withdrawHook, bala error={amountError} helperText={amountHelperText} /> - - - - - to - - - - = ({ address, withdrawHook, bala label={'Confirm'} onConfirmAction={handleConfirmWithdraw} onCloseAction={onClose} + onChangeWallet={onChangeWallet} /> );