Skip to content

Commit

Permalink
separated SendForm using redux-form
Browse files Browse the repository at this point in the history
  • Loading branch information
Qrysto committed Jan 20, 2019
1 parent 0b4ce6f commit f36927e
Show file tree
Hide file tree
Showing 4 changed files with 317 additions and 90 deletions.
2 changes: 1 addition & 1 deletion app/App/SendPage/LookupAddressModal.js
Expand Up @@ -48,7 +48,7 @@ class LookupAddressModal extends Component {
className="tda"
onClick={() => {
this.closeModal();
this.props.updateAddress(ele.address);
this.props.updateRecipient(ele.address);
}}
>
{ele.address}
Expand Down
312 changes: 312 additions & 0 deletions app/App/SendPage/SendForm.js
@@ -0,0 +1,312 @@
// External Dependencies
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { reduxForm, Field, reset, change, touch } from 'redux-form';
import styled from '@emotion/styled';

// Internal Global Dependencies
import * as RPC from 'scripts/rpc';
import Text from 'components/Text';
import Icon from 'components/Icon';
import Button from 'components/Button';
import TextField from 'components/TextField';
import Select from 'components/Select';
import FormField from 'components/FormField';
import InputGroup from 'components/InputGroup';
import UIController from 'components/UIController';
import Link from 'components/Link';
import { rpcErrorHandler } from 'utils/form';

// Internal Local Dependencies
import LookupAddressModal from './LookupAddressModal';

// Resources
import sendIcon from 'images/send.sprite.svg';
import addressBookIcon from 'images/address-book.sprite.svg';

const formName = 'sendNXS';
const floatRegex = /^[0-9]+(.[0-9]*)?$/;

const SendFormComponent = styled.form({
maxWidth: 620,
margin: '0 auto',
});

const SendAmount = styled.div({
display: 'flex',
});

const SendAmountField = styled.div({
flex: 1,
});

const SendAmountEqual = styled.div({
display: 'flex',
alignItems: 'flex-end',
padding: '.1em .6em',
fontSize: '1.2em',
});

const SendFormButtons = styled.div({
display: 'flex',
justifyContent: 'space-between',
marginTop: '2em',
});

const getAccountOptions = AccountChanger => {
if (AccountChanger) {
return AccountChanger.map(e => ({
value: e.name,
display: `${e.name} (${e.val} NXS)`,
}));
}
return [];
};

const getNxsFiatPrice = (rawNXSvalues, fiatCurrency) => {
if (rawNXSvalues) {
const marketInfo = rawNXSvalues.find(e => e.name === fiatCurrency);
if (marketInfo) {
return marketInfo.price;
}
}
return null;
};

const getDefaultSendFrom = AccountChanger => {
if (AccountChanger && AccountChanger.length > 0) {
if (AccountChanger.find(acc => acc.name === 'default')) {
return 'default';
} else {
return AccountChanger[0].name;
}
}
return null;
};

const mapStateToProps = ({
sendReceive: { AccountChanger },
settings: { fiatCurrency, minConfirmations },
common: { rawNXSvalues, encrypted, loggedIn },
}) => {
return {
accountOptions: getAccountOptions(AccountChanger),
fiatCurrency: fiatCurrency,
minConfirmations: minConfirmations,
encrypted: encrypted,
loggedIn: loggedIn,
nxsFiatPrice: getNxsFiatPrice(rawNXSvalues, fiatCurrency),
initialValues: {
sendFrom: getDefaultSendFrom(AccountChanger),
sendTo: null,
amount: 0,
fiatAmount: 0,
message: '',
},
};
};

const mapDispatchToProps = dispatch => ({
updateRecipient: address => dispatch(change(formName, 'sendTo', address)),
updateNxsAmount: amount => dispatch(change(formName, 'amount', amount)),
updateFiatAmount: fiatAmount =>
dispatch(change(formName, 'fiatAmount', fiatAmount)),
touch: () => dispatch(touch()),
});

@connect(
mapStateToProps,
mapDispatchToProps
)
@reduxForm({
form: formName,
validate: ({ sendFrom, sendTo, amount }) => {
const errors = {};
if (!sendFrom) {
errors.sendFrom = 'No accounts selected';
}
if (!sendTo) {
errors.sendTo = <Text id="Alert.InvalidAddress" />;
}
if (!amount || parseFloat(amount) <= 0) {
errors.amount = <Text id="Alert.InvalidAmount" />;
}
return errors;
},
asyncBlurFields: ['sendTo'],
asyncValidate: async ({ sendTo }) => {
if (sendTo) {
try {
const result = await RPC.PROMISE('validateaddress', [sendTo]);
if (!result.isvalid) {
throw { sendTo: <Text id="Alert.InvalidAddress" /> };
}
if (result.ismine) {
throw { sendTo: <Text id="Alert.registeredToThis" /> };
}
} catch (err) {
throw { sendTo: err };
}
}
return null;
},
onSubmit: ({ sendFrom, sendTo, amount, message }, dispatch, props) => {
const params = [
sendFrom,
sendTo,
parseFloat(amount),
parseInt(props.minConfirmations),
];
if (message) params.push(message);
return RPC.PROMISE('sendfrom', params);
},
onSubmitSuccess: (result, dispatch, props) => {
UIController.openSuccessDialog({
message: <Text id="Alert.Sent" />,
});
dispatch(reset(formName));
props.getAccountData();
},
onSubmitFail: rpcErrorHandler('Error Saving Settings'),
})
export default class SendForm extends Component {
nxsToFiat = (e, value) => {
if (floatRegex.test(value)) {
const nxs = parseFloat(value);
const { nxsFiatPrice } = this.props;
if (nxsFiatPrice) {
const fiat = nxs * nxsFiatPrice;
this.props.updateFiatAmount(fiat.toFixed(2));
}
}
};

fiatToNxs = (e, value) => {
if (floatRegex.test(value)) {
const fiat = parseFloat(value);
const { nxsFiatPrice } = this.props;
if (nxsFiatPrice) {
const nxs = fiat / nxsFiatPrice;
this.props.updateNxsAmount(nxs.toFixed(5));
}
}
};

lookupAddress = () => {
UIController.openModal(LookupAddressModal, {
updateRecipient: this.props.updateRecipient,
});
};

confirmSend = () => {
const { handleSubmit, invalid, encrypted, loggedIn, touch } = this.props;

if (invalid) {
// Mark the form touched so that the validation errors will be shown
touch();
return;
}

if (encrypted && !loggedIn) {
const modalId = UIController.openErrorDialog({
message: 'You are not logged in',
note: (
<>
<p>You need to log in to your wallet before sending transactions</p>
<Link
to="/Settings/Security"
onClick={() => {
UIController.removeModal(modalId);
}}
>
Log in now
</Link>
</>
),
});
return;
}

UIController.openConfirmDialog({
question: <Text id="sendReceive.SendTransaction" />,
yesCallback: handleSubmit,
});
};

render() {
const { accountOptions, fiatCurrency } = this.props;
return (
<SendFormComponent onSubmit={this.confirmSend}>
<FormField label="Send From">
<Field
component={Select.RF}
name="sendFrom"
options={accountOptions}
/>
</FormField>

<FormField label="Send To">
<InputGroup>
<Field
component={TextField.RF}
name="sendTo"
placeholder="Recipient Address"
/>
<Button fitHeight className="relative" onClick={this.lookupAddress}>
<Icon spaceRight icon={addressBookIcon} />
<Text id="sendReceive.Contacts" />
</Button>
</InputGroup>
</FormField>

<SendAmount>
<SendAmountField>
<FormField connectLabel label={<Text id="sendReceive.Amount" />}>
<Field
component={TextField.RF}
name="amount"
placeholder="0.00000"
onChange={this.nxsToFiat}
/>
</FormField>
</SendAmountField>

<SendAmountEqual>=</SendAmountEqual>

<SendAmountField>
<FormField connectLabel label={fiatCurrency}>
<Field
component={TextField.RF}
name="fiatAmount"
placeholder="0.00"
onChange={this.fiatToNxs}
/>
</FormField>
</SendAmountField>
</SendAmount>

<Text id="sendReceive.EnterYourMessage">
{placeholder => (
<FormField connectLabel label={<Text id="sendReceive.Message" />}>
<Field
component={TextField.RF}
name="message"
multiline
rows={1}
placeholder={placeholder}
/>
</FormField>
)}
</Text>

<SendFormButtons>
<div />
<Button type="submit" skin="primary">
<Icon icon={sendIcon} spaceRight />
<Text id="sendReceive.SendNow" />
</Button>
</SendFormButtons>
</SendFormComponent>
);
}
}

0 comments on commit f36927e

Please sign in to comment.