Browse Source

feature(form): refactor out form container

renovate/lint-staged-8.x
Jack Mallers 7 years ago
parent
commit
b3003326e3
  1. 46
      app/components/Form/Form.js
  2. 59
      app/components/Form/Form.scss
  3. 0
      app/components/Form/PayForm.js
  4. 0
      app/components/Form/RequestForm.js
  5. 3
      app/components/Form/index.js
  6. 68
      app/components/PayForm/PayForm.js
  7. 152
      app/components/PayForm/PayForm.scss
  8. 20
      app/reducers/form.js
  9. 21
      app/reducers/payform.js
  10. 36
      app/routes/app/components/App.js
  11. 4
      app/routes/app/components/components/Nav.js
  12. 70
      app/routes/app/containers/AppContainer.js

46
app/components/Form/Form.js

@ -0,0 +1,46 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { MdClose } from 'react-icons/lib/md'
import PayForm from './PayForm'
import RequestForm from './RequestForm'
import styles from './Form.scss'
const FORM_TYPES = {
PAY_FORM: PayForm,
REQUEST_FORM: RequestForm
}
class Form extends Component {
render() {
console.log('props: ', this.props)
const { formType, closeForm } = this.props
if (!formType) { return null }
const FormComponent = FORM_TYPES[formType]
return (
<div className={`${styles.outtercontainer} ${formType && styles.open}`}>
<div className={styles.innercontainer}>
<div className={styles.esc} onClick={closeForm}>
<MdClose />
</div>
<div className={styles.content}>
content
</div>
</div>
</div>
)
}
}
Form.propTypes = {
}
export default Form

59
app/components/Form/Form.scss

@ -0,0 +1,59 @@
@import '../../variables.scss';
.outtercontainer {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
height: 100vh;
background: $white;
z-index: 0;
opacity: 0;
transition: all 0.5s;
&.open {
opacity: 1;
z-index: 10;
}
}
.innercontainer {
position: relative;
height: 100vh;
margin: 5%;
}
.esc {
position: absolute;
top: 0;
right: 0;
color: $darkestgrey;
cursor: pointer;
padding: 20px;
border-radius: 50%;
&:hover {
color: $bluegrey;
background: $darkgrey;
}
&:active {
color: $white;
background: $main;
}
svg {
width: 32px;
height: 32px;
}
}
.content {
width: 50%;
margin: 0 auto;
display: flex;
flex-direction: column;
height: 75vh;
justify-content: center;
align-items: center;
}

0
app/components/Form/PayForm.js

0
app/components/Form/RequestForm.js

3
app/components/Form/index.js

@ -0,0 +1,3 @@
import Form from './Form'
export default Form

68
app/components/PayForm/PayForm.js

@ -4,15 +4,77 @@ import styles from './PayForm.scss'
class PayForm extends Component {
render() {
console.log('props: ', this.props)
const {
payform,
isOnchain,
isLn,
inputCaption,
setPayAmount,
setPayInput,
onPaySubmit
} = this.props
return (
<div>
payform
<div className={styles.container}>
<div className={styles.content}>
<section className={`${styles.amountContainer} ${isLn ? styles.ln : ''}`}>
<input
type='text'
ref={input => this.amountInput = input} // eslint-disable-line
size=''
style={
isLn ?
{ width: '75%', fontSize: '85px' }
:
{ width: `${amount.length > 1 ? (amount.length * 15) - 5 : 25}%`, fontSize: `${190 - (amount.length ** 2)}px` }
}
value={payform.amount}
onChange={event => setPayAmount(event.target.value)}
id='amount'
readOnly={isLn}
/>
</section>
<div className={styles.inputContainer}>
<aside className={styles.paymentIcon}>
{(() => {
if (isOnchain) {
return (
<i>
<span>on-chain</span>
<FaChain />
</i>
)
} else if (isLn) {
return (
<i>
<span>lightning network</span>
<FaBolt />
</i>
)
}
return null
})()}
</aside>
<section className={styles.input}>
<input
type='text'
placeholder='Payment request or bitcoin address'
value={payform.payInput}
onChange={event => setPayInput(event.target.value)}
id='paymentRequest'
/>
</section>
</div>
<section className={styles.buttonGroup}>
<div className={styles.button} onClick={onPaySubmit}>Pay</div>
</section>
</div>
</div>
)
}
}
PayForm.propTypes = {
}

152
app/components/PayForm/PayForm.scss

@ -0,0 +1,152 @@
@import '../../variables.scss';
.container {
width: 50%;
margin: 0 auto;
display: flex;
flex-direction: column;
height: 75vh;
justify-content: center;
align-items: center;
}
.content {
margin: 0 auto;
display: flex;
flex-direction: column;
height: 75vh;
justify-content: center;
align-items: center;
}
.amountContainer {
color: $main;
display: flex;
justify-content: center;
min-height: 120px;
margin-bottom: 20px;
min-height: 175px;
&.ln {
opacity: 0.75;
}
label, input[type=text] {
color: inherit;
display: inline-block;
vertical-align: top;
padding: 0;
}
label {
svg {
width: 85px;
height: 85px;
}
svg[data-icon='ltc'] {
margin-right: 10px;
g {
transform: scale(1.75) translate(-5px, -5px);
}
}
}
input[type=text] {
width: 100px;
font-size: 180px;
border: none;
outline: 0;
-webkit-appearance: none;
}
}
.inputContainer {
position: relative;
width: 100%;
padding: 40px 0;
cursor: pointer;
.info {
margin-bottom: 10px;
min-height: 19px;
}
.paymentIcon {
position: absolute;
width: 20%;
left: calc(-12.5% - 75px);
top: 42px;
color: $main;
font-size: 50px;
text-align: center;
span {
text-transform: uppercase;
display: block;
font-size: 12px;
font-weight: 200;
}
}
}
.input {
display: flex;
justify-content: center;
font-size: 18px;
height: auto;
min-height: 55px;
border: 1px solid $traditionalgrey;
border-radius: 6px;
position: relative;
padding: 0 20px;
label, input[type=text] {
font-size: inherit;
}
label {
padding-top: 19px;
padding-bottom: 12px;
color: $traditionalgrey;
}
input[type=text] {
width: 100%;
border: none;
outline: 0;
-webkit-appearance: none;
height: 55px;
padding: 0 10px;
}
}
.buttonGroup {
width: 100%;
display: flex;
flex-direction: row;
border-radius: 6px;
overflow: hidden;
.button {
cursor: pointer;
height: 55px;
min-height: 55px;
text-transform: none;
font-size: 18px;
transition: opacity .2s ease-out;
background: $main;
color: $white;
border: none;
font-weight: 500;
padding: 0;
width: 100%;
text-align: center;
line-height: 55px;
&:first-child {
border-right: 1px solid lighten($main, 20%);
}
}
}

20
app/reducers/form.js

