-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: wallet-ui send workflow allow return back #468
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||
import { KeyboardEvent, useEffect } from 'react'; | ||||||
import { KeyboardEvent, useCallback, useEffect } from 'react'; | ||||||
import { InputHTMLAttributes, useRef, useState } from 'react'; | ||||||
import { HelperText } from '../../atom/HelperText'; | ||||||
import { Label } from '../../atom/Label'; | ||||||
|
@@ -20,6 +20,7 @@ interface Props extends InputHTMLAttributes<HTMLInputElement> { | |||||
error?: boolean; | ||||||
helperText?: string; | ||||||
label?: string; | ||||||
value?: string; | ||||||
decimalsMax?: number; | ||||||
asset: Erc20TokenBalance; | ||||||
onChangeCustom?: (value: string) => void; | ||||||
|
@@ -30,72 +31,64 @@ export const AmountInputView = ({ | |||||
error, | ||||||
helperText, | ||||||
label, | ||||||
value, | ||||||
decimalsMax = 18, | ||||||
asset, | ||||||
onChangeCustom, | ||||||
...otherProps | ||||||
}: Props) => { | ||||||
const [focused, setFocused] = useState(false); | ||||||
const inputRef = useRef<HTMLInputElement>(null); | ||||||
const [inputValue, setInputValue] = useState(value || ''); // Manage the input's value | ||||||
const [totalPrice, setTotalPrice] = useState(''); | ||||||
const [usdMode, setUsdMode] = useState(false); | ||||||
|
||||||
const fetchTotalPrice = () => { | ||||||
const inputValue = inputRef.current?.value || ''; | ||||||
const fetchTotalPrice = useCallback(() => { | ||||||
if (asset.usdPrice && inputValue && inputValue !== '.') { | ||||||
const inputFloat = parseFloat(inputValue); | ||||||
setTotalPrice(getAmountPrice(asset, inputFloat, usdMode)); | ||||||
} else { | ||||||
setTotalPrice(''); | ||||||
} | ||||||
}; | ||||||
}, [asset, inputValue, usdMode]); | ||||||
|
||||||
const resizeInput = () => { | ||||||
if (inputRef.current !== null) | ||||||
inputRef.current.style.width = | ||||||
inputRef.current.value.length * 8 + 6 + 'px'; | ||||||
}; | ||||||
const resizeInput = useCallback(() => { | ||||||
if (inputRef.current !== null) { | ||||||
inputRef.current.style.width = inputValue.length * 8 + 6 + 'px'; | ||||||
} | ||||||
}, [inputValue]); | ||||||
|
||||||
const triggerOnChange = () => { | ||||||
//If we are in USD mode we sent the eth amount as the value | ||||||
let valueToSend = inputRef.current?.value || ''; | ||||||
const triggerOnChange = (newValue: string) => { | ||||||
setInputValue(newValue); | ||||||
if (onChangeCustom) { | ||||||
if ( | ||||||
usdMode && | ||||||
asset.usdPrice && | ||||||
inputRef.current?.value && | ||||||
inputRef.current?.value !== '.' | ||||||
) { | ||||||
const inputFloat = parseFloat(inputRef.current.value); | ||||||
let valueToSend = newValue; | ||||||
if (usdMode && asset.usdPrice && newValue && newValue !== '.') { | ||||||
const inputFloat = parseFloat(newValue); | ||||||
valueToSend = getAmountPrice(asset, inputFloat, usdMode); | ||||||
} | ||||||
onChangeCustom(valueToSend); | ||||||
} | ||||||
}; | ||||||
|
||||||
const handleOnKeyUp = () => { | ||||||
//Resize the input depending on content | ||||||
useEffect(() => { | ||||||
// Adjust the input size whenever the value changes | ||||||
resizeInput(); | ||||||
inputRef.current && fetchTotalPrice(); | ||||||
}; | ||||||
|
||||||
}, [resizeInput]); | ||||||
const handleOnKeyDown = (event: KeyboardEvent<HTMLInputElement>) => { | ||||||
//Only accept numeric and decimals | ||||||
if ( | ||||||
(!/[0-9]|\./.test(event.key) || | ||||||
(event.key === '.' && | ||||||
inputRef.current && | ||||||
inputRef.current.value.includes('.'))) && | ||||||
(event.key === '.' && inputValue.includes('.'))) && | ||||||
!isSpecialInputKey(event) | ||||||
) { | ||||||
event.preventDefault(); | ||||||
return; | ||||||
} | ||||||
|
||||||
//Check decimals | ||||||
if (inputRef.current && inputRef.current.value.includes('.')) { | ||||||
const decimalIndex = inputRef.current.value.indexOf('.'); | ||||||
const decimals = inputRef.current.value.substring(decimalIndex); | ||||||
if (inputValue.includes('.')) { | ||||||
const decimalIndex = inputValue.indexOf('.'); | ||||||
const decimals = inputValue.substring(decimalIndex); | ||||||
if (decimals.length >= decimalsMax && !isSpecialInputKey(event)) { | ||||||
event.preventDefault(); | ||||||
return; | ||||||
|
@@ -110,29 +103,29 @@ export const AmountInputView = ({ | |||||
}; | ||||||
|
||||||
const handleMaxClick = () => { | ||||||
if (inputRef.current && asset.usdPrice) { | ||||||
if (value && asset.usdPrice) { | ||||||
const amountStr = ethers.utils | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no need to check the value here, as either the value is empty or not, the Max button should behave the same |
||||||
.formatUnits(asset.amount, asset.decimals) | ||||||
.toString(); | ||||||
const amountFloat = parseFloat(amountStr); | ||||||
inputRef.current.value = usdMode | ||||||
const value = usdMode | ||||||
? getAmountPrice(asset, amountFloat, false) | ||||||
: amountStr; | ||||||
fetchTotalPrice(); | ||||||
resizeInput(); | ||||||
triggerOnChange(); | ||||||
Comment on lines
114
to
115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
this 2 can be removed, as they will triggered at onEffect |
||||||
triggerOnChange(value); | ||||||
} | ||||||
}; | ||||||
|
||||||
useEffect(() => { | ||||||
if (inputRef.current?.value && inputRef.current?.value !== '.') { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this useEffect block is no need, as setInputValue has fired in triggerOnChange |
||||||
inputRef.current.value = totalPrice; | ||||||
fetchTotalPrice(); | ||||||
triggerOnChange(); | ||||||
resizeInput(); | ||||||
if (value !== undefined) { | ||||||
setInputValue(value); | ||||||
} | ||||||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||||||
}, [usdMode]); | ||||||
}, [value]); | ||||||
|
||||||
useEffect(() => { | ||||||
fetchTotalPrice(); | ||||||
}, [fetchTotalPrice]); | ||||||
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
remove the useCallback , but move it to useEffect for easier understand |
||||||
return ( | ||||||
<Wrapper> | ||||||
|
@@ -150,14 +143,14 @@ export const AmountInputView = ({ | |||||
<Left> | ||||||
<Input | ||||||
error={error} | ||||||
value={inputValue} | ||||||
disabled={disabled} | ||||||
focused={focused} | ||||||
onFocus={() => setFocused(true)} | ||||||
onBlur={() => setFocused(false)} | ||||||
ref={inputRef} | ||||||
onKeyUp={() => handleOnKeyUp()} | ||||||
onKeyDown={(event) => handleOnKeyDown(event)} | ||||||
onChange={(event) => triggerOnChange()} | ||||||
onChange={(event) => triggerOnChange(event.target.value)} | ||||||
{...otherProps} | ||||||
/> | ||||||
{!usdMode && ( | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||
import { useRef, useState } from 'react'; | ||||||||||||||||||||||||||
import { useEffect, useRef, useState } from 'react'; | ||||||||||||||||||||||||||
import { AmountInput } from 'components/ui/molecule/AmountInput'; | ||||||||||||||||||||||||||
import { SendSummaryModal } from '../SendSummaryModal'; | ||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||
|
@@ -47,6 +47,18 @@ export const SendModalView = ({ closeModal }: Props) => { | |||||||||||||||||||||||||
const debounceRef = useRef<NodeJS.Timeout | null>(null); | ||||||||||||||||||||||||||
const [loading, setLoading] = useState(false); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
useEffect(() => {}, [fields]); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is the purpose to have the useEffect? |
||||||||||||||||||||||||||
const handleBack = (amount: string, address: string) => { | ||||||||||||||||||||||||||
setSummaryModalOpen(false); | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
setFields((prevFields) => ({ | ||||||||||||||||||||||||||
...prevFields, | ||||||||||||||||||||||||||
amount: amount, | ||||||||||||||||||||||||||
address: address, | ||||||||||||||||||||||||||
})); | ||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Comment on lines
+52
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
setFields is not necessary, as the user still in the send model after the confirmation model render, the state will be remained |
||||||||||||||||||||||||||
const handleChange = (fieldName: string, fieldValue: string) => { | ||||||||||||||||||||||||||
//Check if input amount does not exceed user balance | ||||||||||||||||||||||||||
setErrors((prevErrors) => ({ | ||||||||||||||||||||||||||
|
@@ -142,6 +154,7 @@ export const SendModalView = ({ closeModal }: Props) => { | |||||||||||||||||||||||||
label="To" | ||||||||||||||||||||||||||
placeholder="Paste recipient address or .stark name here" | ||||||||||||||||||||||||||
onChange={(value) => handleChange('address', value.target.value)} | ||||||||||||||||||||||||||
value={fields.address} | ||||||||||||||||||||||||||
disableValidate | ||||||||||||||||||||||||||
validateError={errors.address} | ||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||
|
@@ -157,6 +170,7 @@ export const SendModalView = ({ closeModal }: Props) => { | |||||||||||||||||||||||||
<AmountInput | ||||||||||||||||||||||||||
label="Amount" | ||||||||||||||||||||||||||
onChangeCustom={(value) => handleChange('amount', value)} | ||||||||||||||||||||||||||
value={fields.amount} | ||||||||||||||||||||||||||
error={errors.amount !== '' ? true : false} | ||||||||||||||||||||||||||
helperText={errors.amount} | ||||||||||||||||||||||||||
decimalsMax={wallet.erc20TokenBalanceSelected.decimals} | ||||||||||||||||||||||||||
|
@@ -198,6 +212,7 @@ export const SendModalView = ({ closeModal }: Props) => { | |||||||||||||||||||||||||
{summaryModalOpen && ( | ||||||||||||||||||||||||||
<SendSummaryModal | ||||||||||||||||||||||||||
closeModal={closeModal} | ||||||||||||||||||||||||||
handleBack={handleBack} | ||||||||||||||||||||||||||
address={resolvedAddress} | ||||||||||||||||||||||||||
amount={fields.amount} | ||||||||||||||||||||||||||
chainId={fields.chainId} | ||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -39,6 +39,7 @@ interface Props { | |||||
amount: string; | ||||||
chainId: string; | ||||||
closeModal?: () => void; | ||||||
handleBack: (amount: string, address: string) => void; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
selectedFeeToken: FeeToken; | ||||||
} | ||||||
|
||||||
|
@@ -47,6 +48,7 @@ export const SendSummaryModalView = ({ | |||||
amount, | ||||||
chainId, | ||||||
closeModal, | ||||||
handleBack, | ||||||
selectedFeeToken, | ||||||
}: Props) => { | ||||||
const wallet = useAppSelector((state) => state.wallet); | ||||||
|
@@ -316,8 +318,12 @@ export const SendSummaryModalView = ({ | |||||
)} | ||||||
</Wrapper> | ||||||
<Buttons> | ||||||
<ButtonStyled onClick={closeModal} backgroundTransparent borderVisible> | ||||||
REJECT | ||||||
<ButtonStyled | ||||||
onClick={() => handleBack(amount, address)} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
backgroundTransparent | ||||||
borderVisible | ||||||
> | ||||||
BACK | ||||||
</ButtonStyled> | ||||||
<ButtonStyled | ||||||
enabled={!estimatingGas && !gasFeesError && !totalExceedsBalance} | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as below, remove the useCallback