address, alias and amount validation
Signed-off-by: PRavaga <trueravaga@gmail.com>
This commit is contained in:
parent
94e1b6151f
commit
c24462d7db
4 changed files with 44 additions and 183 deletions
|
|
@ -2,10 +2,9 @@ import React from "react";
|
|||
import nextId from "react-id-generator";
|
||||
import s from "./MyInput.module.scss";
|
||||
|
||||
const MyInput = ({ label, value, noActiveBorder, ...props }) => {
|
||||
const MyInput = ({ label, value, noActiveBorder, isValid, ...props }) => {
|
||||
const id = nextId();
|
||||
const inputClasses =
|
||||
value.length && !noActiveBorder > 0 ? "_input-filled" : "";
|
||||
const inputClasses = isValid && !noActiveBorder > 0 ? "_input-filled" : "";
|
||||
|
||||
return (
|
||||
<div className={s.myInput}>
|
||||
|
|
@ -21,4 +20,4 @@ const MyInput = ({ label, value, noActiveBorder, ...props }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default MyInput;
|
||||
export default MyInput;
|
||||
|
|
|
|||
|
|
@ -1,100 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from "react";
|
||||
import checkIcon from "../../../assets/svg/check.svg";
|
||||
import aliasIcon from "../../../assets/svg/contacts.svg";
|
||||
import mainStyles from "../WalletSend.module.scss";
|
||||
import s from "./AddressInput.module.scss";
|
||||
import { getAliasDetails, getAlias } from "../../../../background/wallet";
|
||||
|
||||
const AddressInput = ({ address }) => {
|
||||
const textareaRef = useRef(null);
|
||||
const [aliasVisible, setAliasVisible] = useState(false);
|
||||
const [alias, setAlias] = useState({ value: "", address: "" });
|
||||
|
||||
const buttonClasses = aliasVisible
|
||||
? [s.addAliasBtn, s.active].join(" ")
|
||||
: s.addAliasBtn;
|
||||
|
||||
const getTextAreaClasses = () => {
|
||||
const aliasVisibleClass = aliasVisible && address.value && s.thinText;
|
||||
const inputFilledClass = address.value.length && "_input-filled";
|
||||
return [aliasVisibleClass, inputFilledClass].join(" ");
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
handleInput();
|
||||
}, []);
|
||||
|
||||
const handleInput = () => {
|
||||
textareaRef.current.style.height = "41px";
|
||||
textareaRef.current.style.height = textareaRef.current.scrollHeight + "px";
|
||||
};
|
||||
|
||||
const toggleAlias = async () => {
|
||||
if (!aliasVisible && address.value) {
|
||||
const aliasValue = await getAlias(address.value);
|
||||
if (aliasValue) {
|
||||
setAlias({ value: aliasValue, address: address.value });
|
||||
setAliasVisible(true);
|
||||
} else {
|
||||
const addr = await getAliasDetails(address.value);
|
||||
if (addr) {
|
||||
setAlias({ value: address.value, address: addr });
|
||||
setAliasVisible(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setAliasVisible(!aliasVisible);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAliasChange = async (e) => {
|
||||
const aliasValue = e.target.value;
|
||||
const addr = await getAliasDetails(aliasValue);
|
||||
if (addr) {
|
||||
setAlias({ value: aliasValue, address: addr });
|
||||
address.onChange({ target: { value: addr } }); // set address to resolved address from alias
|
||||
setAliasVisible(true);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<label className={mainStyles.label} htmlFor="address-wallet-send">
|
||||
Address:
|
||||
{address.value && (
|
||||
<button className={buttonClasses} onClick={toggleAlias}>
|
||||
<img src={aliasIcon} alt="add alias button icon" />
|
||||
</button>
|
||||
)}
|
||||
</label>
|
||||
|
||||
<div className={s.textArea}>
|
||||
{aliasVisible && (
|
||||
<div className={s.textAreaAlias}>
|
||||
@ <input value={alias.value} onChange={handleAliasChange} />
|
||||
<span>
|
||||
<img src={checkIcon} alt="check icon" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<textarea
|
||||
disabled={aliasVisible}
|
||||
ref={textareaRef}
|
||||
value={alias.address || address.value}
|
||||
onChange={address.onChange}
|
||||
onInput={handleInput}
|
||||
placeholder={
|
||||
aliasVisible
|
||||
? alias.address
|
||||
: "Enter the Recipient's Address or Alias"
|
||||
}
|
||||
className={getTextAreaClasses()}
|
||||
id="address-wallet-send"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AddressInput;
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
@use "sass:math";
|
||||
|
||||
.textArea {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.textAreaAlias {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 0;
|
||||
padding: 0 15px;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
input {
|
||||
background-color: transparent;
|
||||
color: #ffffff;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 100%;
|
||||
padding-right: 40px;
|
||||
}
|
||||
span {
|
||||
flex: 0 0 15px;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
border: 2px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 8px;
|
||||
background-color: #0C0C3A;
|
||||
width: 100%;
|
||||
resize: none;
|
||||
min-height: 41px;
|
||||
font-weight: 300;
|
||||
line-height: math.div(21, 18);
|
||||
color: #ffffff;
|
||||
padding: 8px 12px 8px 12px;
|
||||
transition: all 0.1s ease 0s;
|
||||
transition-property: padding, font-size, color;
|
||||
overflow: hidden;
|
||||
&:focus {
|
||||
border-color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
&::placeholder {
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
&.thinText {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
font-size: 16px;
|
||||
padding: 35px 12px 12px 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.addAliasBtn {
|
||||
opacity: 0.7;
|
||||
transition: opacity 0.2s ease 0s;
|
||||
&.active {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { popToTop } from "react-chrome-extension-router";
|
||||
import failedImage from "../../assets/images/failed-round.png";
|
||||
import successImage from "../../assets/images/success-round.png";
|
||||
|
|
@ -9,10 +9,10 @@ import MyButton from "../UI/MyButton/MyButton";
|
|||
import MyInput from "../UI/MyInput/MyInput";
|
||||
import RoutersNav from "../UI/RoutersNav/RoutersNav";
|
||||
import AdditionalDetails from "./AdditionalDetails/AdditionalDetails";
|
||||
import AddressInput from "./AddressInput/AddressInput";
|
||||
import AssetsSelect from "./AssetsSelect/AssetsSelect";
|
||||
import s from "./WalletSend.module.scss";
|
||||
import { fetchBackground } from "../../utils/utils";
|
||||
import { getAliasDetails } from "../../../background/wallet";
|
||||
|
||||
const WalletSend = () => {
|
||||
const { state } = useContext(Store);
|
||||
|
|
@ -20,8 +20,9 @@ const WalletSend = () => {
|
|||
const [transactionSuccess, setTransactionSuccess] = useState(false);
|
||||
const [txId, setTxId] = useState("");
|
||||
// Form data
|
||||
const address = useInput("");
|
||||
const [address, setAddress] = useState("");
|
||||
const [asset, setAsset] = useState(state.wallet.assets[0]);
|
||||
const [submitAddress, setSubmitAddress] = useState("");
|
||||
const amount = useInput("");
|
||||
const comment = useInput("");
|
||||
const mixin = useInput(10);
|
||||
|
|
@ -71,6 +72,28 @@ const WalletSend = () => {
|
|||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (address.startsWith("@")) {
|
||||
const alias = address.slice(1);
|
||||
const resolvedAddress = await fetchAddress(alias);
|
||||
if (resolvedAddress) {
|
||||
setSubmitAddress(resolvedAddress);
|
||||
} else {
|
||||
setSubmitAddress("");
|
||||
}
|
||||
} else {
|
||||
if (address.length === 97) {
|
||||
setSubmitAddress(address);
|
||||
} else {
|
||||
setSubmitAddress("");
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [address]);
|
||||
|
||||
const fetchAddress = async (alias) => await getAliasDetails(alias);
|
||||
|
||||
return (
|
||||
<>
|
||||
{(() => {
|
||||
|
|
@ -80,18 +103,26 @@ const WalletSend = () => {
|
|||
return (
|
||||
<div>
|
||||
<RoutersNav title="Send" />
|
||||
|
||||
<div className={s.sendForm}>
|
||||
<AddressInput address={address} />
|
||||
|
||||
<MyInput
|
||||
placeholder="Address or alias"
|
||||
label="Address"
|
||||
value={address}
|
||||
onChange={(e) => setAddress(e.target.value)}
|
||||
isValid={submitAddress ? true : false}
|
||||
/>
|
||||
<AssetsSelect value={asset} setValue={setAsset} />
|
||||
|
||||
<MyInput
|
||||
type="number"
|
||||
placeholder="Amount to transfer"
|
||||
label="Amount:"
|
||||
value={amount.value}
|
||||
onChange={amount.onChange}
|
||||
isValid={
|
||||
!isNaN(amount.value) &&
|
||||
amount.value >= 0.000000000001 &&
|
||||
amount.value <= 1000000000
|
||||
}
|
||||
/>
|
||||
|
||||
<MyInput
|
||||
|
|
@ -109,7 +140,7 @@ const WalletSend = () => {
|
|||
/>
|
||||
|
||||
<MyButton
|
||||
disabled={!address.value || !amount.value}
|
||||
disabled={!submitAddress || !amount.value}
|
||||
onClick={() => setActiveStep(1)}
|
||||
>
|
||||
Send
|
||||
|
|
@ -129,7 +160,7 @@ const WalletSend = () => {
|
|||
value={amount.value + " " + asset.ticker}
|
||||
/>
|
||||
<TableRow label="From" value={state.wallet.address} />
|
||||
<TableRow label="To" value={address.value} />
|
||||
<TableRow label="To" value={address} />
|
||||
<TableRow label="Comment" value={comment.value} />
|
||||
<TableRow label="Fee" value={fee.value} />
|
||||
</div>
|
||||
|
|
@ -137,7 +168,7 @@ const WalletSend = () => {
|
|||
<MyButton
|
||||
onClick={async () => {
|
||||
const transferStatus = await sendTransfer(
|
||||
address.value,
|
||||
submitAddress,
|
||||
amount.value,
|
||||
comment.value,
|
||||
asset.assetId
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue