<commit_before>import React, { PropTypes } from 'react'
import classnames from 'classnames'
import $ from 'jquery'
import reactMixin from 'react-mixin'
import { Navigation } from 'react-router'
import { bindActionCreators } from 'redux'
import * as Paths from './../../Paths'
import * as FormEntryActions from './../../actions/FormEntryActions'
import { FormWidgetInput, FormWidgetButton, FacebookShareButton } from './../'

const emailRegEx = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i

@reactMixin.decorate(Navigation)

export default class FormWidget extends React.Component {
  static propTypes = {
    mobilization: PropTypes.object.isRequired,
    widget: PropTypes.object.isRequired,
    editable: PropTypes.bool.isRequired,
    configurable: PropTypes.bool,
    hasNewField: PropTypes.bool
  }

  constructor(props, context) {
    super(props, context)
    this.state = {
      hasMouseOver: false,
      loading: false,
      success: false,
      errors: []
    }
  }

  componentWillReceiveProps() {
    if (this.state.loading) {
      this.setState({loading: false, success: true})
    }
  }

  fields() {
    const { settings } = this.props.widget
    return (settings && settings.fields ? settings.fields : [])
  }

  handleMouseEnter() {
    this.setState({hasMouseOver: true})
  }

  handleMouseLeave() {
    this.setState({hasMouseOver: false})
  }

  handleClick() {
    const { mobilization, widget, editable } = this.props
    if (editable) {
      this.transitionTo(Paths.fieldsMobilizationWidget(mobilization.id, widget.id))
    }
  }

  submit() {
    if (!this.props.editable) {
      const { dispatch, mobilization, widget } = this.props
      const { settings } = widget
      const { fields } = settings
      const bindedFormEntryActions = bindActionCreators(FormEntryActions, dispatch)
      const fieldsWithValue = fields.map((field) => {
        return {...field, value: $('#input-' + field.uid).val()}
      })
      const errors = this.validate(fieldsWithValue)
      this.setState({errors: errors})

      if (errors.length === 0) {
        this.setState({loading: true})
        bindedFormEntryActions.addFormEntry({
          mobilization_id: mobilization.id,
          form_entry: {
            widget_id: widget.id,
            fields: JSON.stringify(fieldsWithValue)
          }
        })
      }
    }
  }

  validate(fieldsWithValue) {
    const errors = []
    fieldsWithValue.forEach((field) => {
      if (field.required === 'true' && field.value === '') {
        errors.push(`${field.label} não pode ficar em branco`)
      } else if (field.value !== '' && field.kind === 'email' && !field.value.match(emailRegEx)) {
        errors.push(`${field.label} inválido`)
      }
    })
    return errors
  }

  renderCallToAction() {
    const { configurable, widget } = this.props
    let callToAction = widget.settings && widget.settings.call_to_action ? widget.settings.call_to_action : 'Clique para configurar seu formulário...'
    callToAction = callToAction.replace('\n', '<br/><br/>')
    if (!configurable) {
      return <h2 className="mt0 mb3 center" dangerouslySetInnerHTML={{__html: callToAction}} />
    }
  }

  renderFields() {
    const fields = this.fields()
    return fields.map((field, index) => {
      return (
        <FormWidgetInput
          {...this.props}
          key={field.uid}
          uid={field.uid}
          canMoveUp={index !== 0}
          canMoveDown={index !== fields.length - 1}
          initializeEditing={this.props.hasNewField && index === fields.length - 1}
          field={field} />
      )
    })
  }

  renderButton() {
    const { configurable, widget } = this.props
    const { loading, success } = this.state

    if (!configurable) {
      return (
        <FormWidgetButton
          buttonText={(widget.settings ? (widget.settings.button_text || 'Enviar') : 'Enviar')} {...this.props}
          handleClick={::this.submit}
          loading={loading}
          success={success} />
      )
    }
  }

  renderCount() {
    const { configurable, widget, mobilization: { body_font: bodyFont }} = this.props
    if (!configurable) {
      return (
        <div className={classnames('mt2 h3 center', `${bodyFont}-body`)}>
          {widget.form_entries_count}
          &nbsp;
          {widget.settings && widget.settings.count_text ? widget.settings.count_text : 'assinaturas'}
        </div>
      )
    }
  }

  renderOverlay() {
    const { editable, configurable } = this.props
    if (editable && !configurable && this.state.hasMouseOver) {
      return (
        <div
          className="absolute top-0 right-0 bottom-0 left-0 bg-darken-4 h1 bold flex flex-center"
          style={{zIndex: 9998}}>
          <div className="center full-width white">Clique para editar</div>
        </div>
      )
    }
  }

  renderErrors() {
    const { errors } = this.state

    return (
      errors.length > 0 &&
      <div className="red bold mb1">
        {
          errors.map((error) => {
            return(
              <div
                className="p1 border-left border-red mb1 rounded-right"
                style={{backgroundColor: '#F9CACE', borderWidth: '8px'}}>
                {error}
              </div>
            )
          })
        }
      </div>
    )
  }

  renderShareButtons() {
    const checkMarkImage = require('./checkMarkImage.png')
    const { mobilization } = this.props

    return (
      <div className='center p3 bg-white black'>
        <div className='m0 h3 bold'>Formulário submetido com sucesso!</div>
        <div className='py2'>
          <img src={checkMarkImage} style={{width: '100px'}} />
        </div>
        <p>Agora, convoque mais gente para aumentar a força da mobilização!:</p>
        <FacebookShareButton href={Paths.mobilization(mobilization)} />
      </div>
    )
  }

  renderForm() {
    const { editable, configurable } = this.props
    const className = classnames({'p3 bg-darken-3 relative': editable || !configurable})

    return (
      <div>
        <div className={className}>
          { this.renderCallToAction() }
          { this.renderFields() }
          { this.renderErrors() }
          { this.renderButton() }
          { this.renderOverlay() }
        </div>
        { this.renderCount() }
      </div>
    )
  }

