Properly handle decimals in supports liquidate component. #7648
1 changed files with 69 additions and 34 deletions
|
@ -1,6 +1,6 @@
|
|||
// @flow
|
||||
import * as ICONS from 'constants/icons';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import CreditAmount from 'component/common/credit-amount';
|
||||
import Button from 'component/button';
|
||||
import { Form, FormField } from 'component/common/form';
|
||||
|
@ -24,67 +24,100 @@ type Props = {
|
|||
const SupportsLiquidate = (props: Props) => {
|
||||
const { claim, abandonSupportForClaim, handleClose, abandonClaimError } = props;
|
||||
const [previewBalance, setPreviewBalance] = useState(undefined);
|
||||
const [amount, setAmount] = useState(-1);
|
||||
const [defaultValueAssigned, setDefaultValueAssigned] = useState(false);
|
||||
const [unlockTextAmount, setUnlockTextAmount] = useState('');
|
||||
const [error, setError] = useState(false);
|
||||
const initialMessage = __('How much would you like to unlock?');
|
||||
const [message, setMessage] = useState(initialMessage);
|
||||
const amount = Number(unlockTextAmount) || 0;
|
||||
const defaultValue = previewBalance ? previewBalance * 0.25 : 0;
|
||||
const keep =
|
||||
amount >= 0
|
||||
? Boolean(previewBalance) && Number.parseFloat(String(Number(previewBalance) - Number(amount))).toFixed(8)
|
||||
: Boolean(previewBalance) && Number.parseFloat(String((Number(previewBalance) / 4) * 3)).toFixed(8); // default unlock 25%
|
||||
? Boolean(previewBalance) && Number.parseFloat(String(Number(previewBalance) - amount)).toFixed(8)
|
||||
: Boolean(previewBalance) && Number.parseFloat(String(defaultValue * 3)).toFixed(8);
|
||||
const claimId = claim && claim.claim_id;
|
||||
const type = claim.value_type;
|
||||
|
||||
useEffect(() => {
|
||||
if (claimId && abandonSupportForClaim) {
|
||||
abandonSupportForClaim(claimId, type, false, true).then(r => {
|
||||
abandonSupportForClaim(claimId, type, false, true).then((r) => {
|
||||
setPreviewBalance(r.total_input);
|
||||
});
|
||||
}
|
||||
}, [abandonSupportForClaim, claimId, type, setPreviewBalance]);
|
||||
|
||||
function handleSubmit() {
|
||||
abandonSupportForClaim(claimId, type, keep, false).then(r => {
|
||||
abandonSupportForClaim(claimId, type, keep, false).then((r) => {
|
||||
if (r) {
|
||||
handleClose();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleChange(a) {
|
||||
if (a === undefined || isNaN(Number(a))) {
|
||||
const handleRangeChange = useCallback(
|
||||
(newValue) => {
|
||||
setUnlockTextAmount(String(newValue));
|
||||
},
|
||||
[setUnlockTextAmount]
|
||||
);
|
||||
|
||||
const handleChangeUnlockText = useCallback(
|
||||
(newValue) => {
|
||||
// Get rid of all characters except digits, commas and periods.
|
||||
const onlyValidAmount = newValue.replace(/[^0-9.,]+/, '');
|
||||
setUnlockTextAmount(onlyValidAmount);
|
||||
},
|
||||
[setUnlockTextAmount]
|
||||
);
|
||||
|
||||
const handleUnlockTextFocus = useCallback(() => {
|
||||
// Get rid of empty zero when user starts typing (small ux improvement)
|
||||
if (Number(unlockTextAmount) === 0) {
|
||||
setUnlockTextAmount('');
|
||||
}
|
||||
}, [unlockTextAmount, setUnlockTextAmount]);
|
||||
|
||||
const handleUnlockTextBlur = useCallback(() => {
|
||||
if (!unlockTextAmount || isNaN(Number(unlockTextAmount))) {
|
||||
setUnlockTextAmount(previewBalance ? String(defaultValue) : '0');
|
||||
}
|
||||
}, [unlockTextAmount, setUnlockTextAmount, previewBalance, defaultValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultValueAssigned || !previewBalance || unlockTextAmount) {
|
||||
return;
|
||||
}
|
||||
setUnlockTextAmount(String(defaultValue));
|
||||
setDefaultValueAssigned(true);
|
||||
}, [defaultValueAssigned, previewBalance, unlockTextAmount, setUnlockTextAmount, setDefaultValueAssigned]);
|
||||
|
||||
// Update message & error based on unlock amount.
|
||||
useEffect(() => {
|
||||
const unlockAmount = Number(unlockTextAmount);
|
||||
const previewBalanceNumber = Number(previewBalance);
|
||||
if (unlockTextAmount && isNaN(unlockAmount)) {
|
||||
setMessage(__('Amount must be a number'));
|
||||
setError(true);
|
||||
setAmount(0);
|
||||
} else if (a === '') {
|
||||
setAmount(0);
|
||||
setError(true);
|
||||
setMessage(__('Amount cannot be blank'));
|
||||
} else if (Number(a) > Number(previewBalance)) {
|
||||
} else if (unlockAmount > previewBalanceNumber) {
|
||||
setMessage(__('Amount cannot be more than available'));
|
||||
setError(false);
|
||||
} else if (Number(a) === Number(previewBalance)) {
|
||||
setMessage(__(`She's about to close up the library!`));
|
||||
setAmount(a);
|
||||
setError(false);
|
||||
} else if (Number(a) > Number(previewBalance) / 2) {
|
||||
setMessage(__('Your content will do better with more staked on it'));
|
||||
setAmount(a);
|
||||
setError(false);
|
||||
} else if (Number(a) === 0) {
|
||||
setMessage(__('Amount cannot be zero'));
|
||||
setAmount(0);
|
||||
setError(true);
|
||||
} else if (Number(a) <= Number(previewBalance) / 2) {
|
||||
} else if (Math.abs(unlockAmount - previewBalanceNumber) <= Number.EPSILON) {
|
||||
setMessage(__(`She's about to close up the library!`));
|
||||
setError(false);
|
||||
} else if (unlockAmount > previewBalanceNumber / 2) {
|
||||
setMessage(__('Your content will do better with more staked on it'));
|
||||
setError(false);
|
||||
} else if (unlockAmount === 0) {
|
||||
setMessage(__('Amount cannot be zero'));
|
||||
setError(true);
|
||||
} else if (unlockAmount <= previewBalanceNumber / 2) {
|
||||
setMessage(__('A prudent choice'));
|
||||
setAmount(Number(a));
|
||||
setError(false);
|
||||
} else {
|
||||
setMessage(initialMessage);
|
||||
setAmount(a);
|
||||
setError(false);
|
||||
}
|
||||
}
|
||||
}, [unlockTextAmount, previewBalance, setMessage, setError]);
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
@ -140,8 +173,8 @@ const SupportsLiquidate = (props: Props) => {
|
|||
min={0}
|
||||
step={0.01}
|
||||
max={previewBalance}
|
||||
value={Number(amount) >= 0 ? amount : previewBalance / 4} // by default, set it to 25% of available
|
||||
onChange={e => handleChange(e.target.value)}
|
||||
value={amount}
|
||||
onChange={(e) => handleRangeChange(e.target.value)}
|
||||
/>
|
||||
<label className="range__label">
|
||||
<span>0</span>
|
||||
|
@ -150,9 +183,11 @@ const SupportsLiquidate = (props: Props) => {
|
|||
</label>
|
||||
<FormField
|
||||
type="text"
|
||||
value={amount >= 0 ? amount || '' : previewBalance && previewBalance / 4}
|
||||
value={unlockTextAmount}
|
||||
helper={message}
|
||||
onChange={e => handleChange(e.target.value)}
|
||||
onFocus={handleUnlockTextFocus}
|
||||
onChange={(e) => handleChangeUnlockText(e.target.value)}
|
||||
onBlur={handleUnlockTextBlur}
|
||||
/>
|
||||
</Form>
|
||||
)}
|
||||
|
|
Loading…
Reference in a new issue