Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import React from 'react'
import { observer } from 'xmobx/mobx-react'
import { action } from 'xmobx/mobx'
import { isArray, isSafe, isFunction, isObj } from 'exotic'
import { ObserverForm, FormState } from 'src/forms'
import { wording } from 'src/words'
import { PaymentFormProps } from './typings'
import { inputList } from './fixture'
import { paymentWithBillingAddressFormState } from './state'
import { Wrapper, StyledCancel, StyledSubmitButton } from './styled'

class FormStateCard extends FormState {
  inputsList = inputList
}

const SubmitButton = props => <StyledSubmitButton {...props} />
const CancelButton = props => <StyledCancel {...props} />

const fieldsToDisable = [
  'cardFirstName',
  'cardLastName',
  'cardNumber',
  'expirationMonth',
  'expirationYear',
  'securityCode',
]

/**
 * @todo this is missing typings!!!
 */

@observer
class FormCard<
  Props extends PaymentFormProps = PaymentFormProps
> extends ObserverForm<Props> {
  constructor(props) {
    super(props)
    this.state = new FormStateCard()
  }

  isSubmitButtonNeeded = !this.props.hasBlurValidation
  isCancelButtonNeeded = !this.props.hasBlurValidation

  SubmitButton = SubmitButton
  CancelButton = CancelButton

  static defaultProps = {
    state: new FormStateCard(),
  }

  setFormValue(inputState, item) {
    if (
      isObj(item) &&
      isSafe(item[inputState.name]) &&
      inputState.value !== item[inputState.name]
    ) {
      inputState.setValue(item[inputState.name])
    }
  }

  @action.bound
  doPreFillForm(props, state) {
    const { item } = props

    const toList = inputsList => isArray(inputsList) && inputsList
    const list = toList(state.inputsList)

    list.map(inputState => {
      if (
        inputState.type === 'groupElements' &&
        isArray(inputState.elementList)
      ) {
        inputState.elementList.map(inputElementState => {
          this.setFormValue(inputElementState, item)
        })
      } else {
        this.setFormValue(inputState, item)
      }

      fieldsToDisable.map(fieldName => {
        if (inputState.name === fieldName) {
          inputState.isDisabled = true
          inputState.validationType = 'none'
        }
      })
    })
  }

  @action.bound
  setCheckBoxVisibility(state, isVisible) {
    state.isSelected = !isVisible
    state.isHidden = isVisible
  }

  @action.bound
  setDefaultPaymentState() {
    const { isSelected } = this.props
    const defaultPaymentState = this.state.get('defaultPaymentMethod')
    if (isSelected !== defaultPaymentState.isSelected) {
      defaultPaymentState.isSelected = isSelected
    }
  }

  @action.bound
  addFormReset(inputState) {
    if (inputState.type === 'text' || inputState.type === 'telephone') {
      inputState.setValue('')
      inputState.isValidInput = true
    } else if (inputState.type === 'checkbox') {
      inputState.setValue(true)
      inputState.isValidInput = true
    }

    // To reset groupElements
    if (inputState.elementList.length > 0) {
      inputState.elementList.forEach(inputElement => {
        this.addFormReset(inputElement)
      })
    }
  }
  componentWillMount() {
    paymentWithBillingAddressFormState.toggleBillingAddress(this)
    const {
      submitButtonLabel,
      cancelButtonLabel,
      submitButtonDataQa,
      cancelButtonDataQa,
    } = this.props

    this.defaultSubmitButtonLabel = isSafe(submitButtonLabel)
      ? submitButtonLabel
      : wording.submit
    this.defaultCancelButtonLabel = isSafe(cancelButtonLabel)
      ? cancelButtonLabel
      : wording.cancel
    this.submitDataQa = submitButtonDataQa
    this.cancelDataQa = cancelButtonDataQa
  }

  componentDidMount() {
    const { isEditPayment } = this.props
    paymentWithBillingAddressFormState.setPaymentForm(this)
    if (isEditPayment === true) {
      this.doPreFillForm(this.props, this.state)
      const checkBoxState = this.state.get('billingAddressSameAsShipping')
      this.setCheckBoxVisibility(checkBoxState, true)
      this.setDefaultPaymentState()
    }
  }

  componentWillUpdate() {
    paymentWithBillingAddressFormState.toggleBillingAddress(this)
  }

  componentWillReceiveProps(nextProps) {
    const { isEditPayment, isExpanded } = nextProps

    if (isEditPayment !== true && isExpanded === true) {
      this.state.inputsList.map(this.addFormReset)
    }
    if (isEditPayment === true) {
      this.setDefaultPaymentState()
      this.doPreFillForm(nextProps, this.state)
    }
  }

  componentWillUnmount() {
    this.state.inputsList.map(inputState => {
      this.resetFormState(inputState)
    })
  }

  handleSubmit = (event: Event) => {
    const { isEditPayment, cardType, cardIdentifier } = this.props
    event.preventDefault()
    const { hasSubmitValidation, onPaymentSubmit } = this.props
    if (hasSubmitValidation === true) {
      paymentWithBillingAddressFormState.isValidForm = this.validateForm()
      if (
        paymentWithBillingAddressFormState.isValidForm &&
        isFunction(onPaymentSubmit)
      ) {
        const args = { cardType, cardIdentifier, state: this.state }
        const hasShippingAddress = onPaymentSubmit(args)
        // console.info('[PaymentWithBillingAddress] handleSubmit')
        // console.debug(hasShippingAddress)
        if (hasShippingAddress !== false && isEditPayment !== true) {
          this.state.inputsList.map(this.addFormReset)
        }
      }
    }
  }
  handleCancel = (event: Event) => {
    event.preventDefault()
    const { onPaymentCancel } = this.props
    if (isFunction(onPaymentCancel)) {
      onPaymentCancel(event)
    }
  }
}

class Form extends React.PureComponent<PaymentFormProps> {
  render() {
    const { className } = this.props
    console.log('[PaymentWithBillingAddress] Form: ', this.props)
    return (
      <Wrapper className={className}>
        <FormCard {...this.props} />
      </Wrapper>
    )
  }
}

export { Form }
export default Form