LearnersGuild/echo

View on GitHub
src/common/components/SurveyForm/index.jsx

Summary

Maintainability
B
4 hrs
Test Coverage
/**
* SurveyForm
* A dumb component that akes an array of fields, renders an appropriate
* input for each field's type, and passes a new array of the same fields
* fields with modified values on submission.
*/
import React, {PropTypes} from 'react'
import Button from 'react-toolbox/lib/button'
import FontIcon from 'react-toolbox/lib/font_icon'
import {Field} from 'redux-form'
 
import {FORM_INPUT_TYPES} from 'src/common/util/survey'
 
import {Flex} from 'src/common/components/Layout'
import SurveyFormInputText from 'src/common/components/SurveyFormInputText'
import SurveyFormInputNumeric from 'src/common/components/SurveyFormInputNumeric'
import SurveyFormInputRadio from 'src/common/components/SurveyFormInputRadio'
import SurveyFormInputSliderGroup from 'src/common/components/SurveyFormInputSliderGroup'
import {validateText, validateNumber, validateNumberGroup} from 'src/common/validations'
 
import styles from './index.css'
 
class SurveyForm extends React.Component {
constructor(props) {
super(props)
this.renderFieldInput = this.renderFieldInput.bind(this)
}
 
validateFieldInput(field) {
if (field) {
switch (field.type) {
case FORM_INPUT_TYPES.TEXT:
return value => validateText(value, field.validate)
case FORM_INPUT_TYPES.NUMERIC:
case FORM_INPUT_TYPES.PERCENTAGE:
case FORM_INPUT_TYPES.RADIO:
return value => validateNumber(value, field.validate)
case FORM_INPUT_TYPES.SLIDER_GROUP:
return items => {
const values = (items || []).map(item => item.value)
return validateNumberGroup(values, field.validate)
}
default:
return value => validateText(value, field.validate)
}
}
}
 
Function `renderFieldInput` has 44 lines of code (exceeds 25 allowed). Consider refactoring.
Function `renderFieldInput` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring.
renderFieldInput(field) {
const {input: {onChange: handleChange}} = field
switch (field.type) {
case FORM_INPUT_TYPES.TEXT:
return (
<SurveyFormInputText
name={field.name}
hint={field.hint}
value={field.input.value || ''}
onChange={handleChange}
/>
)
 
case FORM_INPUT_TYPES.NUMERIC:
case FORM_INPUT_TYPES.PERCENTAGE:
return (
<SurveyFormInputNumeric
name={field.name}
hint={field.hint}
value={isNaN(field.input.value) ? null : field.input.value}
onChange={handleChange}
/>
)
 
case FORM_INPUT_TYPES.RADIO:
return (
<SurveyFormInputRadio
name={field.name}
options={field.options}
value={isNaN(field.input.value) ? null : field.input.value}
onChange={handleChange}
/>
)
 
case FORM_INPUT_TYPES.SLIDER_GROUP:
return (
<SurveyFormInputSliderGroup
sum={100}
name={field.name}
hint={field.hint}
options={field.options}
value={field.input.value || []}
onChange={handleChange}
/>
)
 
default:
return null
}
}
 
renderFields() {
return (
<Flex flexDirection="column" width="100%" className={styles.body}>
{this.props.fields.map((field, i) => {
return (
<div key={i} className={styles.fieldWrapper}>
<h6 className={styles.fieldLabel}>{field.label}</h6>
<Field
name={field.name}
component={this.renderFieldInput}
validate={this.validateFieldInput(field)}
props={field}
/>
</div>
)
})}
</Flex>
)
}
 
Function `render` has 43 lines of code (exceeds 25 allowed). Consider refactoring.
render() {
const {
name,
title,
handleSubmit,
submitLabel,
submitDisabled,
onClickSubmit,
backLabel,
backDisabled,
onClickBack,
showBackButton,
invalid,
submitting,
} = this.props
const disableSubmit = submitDisabled || invalid || submitting
const backButton = showBackButton ? (
<Button disabled={backDisabled} onClick={onClickBack} raised>
<FontIcon value="keyboard_arrow_left"/>
<span className={styles.backButtonText}>{backLabel || 'Back'}</span>
</Button>
) : null
return (
<Flex width="100%" flexDirection="column" className={styles.container}>
<form id={name} onSubmit={handleSubmit ? handleSubmit(onClickSubmit) : onClickSubmit}>
<h5>{title || ''}</h5>
 
{this.props.fields ? this.renderFields() : this.props.content}
 
<Flex
width="100%"
className={styles.footer}
justifyContent={backButton ? 'space-between' : 'flex-end'}
>
{backButton}
<Button
type="submit"
label={submitLabel || 'Submit'}
disabled={disableSubmit}
raised
primary
/>
</Flex>
</form>
</Flex>
)
}
}
 
SurveyForm.propTypes = {
name: PropTypes.string,
title: PropTypes.string,
fields: PropTypes.arrayOf(PropTypes.shape({
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
label: PropTypes.string,
hint: PropTypes.string,
value: PropTypes.any,
options: PropTypes.array,
validate: PropTypes.object,
})),
content: PropTypes.any,
handleSubmit: PropTypes.func,
submitLabel: PropTypes.string,
submitDisabled: PropTypes.bool,
onClickSubmit: PropTypes.func,
backLabel: PropTypes.string,
backDisabled: PropTypes.bool,
onClickBack: PropTypes.func,
showBackButton: PropTypes.bool,
invalid: PropTypes.bool,
submitting: PropTypes.bool,
}
 
export default SurveyForm