@ -3,8 +3,13 @@ import bitcoin from 'bitcoinjs-lib'
// Initial State
const initialState = {
formType: null,
modalOpen: false,
formType: 'pay',
amount: '0',
onchainAmount: '0',
message: '',
@ -14,6 +19,9 @@ const initialState = {
// Constants
// ------------------------------------
export const SET_FORM_TYPE = 'SET_FORM_TYPE'
export const SET_FORM = 'SET_FORM'
export const SET_AMOUNT = 'SET_AMOUNT'
export const SET_ONCHAIN_AMOUNT = 'SET_ONCHAIN_AMOUNT'
@ -25,6 +33,13 @@ export const RESET_FORM = 'RESET_FORM'
// ------------------------------------
// Actions
// ------------------------------------
export function setFormType(formType) {
return {
type: SET_FORM_TYPE,
formType
}
}
export function setForm({ modalOpen, formType }) {
return {
type: SET_FORM,
@ -78,6 +93,9 @@ export function resetForm() {
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[SET_FORM_TYPE]: (state, { formType }) => ({ ...state, formType }),
[SET_FORM]: (state, { modalOpen, formType }) => ({ ...state, modalOpen, formType }),
[SET_AMOUNT]: (state, { amount }) => ({ ...state, amount }),
[SET_ONCHAIN_AMOUNT]: (state, { onchainAmount }) => ({ ...state, onchainAmount }),

21
app/reducers/payform.js

@ -25,6 +25,7 @@ export function setPayAmount(amount) {
}
export function setPayInput(payInput) {
console.log('payInput: ', payInput)
return {
type: SET_PAY_INPUT,
payInput
@ -50,7 +51,9 @@ const ACTION_HANDLERS = {
// Selector
// ------------------------------------
const payFormSelectors = {}
const payAmountSelector = state => state.payform.payInput
const payInputSelector = state => state.payform.payInput
const currencySelector = state => state.ticker.currencySelector
payFormSelectors.isOnchain = createSelector(
payInputSelector,
@ -71,6 +74,24 @@ payFormSelectors.isLn = createSelector(
input => input.length === 124
)
payFormSelectors.inputCaption = createSelector(
payFormSelectors.isOnchain,
payFormSelectors.isLn,
payAmountSelector,
currencySelector,
(isOnchain, isLn, amount, currency) => {
if (!isOnchain || !isLn) { return }
if (isOnchain) {
return `You're about to send ${amount} ${currency.toUpperCase()} on-chain which should take around 10 minutes`
}
if (isLn) {
return `You're about to send ${amount} ${currency.toUpperCase()} over the Lightning Network which will be instant`
}
}
)
export { payFormSelectors }
// ------------------------------------

36
app/routes/app/components/App.js

@ -1,7 +1,8 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import ModalRoot from './components/ModalRoot'
import Form from './components/Form'
import Form from 'components/Form'
// import Form from './components/Form'
import Nav from './components/Nav'
import styles from './App.scss'
@ -39,10 +40,11 @@ class App extends Component {
isOnchain,
isLn,
showModal,
openPayForm,
payFormProps,
closeForm,
children
} = this.props
@ -57,36 +59,20 @@ class App extends Component {
currentTicker={currentTicker}
currency={ticker.currency}
/>
<Form
isOpen={form.modalOpen}
close={() => setForm({ modalOpen: false })}
setAmount={setAmount}
setOnchainAmount={setOnchainAmount}
setMessage={setMessage}
setPubkey={setPubkey}
setPaymentRequest={setPaymentRequest}
peers={peers}
ticker={ticker}
form={form}
sendingTransaction={sendingTransaction}
createInvoice={createInvoice}
payInvoice={payInvoice}
sendCoins={sendCoins}
fetchInvoice={fetchInvoice}
formInvoice={formInvoice}
currentTicker={currentTicker}
isOnchain={isOnchain}
isLn={isLn}
formType={form.formType}
payFormProps={payFormProps}
closeForm={closeForm}
/>
<Nav
ticker={ticker}
balance={balance}
setCurrency={setCurrency}
formClicked={formType => setForm({ modalOpen: true, formType })}
currentTicker={currentTicker}
showModal={showModal}
payFormProps={payFormProps}
openPayForm={openPayForm}
/>
<div className={styles.content}>
{children}

4
app/routes/app/components/components/Nav.js

@ -9,7 +9,7 @@ import CurrencyIcon from 'components/CurrencyIcon'
import { btc, usd } from 'utils'
import styles from './Nav.scss'
const Nav = ({ ticker, balance, setCurrency, formClicked, currentTicker, showModal, payFormProps }) => (
const Nav = ({ ticker, balance, setCurrency, formClicked, currentTicker, openPayForm }) => (
<nav className={styles.nav}>
<ul className={styles.info}>
<li className={`${styles.currencies} ${styles.link}`}>
@ -72,7 +72,7 @@ const Nav = ({ ticker, balance, setCurrency, formClicked, currentTicker, showMod
</li>
</ul>
<div className={styles.buttons}>
<div className={styles.button} onClick={() => showModal('PAY_FORM', payFormProps)}>
<div className={styles.button} onClick={openPayForm}>
<span>Pay</span>
</div>
<div className={styles.button} onClick={() => formClicked('request')}>

70
app/routes/app/containers/AppContainer.js

@ -8,6 +8,8 @@ import { payInvoice } from 'reducers/payment'
import { sendCoins } from 'reducers/transaction'
import { fetchChannels } from 'reducers/channels'
import {
setFormType,
setForm,
setPaymentType,
setAmount,
@ -18,7 +20,7 @@ import {
formSelectors
} from 'reducers/form'
import { setPayAmount, setPayInput } from 'reducers/payform'
import { setPayAmount, setPayInput, payFormSelectors } from 'reducers/payform'
import App from '../components/App'
@ -41,7 +43,12 @@ const mapDispatchToProps = {
sendCoins,
fetchChannels,
fetchInvoice,
showModal
showModal,
setPayAmount,
setPayInput,
setFormType
}
const mapStateToProps = state => ({
@ -51,29 +58,52 @@ const mapStateToProps = state => ({
transaction: state.transaction,
form: state.form,
payform: state.payform,
invoice: state.invoice,
modal: state.modal,
currentTicker: tickerSelectors.currentTicker(state),
isOnchain: formSelectors.isOnchain(state),
isLn: formSelectors.isLn(state),
// Props to pass to the payment form modal
payFormProps: {
setPayAmount,
setPayInput,
onPaySubmit: () => {
const isOnchain = formSelectors.isOnchain(state)
const isLn = formSelectors.isLn(state)
console.log('isOnchain: ', isOnchain)
console.log('isLn: ', isLn)
console.log('amount: ', state.payform.amount)
console.log('inputField: ', state.payform.inputField)
isOnchain: payFormSelectors.isOnchain(state),
isLn: payFormSelectors.isLn(state),
inputCaption: payFormSelectors.isLn(state)
})
const mergeProps = (stateProps, dispatchProps, ownProps) => {
return {
...stateProps,
...dispatchProps,
...ownProps,
// action to open the pay form
openPayForm: () => {
dispatchProps.setFormType('PAY_FORM')
},
// action to open the request form
openRequestForm: () => {
dispatchProps.setFormType('REQUEST_FORM')
},
// action to close form
closeForm: () => {
dispatchProps.setFormType(null)
},
// Props to pass to the pay form
payFormProps: {
payform: stateProps.payform,
isOnchain: stateProps.isOnchain,
isLn: stateProps.isLn,
inputCaption: stateProps.inputCaption,
setPayAmount: dispatchProps.setPayAmount,
setPayInput: dispatchProps.setPayInput,
onPaySubmit: () => {
console.log('do submit stuff')
}
}
}
})
}
export default connect(mapStateToProps, mapDispatchToProps)(App)
export default connect(mapStateToProps, mapDispatchToProps, mergeProps)(App)

Loading…
Cancel
Save