MyCrypto/common/containers/Tabs/Swap/components/CurrencySwap.jsx

230 lines
7.1 KiB
React
Raw Normal View History

import './CurrencySwap.scss';
import React, { Component } from 'react';
import translate from 'translations';
import { combineAndUpper } from 'utils/formatters';
2017-09-07 20:14:52 +00:00
import SimpleSelect from 'components/ui/SimpleSelect';
import SimpleButton from 'components/ui/SimpleButton';
import type {
OriginKindSwapAction,
DestinationKindSwapAction,
OriginAmountSwapAction,
DestinationAmountSwapAction,
ChangeStepSwapAction
} from 'actions/swapTypes';
import bityConfig, { kindMin, kindMax } from 'config/bity';
import { toFixedIfLarger } from 'utils/formatters';
export type StateProps = {
bityRates: {},
originAmount: ?number,
destinationAmount: ?number,
originKind: string,
destinationKind: string,
destinationKindOptions: String[],
originKindOptions: String[]
};
export type ActionProps = {
originKindSwap: (value: string) => OriginKindSwapAction,
destinationKindSwap: (value: string) => DestinationKindSwapAction,
originAmountSwap: (value: ?number) => OriginAmountSwapAction,
destinationAmountSwap: (value: ?number) => DestinationAmountSwapAction,
changeStepSwap: () => ChangeStepSwapAction,
showNotification: Function
};
export default class CurrencySwap extends Component {
props: StateProps & ActionProps;
state = {
disabled: true,
showedMinMaxError: false
};
isMinMaxValid = (amount, kind) => {
let bityMin;
let bityMax;
if (kind !== 'BTC') {
const bityPairRate = this.props.bityRates['BTC' + kind];
bityMin = kindMin(bityPairRate, kind);
bityMax = kindMax(bityPairRate, kind);
} else {
bityMin = bityConfig.BTCMin;
bityMax = bityConfig.BTCMax;
}
let higherThanMin = amount >= bityMin;
let lowerThanMax = amount <= bityMax;
return higherThanMin && lowerThanMax;
};
isDisabled = (originAmount, originKind, destinationAmount) => {
const hasOriginAmountAndDestinationAmount =
originAmount && destinationAmount;
const minMaxIsValid = this.isMinMaxValid(originAmount, originKind);
return !(hasOriginAmountAndDestinationAmount && minMaxIsValid);
};
setDisabled(originAmount, originKind, destinationAmount) {
const disabled = this.isDisabled(
originAmount,
originKind,
destinationAmount
);
if (disabled && originAmount && !this.state.showedMinMaxError) {
const { bityRates } = this.props;
const ETHMin = kindMin(bityRates.BTCETH, 'ETH');
const ETHMax = kindMax(bityRates.BTCETH, 'ETH');
const REPMin = kindMin(bityRates.BTCREP, 'REP');
const notificationMessage = `
Minimum amount ${bityConfig.BTCMin} BTC,
${toFixedIfLarger(ETHMin, 3)} ETH.
Max amount ${bityConfig.BTCMax} BTC,
${toFixedIfLarger(ETHMax, 3)} ETH, or
${toFixedIfLarger(REPMin, 3)} REP
`;
this.setState(
{
disabled: disabled,
showedMinMaxError: true
},
() => {
this.props.showNotification('danger', notificationMessage, 10000);
}
);
} else {
this.setState({
disabled: disabled
});
}
}
onClickStartSwap = () => {
this.props.changeStepSwap(2);
};
setOriginAndDestinationToNull = () => {
this.props.originAmountSwap(null);
this.props.destinationAmountSwap(null);
this.setDisabled(null, this.props.originKind, null);
};
onChangeOriginAmount = (event: SyntheticInputEvent) => {
const { destinationKind, originKind } = this.props;
const amount = event.target.value;
let originAmountAsNumber = parseFloat(amount);
if (originAmountAsNumber || originAmountAsNumber === 0) {
let pairName = combineAndUpper(originKind, destinationKind);
let bityRate = this.props.bityRates[pairName];
this.props.originAmountSwap(originAmountAsNumber);
let destinationAmount = originAmountAsNumber * bityRate;
this.props.destinationAmountSwap(destinationAmount);
this.setDisabled(originAmountAsNumber, originKind, destinationAmount);
} else {
this.setOriginAndDestinationToNull();
}
};
onChangeDestinationAmount = (event: SyntheticInputEvent) => {
const { destinationKind, originKind } = this.props;
const amount = event.target.value;
let destinationAmountAsNumber = parseFloat(amount);
if (destinationAmountAsNumber || destinationAmountAsNumber === 0) {
this.props.destinationAmountSwap(destinationAmountAsNumber);
let pairNameReversed = combineAndUpper(destinationKind, originKind);
let bityRate = this.props.bityRates[pairNameReversed];
let originAmount = destinationAmountAsNumber * bityRate;
this.props.originAmountSwap(originAmount, originKind);
this.setDisabled(originAmount, originKind, destinationAmountAsNumber);
} else {
this.setOriginAndDestinationToNull();
}
};
onChangeDestinationKind = (event: SyntheticInputEvent) => {
let newDestinationKind = event.target.value;
this.props.destinationKindSwap(newDestinationKind);
};
onChangeOriginKind = (event: SyntheticInputEvent) => {
let newOriginKind = event.target.value;
this.props.originKindSwap(newOriginKind);
};
render() {
const {
originAmount,
destinationAmount,
originKind,
destinationKind,
destinationKindOptions,
originKindOptions
} = this.props;
return (
<article className="CurrencySwap">
<h1 className="CurrencySwap-title">
{translate('SWAP_init_1')}
</h1>
<div className="form-inline">
<input
className={`CurrencySwap-input form-control ${originAmount !== '' &&
this.isMinMaxValid(originAmount, originKind)
? 'is-valid'
: 'is-invalid'}`}
type="number"
placeholder="Amount"
value={
parseFloat(originAmount) === 0 ? originAmount : originAmount || ''
}
onChange={this.onChangeOriginAmount}
/>
2017-09-07 20:14:52 +00:00
<SimpleSelect
value={originKind}
onChange={this.onChangeOriginKind.bind(this)}
options={originKindOptions}
/>
<h1 className="CurrencySwap-divider">
{translate('SWAP_init_2')}
</h1>
<input
className={`CurrencySwap-input form-control ${destinationAmount !==
'' && this.isMinMaxValid(originAmount, originKind)
? 'is-valid'
: 'is-invalid'}`}
type="number"
placeholder="Amount"
value={
parseFloat(destinationAmount) === 0
? destinationAmount
: destinationAmount || ''
}
onChange={this.onChangeDestinationAmount}
/>
2017-09-07 20:14:52 +00:00
<SimpleSelect
value={destinationKind}
onChange={this.onChangeDestinationKind}
options={destinationKindOptions}
/>
</div>
<div className="CurrencySwap-submit">
<SimpleButton
onClick={this.onClickStartSwap}
text={translate('SWAP_init_CTA')}
disabled={this.state.disabled}
type="info"
/>
</div>
</article>
);
}
}