diff options
6 files changed, 52 insertions, 23 deletions
diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx index 68b77cfc3..72a246280 100644 --- a/packages/website/ts/components/inputs/balance_bounded_input.tsx +++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx @@ -14,6 +14,7 @@ interface BalanceBoundedInputProps { amount?: BigNumber; hintText?: string; onChange: ValidatedBigNumberCallback; + onErrorMsgChange?: (errorMsg: React.ReactNode) => void; shouldShowIncompleteErrs?: boolean; shouldCheckBalance: boolean; validate?: (amount: BigNumber) => InputErrMsg; @@ -36,6 +37,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp isDisabled: false, shouldShowErrs: true, hintText: 'amount', + onErrorMsgChange: utils.noop, shouldShowUnderline: true, }; constructor(props: BalanceBoundedInputProps) { @@ -63,17 +65,11 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp } if (shouldResetState) { const amountString = nextProps.amount.toString(); - this.setState({ - errMsg: this._validate(amountString, nextProps.balance), - amountString, - }); + this._setAmountState(amountString, nextProps.balance); } } else if (isCurrentAmountNumeric) { const amountString = ''; - this.setState({ - errMsg: this._validate(amountString, nextProps.balance), - amountString, - }); + this._setAmountState(amountString, nextProps.balance); } } public render(): React.ReactNode { @@ -105,14 +101,11 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp ); } private _onValueChange(e: any, amountString: string): void { - const errMsg = this._validate(amountString, this.props.balance); - this.setState( - { - amountString, - errMsg, - }, + this._setAmountState( + amountString, + this.props.balance, () => { - const isValid = _.isUndefined(errMsg); + const isValid = _.isUndefined(this._validate(amountString, this.props.balance)); if (utils.isNumeric(amountString) && !_.includes(amountString, '-')) { this.props.onChange(isValid, new BigNumber(amountString)); } else { @@ -161,4 +154,13 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp ); } } + + private _setAmountState(amount: string, balance: BigNumber, callback: () => void = utils.noop): void { + const errorMsg = this._validate(amount, balance); + this.props.onErrorMsgChange(errorMsg); + this.setState({ + amountString: amount, + errMsg: this._validate(amount, balance), + }, callback); + } } diff --git a/packages/website/ts/components/inputs/eth_amount_input.tsx b/packages/website/ts/components/inputs/eth_amount_input.tsx index c3822a80b..862ba25f8 100644 --- a/packages/website/ts/components/inputs/eth_amount_input.tsx +++ b/packages/website/ts/components/inputs/eth_amount_input.tsx @@ -12,6 +12,7 @@ interface EthAmountInputProps { amount?: BigNumber; hintText?: string; onChange: ValidatedBigNumberCallback; + onErrorMsgChange?: (errorMsg: React.ReactNode) => void; shouldShowIncompleteErrs: boolean; onVisitBalancesPageClick?: () => void; shouldCheckBalance: boolean; @@ -40,6 +41,7 @@ export class EthAmountInput extends React.Component<EthAmountInputProps, EthAmou balance={this.props.balance} amount={amount} onChange={this._onChange.bind(this)} + onErrorMsgChange={this.props.onErrorMsgChange} shouldCheckBalance={this.props.shouldCheckBalance} shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs} onVisitBalancesPageClick={this.props.onVisitBalancesPageClick} diff --git a/packages/website/ts/components/inputs/token_amount_input.tsx b/packages/website/ts/components/inputs/token_amount_input.tsx index 9a74bdd51..3ff2c5440 100644 --- a/packages/website/ts/components/inputs/token_amount_input.tsx +++ b/packages/website/ts/components/inputs/token_amount_input.tsx @@ -20,6 +20,7 @@ interface TokenAmountInputProps { shouldCheckBalance: boolean; shouldCheckAllowance: boolean; onChange: ValidatedBigNumberCallback; + onErrorMsgChange?: (errorMsg: React.ReactNode) => void; onVisitBalancesPageClick?: () => void; lastForceTokenStateRefetch: number; shouldShowErrs?: boolean; @@ -85,6 +86,7 @@ export class TokenAmountInput extends React.Component<TokenAmountInputProps, Tok amount={amount} balance={ZeroEx.toUnitAmount(this.state.balance, this.props.token.decimals)} onChange={this._onChange.bind(this)} + onErrorMsgChange={this.props.onErrorMsgChange} validate={this._validate.bind(this)} shouldCheckBalance={this.props.shouldCheckBalance} shouldShowIncompleteErrs={this.props.shouldShowIncompleteErrs} diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx index 2ed924bcd..c8ced8d08 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -31,8 +31,8 @@ export interface WrapEtherItemProps { interface WrapEtherItemState { currentInputAmount?: BigNumber; - currentInputHasErrors: boolean; isEthConversionHappening: boolean; + errorMsg: React.ReactNode; } const styles: Styles = { @@ -47,12 +47,18 @@ const styles: Styles = { width: 125, }, ethAmountInput: { height: 32 }, - innerDiv: { paddingLeft: 60, paddingTop: 0 }, - wrapEtherConfirmationButtonContainer: { width: 128, top: 16 }, + innerDiv: { paddingLeft: 60, paddingTop: 0, paddingBottom: 10 }, + wrapEtherConfirmationButtonContainer: { width: 128, top: 18 }, wrapEtherConfirmationButtonLabel: { - fontSize: 10, + fontSize: 12, color: colors.white, }, + errorMsg: { + fontSize: 12, + marginTop: 4, + color: 'red', + minHeight: 20, + }, }; export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEtherItemState> { @@ -60,8 +66,8 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther super(props); this.state = { currentInputAmount: undefined, - currentInputHasErrors: false, isEthConversionHappening: false, + errorMsg: null, }; } public render(): React.ReactNode { @@ -85,6 +91,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther shouldShowErrs={false} shouldShowUnderline={false} style={styles.ethAmountInput} + onErrorMsgChange={this._onErrorMsgChange.bind(this)} /> ) : ( <TokenAmountInput @@ -99,12 +106,14 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther onChange={this._onValueChange.bind(this)} amount={this.state.currentInputAmount} hintText="0.00" - shouldShowErrs={false} // TODO: error handling + shouldShowErrs={false} shouldShowUnderline={false} style={styles.ethAmountInput} + onErrorMsgChange={this._onErrorMsgChange.bind(this)} /> )} </div> + {this._renderErrorMsg()} </div> } secondaryTextLines={2} @@ -119,7 +128,11 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther private _onValueChange(isValid: boolean, amount?: BigNumber): void { this.setState({ currentInputAmount: amount, - currentInputHasErrors: !isValid, + }); + } + private _onErrorMsgChange(errorMsg: React.ReactNode): void { + this.setState({ + errorMsg, }); } private _renderIsEthConversionHappeningSpinner(): React.ReactElement<{}> { @@ -144,6 +157,13 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther </div> ); } + private _renderErrorMsg(): React.ReactNode { + return ( + <div style={styles.errorMsg}> + {this.state.errorMsg} + </div> + ); + } private async _wrapEtherConfirmationActionAsync(): Promise<void> { this.setState({ isEthConversionHappening: true, diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts index 5caf5e73c..e3901fd81 100644 --- a/packages/website/ts/types.ts +++ b/packages/website/ts/types.ts @@ -208,7 +208,7 @@ export interface ContractEvent { } export type InputErrMsg = React.ReactNode | string | undefined; -export type ValidatedBigNumberCallback = (isValid: boolean, amount?: BigNumber) => void; +export type ValidatedBigNumberCallback = (isValid: boolean, amount?: BigNumber, errorMessage?: React.ReactNode) => void; export enum ScreenWidths { Sm = 'SM', Md = 'MD', diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 3c99bd2fe..5a0ab934d 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -27,6 +27,9 @@ const MD_MIN_EM = 52; const isDogfood = (): boolean => _.includes(window.location.href, configs.DOMAIN_DOGFOOD); export const utils = { + noop(): void { + return undefined; + }, assert(condition: boolean, message: string): void { if (!condition) { throw new Error(message); |