Browse Source

fix(ui): autofocus and clear pay and request forms

When the payment and request forms open ensure that the forms are empty
and the most relevant form field is selected by default.

Fix #389
renovate/lint-staged-8.x
Tom Kirkpatrick 6 years ago
parent
commit
eb71b6c579
No known key found for this signature in database GPG Key ID: 72203A8EC5967EA8
  1. 6
      app/components/AmountInput/AmountInput.js
  2. 17
      app/components/Form/Pay.js
  3. 197
      app/components/Form/Request.js
  4. 8
      test/unit/components/Form/Pay.spec.js
  5. 4
      test/unit/components/Form/Request.spec.js

6
app/components/AmountInput/AmountInput.js

@ -7,6 +7,7 @@ class AmountInput extends React.Component {
this.handleChange = this.handleChange.bind(this)
this.handleBlur = this.handleBlur.bind(this)
this.handleKeyDown = this.handleKeyDown.bind(this)
this.textInput = React.createRef()
}
setRules() {
@ -41,6 +42,10 @@ class AmountInput extends React.Component {
}
}
focusTextInput() {
this.textInput.current.focus()
}
parseNumber(_value) {
let value = _value || ''
if (typeof _value === 'string') {
@ -143,6 +148,7 @@ class AmountInput extends React.Component {
onBlur={this.handleBlur}
onKeyDown={this.handleKeyDown}
readOnly={readOnly}
ref={this.textInput}
type="text"
required
value={amount}

17
app/components/Form/Pay.js

@ -12,6 +12,22 @@ import AmountInput from 'components/AmountInput'
import styles from './Pay.scss'
class Pay extends Component {
constructor(props) {
super(props)
this.paymentRequestInput = React.createRef()
}
componentDidMount() {
const { setPayInput, setPayAmount } = this.props
// Clear the form of any previous data.
setPayInput('')
setPayAmount('')
// Focus the payment request input field.
this.paymentRequestInput.current.focus()
}
componentDidUpdate(prevProps) {
const {
isLn,
@ -110,6 +126,7 @@ class Pay extends Component {
onBlur={onPayInputBlur}
id="paymentRequest"
rows="4"
ref={this.paymentRequestInput}
/>
<section
className={`${styles.errorMessage} ${

197
app/components/Form/Request.js

@ -1,4 +1,4 @@
import React from 'react'
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Isvg from 'react-inlinesvg'
@ -9,100 +9,121 @@ import { btc } from 'lib/utils'
import AmountInput from 'components/AmountInput'
import styles from './Request.scss'
const Request = ({
requestform: { amount, memo, showCurrencyFilters },
ticker,
setRequestAmount,
setRequestMemo,
setCurrency,
setRequestCurrencyFilters,
currencyName,
requestFiatAmount,
class Request extends Component {
constructor(props) {
super(props)
this.amountInput = React.createRef()
}
currentCurrencyFilters,
componentDidMount() {
const { setRequestMemo, setRequestAmount } = this.props
onRequestSubmit
}) => {
const onCurrencyFilterClick = currency => {
// change the input amount
setRequestAmount(btc.convert(ticker.currency, currency, amount))
// Clear the form of any previous data.
setRequestMemo('')
setRequestAmount('')
setCurrency(currency)
setRequestCurrencyFilters(false)
// Focus the amount input field.
this.amountInput.current.focusTextInput()
}
return (
<div className={styles.container}>
<header className={styles.header}>
<Isvg src={hand} />
<h1>Request Payment</h1>
</header>
<div className={styles.content}>
<section className={styles.amount}>
<div className={styles.top}>
<label htmlFor="amount">Amount</label>
<span />
</div>
<div className={styles.bottom}>
<AmountInput
id="amount"
amount={amount}
currency={ticker.currency}
onChangeEvent={setRequestAmount}
/>
<div className={styles.currency}>
<section
className={styles.currentCurrency}
onClick={() => setRequestCurrencyFilters(!showCurrencyFilters)}
>
<span>{currencyName}</span>
<span>
<FaAngleDown />
</span>
</section>
<ul className={showCurrencyFilters ? styles.active : undefined}>
{currentCurrencyFilters.map(filter => (
<li key={filter.key} onClick={() => onCurrencyFilterClick(filter.key)}>
{filter.name}
</li>
))}
</ul>
render() {
const {
requestform: { amount, memo, showCurrencyFilters },
ticker,
setRequestAmount,
setRequestMemo,
setCurrency,
setRequestCurrencyFilters,
currencyName,
requestFiatAmount,
currentCurrencyFilters,
onRequestSubmit
} = this.props
const onCurrencyFilterClick = currency => {
// change the input amount
setRequestAmount(btc.convert(ticker.currency, currency, amount))
setCurrency(currency)
setRequestCurrencyFilters(false)
}
return (
<div className={styles.container}>
<header className={styles.header}>
<Isvg src={hand} />
<h1>Request Payment</h1>
</header>
<div className={styles.content}>
<section className={styles.amount}>
<div className={styles.top}>
<label htmlFor="amount">Amount</label>
<span />
</div>
<div className={styles.bottom}>
<AmountInput
id="amount"
amount={amount}
currency={ticker.currency}
onChangeEvent={setRequestAmount}
ref={this.amountInput}
/>
<div className={styles.currency}>
<section
className={styles.currentCurrency}
onClick={() => setRequestCurrencyFilters(!showCurrencyFilters)}
>
<span>{currencyName}</span>
<span>
<FaAngleDown />
</span>
</section>
<ul className={showCurrencyFilters ? styles.active : undefined}>
{currentCurrencyFilters.map(filter => (
<li key={filter.key} onClick={() => onCurrencyFilterClick(filter.key)}>
{filter.name}
</li>
))}
</ul>
</div>
</div>
</div>
<div className={styles.fiatAmount}>{`${requestFiatAmount || 0} ${
ticker.fiatTicker
}`}</div>
</section>
<section className={styles.memo}>
<div className={styles.top}>
<label htmlFor="memo">Memo</label>
</div>
<div className={styles.bottom}>
<input
type="text"
placeholder="Details about the request"
value={memo}
onChange={event => setRequestMemo(event.target.value)}
id="memo"
/>
</div>
</section>
<section className={styles.submit}>
<div
className={`${styles.button} ${amount > 0 ? styles.active : undefined}`}
onClick={onRequestSubmit}
>
Request
</div>
</section>
<div className={styles.fiatAmount}>{`${requestFiatAmount || 0} ${
ticker.fiatTicker
}`}</div>
</section>
<section className={styles.memo}>
<div className={styles.top}>
<label htmlFor="memo">Memo</label>
</div>
<div className={styles.bottom}>
<input
type="text"
placeholder="Details about the request"
value={memo}
onChange={event => setRequestMemo(event.target.value)}
id="memo"
/>
</div>
</section>
<section className={styles.submit}>
<div
className={`${styles.button} ${amount > 0 ? styles.active : undefined}`}
onClick={onRequestSubmit}
>
Request
</div>
</section>
</div>
</div>
</div>
)
)
}
}
Request.propTypes = {

8
test/unit/components/Form/Pay.spec.js

@ -1,5 +1,5 @@
import React from 'react'
import { configure, shallow } from 'enzyme'
import { configure, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Pay from 'components/Form/Pay'
@ -45,7 +45,7 @@ const defaultProps = {
describe('Form', () => {
describe('should show the form without an input', () => {
const el = shallow(<Pay {...defaultProps} />)
const el = mount(<Pay {...defaultProps} />)
it('should contain Pay', () => {
expect(el.find('input#paymentRequest').props.value).toBe(undefined)
@ -54,7 +54,7 @@ describe('Form', () => {
describe('should show lightning with a lightning input', () => {
const props = { ...defaultProps, isLn: true }
const el = shallow(<Pay {...props} />)
const el = mount(<Pay {...props} />)
it('should contain Pay', () => {
expect(el.find('input#paymentRequest').props.value).toBe(undefined)
@ -63,7 +63,7 @@ describe('Form', () => {
describe('should show on-chain with an on-chain input', () => {
const props = { ...defaultProps, isOnchain: true }
const el = shallow(<Pay {...props} />)
const el = mount(<Pay {...props} />)
it('should contain Pay', () => {
expect(el.find('input#paymentRequest').props.value).toBe(undefined)

4
test/unit/components/Form/Request.spec.js

@ -1,5 +1,5 @@
import React from 'react'
import { configure, shallow } from 'enzyme'
import { configure, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import Request from 'components/Form/Request'
@ -28,7 +28,7 @@ const defaultProps = {
describe('Form', () => {
describe('should show request form when formType is REQUEST_FORM', () => {
const props = { ...defaultProps }
const el = shallow(<Request {...props} />)
const el = mount(<Request {...props} />)
it('should contain Request', () => {
expect(el.contains('Request')).toBe(true)
})

Loading…
Cancel
Save