  render() {
    const {
      editable,
      mobilization: { header_font: headerFont }
    } = this.props
<commit_msg>Change copy<commit_after>import React, { PropTypes } from 'react'
import classnames from 'classnames'
import $ from 'jquery'
import reactMixin from 'react-mixin'
import { Navigation } from 'react-router'
import { bindActionCreators } from 'redux'
import * as Paths from './../../Paths'
import * as FormEntryActions from './../../actions/FormEntryActions'
import { FormWidgetInput, FormWidgetButton, FacebookShareButton } from './../'

const emailRegEx = /^([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$/i

@reactMixin.decorate(Navigation)

export default class FormWidget extends React.Component {
  static propTypes = {
    mobilization: PropTypes.object.isRequired,
    widget: PropTypes.object.isRequired,
    editable: PropTypes.bool.isRequired,
    configurable: PropTypes.bool,
    hasNewField: PropTypes.bool
  }

  constructor(props, context) {
    super(props, context)
    this.state = {
      hasMouseOver: false,
      loading: false,
      success: false,
      errors: []
    }
  }

  componentWillReceiveProps() {
    if (this.state.loading) {
      this.setState({loading: false, success: true})
    }
  }

  fields() {
    const { settings } = this.props.widget
    return (settings && settings.fields ? settings.fields : [])
  }

  handleMouseEnter() {
    this.setState({hasMouseOver: true})
  }

  handleMouseLeave() {
    this.setState({hasMouseOver: false})
  }

  handleClick() {
    const { mobilization, widget, editable } = this.props
    if (editable) {
      this.transitionTo(Paths.fieldsMobilizationWidget(mobilization.id, widget.id))
    }
  }

  submit() {
    if (!this.props.editable) {
      const { dispatch, mobilization, widget } = this.props
      const { settings } = widget
      const { fields } = settings
      const bindedFormEntryActions = bindActionCreators(FormEntryActions, dispatch)
      const fieldsWithValue = fields.map((field) => {
        return {...field, value: $('#input-' + field.uid).val()}
      })
      const errors = this.validate(fieldsWithValue)
      this.setState({errors: errors})

      if (errors.length === 0) {
        this.setState({loading: true})
        bindedFormEntryActions.addFormEntry({
          mobilization_id: mobilization.id,
          form_entry: {
            widget_id: widget.id,
            fields: JSON.stringify(fieldsWithValue)
          }
        })
      }
    }
  }

  validate(fieldsWithValue) {
    const errors = []
    fieldsWithValue.forEach((field) => {
      if (field.required === 'true' && field.value === '') {
        errors.push(`${field.label} não pode ficar em branco`)
      } else if (field.value !== '' && field.kind === 'email' && !field.value.match(emailRegEx)) {
        errors.push(`${field.label} inválido`)
      }
    })
    return errors
  }

  renderCallToAction() {
    const { configurable, widget } = this.props
    let callToAction = widget.settings && widget.settings.call_to_action ? widget.settings.call_to_action : 'Clique para configurar seu formulário...'
    callToAction = callToAction.replace('\n', '<br/><br/>')
    if (!configurable) {
      return <h2 className="mt0 mb3 center" dangerouslySetInnerHTML={{__html: callToAction}} />
    }
  }

  renderFields() {
    const fields = this.fields()
    return fields.map((field, index) => {
      return (
        <FormWidgetInput
          {...this.props}
          key={field.uid}
          uid={field.uid}
          canMoveUp={index !== 0}
          canMoveDown={index !== fields.length - 1}
          initializeEditing={this.props.hasNewField && index === fields.length - 1}
          field={field} />
      )
    })
  }

  renderButton() {
    const { configurable, widget } = this.props
    const { loading, success } = this.state

    if (!configurable) {
      return (
        <FormWidgetButton
          buttonText={(widget.settings ? (widget.settings.button_text || 'Enviar') : 'Enviar')} {...this.props}
          handleClick={::this.submit}
          loading={loading}
          success={success} />
      )
    }
  }

  renderCount() {
    const { configurable, widget, mobilization: { body_font: bodyFont }} = this.props
    if (!configurable) {
      return (
        <div className={classnames('mt2 h3 center', `${bodyFont}-body`)}>
          {widget.form_entries_count}
          &nbsp;
          {widget.settings && widget.settings.count_text ? widget.settings.count_text : 'assinaturas'}
        </div>
      )
    }
  }

  renderOverlay() {
    const { editable, configurable } = this.props
    if (editable && !configurable && this.state.hasMouseOver) {
      return (
        <div
          className="absolute top-0 right-0 bottom-0 left-0 bg-darken-4 h1 bold flex flex-center"
          style={{zIndex: 9998}}>
          <div className="center full-width white">Clique para editar</div>
        </div>
      )
    }
  }

  renderErrors() {
    const { errors } = this.state

    return (
      errors.length > 0 &&
      <div className="red bold mb1">
        {
          errors.map((error) => {
            return(
              <div
                className="p1 border-left border-red mb1 rounded-right"
                style={{backgroundColor: '#F9CACE', borderWidth: '8px'}}>
                {error}
              </div>
            )
          })
        }
      </div>
    )
  }

  renderShareButtons() {
    const checkMarkImage = require('./checkMarkImage.png')
    const { mobilization } = this.props

    return (
      <div className='center p3 bg-white black'>
        <div className='m0 h3 bold'>Formulário submetido com sucesso!</div>
        <div className='py2'>
          <img src={checkMarkImage} style={{width: '100px'}} />
        </div>
        <p>Agora, convoque mais gente para aumentar a força da mobilização!</p>
        <FacebookShareButton href={Paths.mobilization(mobilization)} />
      </div>
    )
  }

  renderForm() {
    const { editable, configurable } = this.props
    const className = classnames({'p3 bg-darken-3 relative': editable || !configurable})

    return (
      <div>
        <div className={className}>
          { this.renderCallToAction() }
          { this.renderFields() }
          { this.renderErrors() }
          { this.renderButton() }
          { this.renderOverlay() }
        </div>
        { this.renderCount() }
      </div>
    )
  }

  render() {
    const {
      editable,
      mobilization: { header_font: headerFont }
    } = this.props

{'fraction_non_alphanumeric': 0.14524750174297002, 'fraction_numerical': 0.0061972267410333876, 'mean_word_length': 2.3760460251046025, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 71, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7652365', 'n_tokens_mistral': 3944, 'n_tokens_neox': 3881, 'n_words': 785}