import React, { PropTypes } from 'react'; import { History } from 'react-router'; import { contain } from 'thundercats-react'; import debugFactory from 'debug'; import dedent from 'dedent'; import { getDefaults } from '../utils'; import { inHTMLData, uriInSingleQuotedAttr } from 'xss-filters'; import { Button, Col, Input, Row, Panel, Well } from 'react-bootstrap'; import { isAscii, isEmail, isURL } from 'validator'; const debug = debugFactory('freecc:jobs:newForm'); const checkValidity = [ 'position', 'locale', 'description', 'email', 'url', 'logo', 'company', 'isHighlighted', 'howToApply' ]; const hightlightCopy = ` Highlight my post to make it stand out. (+$50) `; const foo = ` This will narrow the field substantially with higher quality applicants `; const isFullStackCopy = ` Applicants must have earned Free Code Camp’s Full Stack Certification to apply.* `; const isFrontEndCopy = ` Applicants must have earned Free Code Camp’s Front End Certification to apply.* `; const isRemoteCopy = ` This job can be performed remotely. `; const howToApplyCopy = dedent` Examples: click here to apply yourcompany.com/jobs/33 Or email jobs@yourcompany.com `; const checkboxClass = dedent` text-left jobs-checkbox-spacer col-sm-offset-2 col-sm-6 col-md-offset-3 `; function formatValue(value, validator, type = 'string') { const formated = getDefaults(type); if (validator && type === 'string') { formated.valid = validator(value); } if (value) { formated.value = value; formated.bsStyle = formated.valid ? 'success' : 'error'; } return formated; } function isValidURL(data) { return isURL(data, { 'require_protocol': true }); } function makeRequired(validator) { return (val) => !!val && validator(val); } export default contain({ actions: 'jobActions', store: 'jobsStore', map({ form = {} }) { const { position, locale, description, email, url, logo, company, isHighlighted, isFullStackCert, isFrontEndCert, isRemoteOk, howToApply } = form; return { position: formatValue(position, makeRequired(isAscii)), locale: formatValue(locale, makeRequired(isAscii)), description: formatValue(description, makeRequired(isAscii)), email: formatValue(email, makeRequired(isEmail)), url: formatValue(url, isValidURL), logo: formatValue(logo, isValidURL), company: formatValue(company, makeRequired(isAscii)), isHighlighted: formatValue(isHighlighted, null, 'bool'), isFullStackCert: formatValue(isFullStackCert, null, 'bool'), isFrontEndCert: formatValue(isFrontEndCert, null, 'bool'), isRemoteOk: formatValue(isRemoteOk, null, 'bool'), howToApply: formatValue(howToApply, makeRequired(isAscii)) }; }, subscribeOnWillMount() { return typeof window !== 'undefined'; } }, React.createClass({ displayName: 'NewJob', propTypes: { jobActions: PropTypes.object, position: PropTypes.object, locale: PropTypes.object, description: PropTypes.object, email: PropTypes.object, url: PropTypes.object, logo: PropTypes.object, company: PropTypes.object, isHighlighted: PropTypes.object, isFullStackCert: PropTypes.object, isFrontEndCert: PropTypes.object, isRemoteOk: PropTypes.object, howToApply: PropTypes.object }, mixins: [History], handleSubmit(e) { e.preventDefault(); const props = this.props; let valid = true; checkValidity.forEach((prop) => { // if value exist, check if it is valid if (props[prop].value && props[prop].type !== 'boolean') { valid = valid && !!props[prop].valid; } }); if (!valid) { debug('form not valid'); return; } const { jobActions, // form values position, locale, description, email, url, logo, company, isHighlighted, isFullStackCert, isFrontEndCert, isRemoteOk, howToApply } = this.props; // sanitize user output const jobValues = { position: inHTMLData(position.value), locale: inHTMLData(locale.value), description: inHTMLData(description.value), email: inHTMLData(email.value), url: uriInSingleQuotedAttr(url.value), logo: uriInSingleQuotedAttr(logo.value), company: inHTMLData(company.value), isHighlighted: !!isHighlighted.value, isFrontEndCert: !!isFrontEndCert.value, isFullStackCert: !!isFullStackCert.value, isRemoteOk: !!isRemoteOk.value, howToApply: inHTMLData(howToApply.value) }; const job = Object.keys(jobValues).reduce((accu, prop) => { if (jobValues[prop]) { accu[prop] = jobValues[prop]; } return accu; }, {}); job.postedOn = new Date(); debug('job sanitized', job); jobActions.saveForm(job); this.history.pushState(null, '/jobs/new/preview'); }, componentDidMount() { const { jobActions } = this.props; jobActions.getSavedForm(); }, handleChange(name, { target: { value } }) { const { jobActions: { handleForm } } = this.props; handleForm({ [name]: value }); }, render() { const { position, locale, description, email, url, logo, company, isHighlighted, isFrontEndCert, isFullStackCert, isRemoteOk, howToApply, jobActions: { handleForm } } = this.props; const { handleChange } = this; const labelClass = 'col-sm-offset-1 col-sm-2'; const inputClass = 'col-sm-6'; return (

First, tell us about the position

handleChange('position', e) } placeholder={ 'e.g. Full Stack Developer, Front End Developer, etc.' } required={ true } type='text' value={ position.value } wrapperClassName={ inputClass } /> handleChange('locale', e) } placeholder='e.g. San Francisco, Remote, etc.' required={ true } type='text' value={ locale.value } wrapperClassName={ inputClass } /> handleChange('description', e) } required={ true } rows='10' type='textarea' value={ description.value } wrapperClassName={ inputClass } /> handleForm({ isFrontEndCert: !!checked }) } type='checkbox' wrapperClassName={ checkboxClass } /> handleForm({ isFullStackCert: !!checked }) } type='checkbox' wrapperClassName={ checkboxClass } /> handleForm({ isRemoteOk: !!checked }) } type='checkbox' wrapperClassName={ checkboxClass } /> * { foo }

How should they apply?

handleChange('howToApply', e) } placeholder={ howToApplyCopy } required={ true } rows='2' type='textarea' value={ howToApply.value } wrapperClassName={ inputClass } />

Tell us about your organization

handleChange('company', e) } type='text' value={ company.value } wrapperClassName={ inputClass } /> handleChange('email', e) } placeholder='This is how we will contact you' required={ true } type='email' value={ email.value } wrapperClassName={ inputClass } /> handleChange('url', e) } placeholder='http://yourcompany.com' type='url' value={ url.value } wrapperClassName={ inputClass } /> handleChange('logo', e) } placeholder='http://yourcompany.com/logo.png' type='url' value={ logo.value } wrapperClassName={ inputClass } />

Make it stand out

Highlight this ad to give it extra attention.
Featured listings receive more clicks and more applications.
handleForm({ isHighlighted: !!checked }) } type='checkbox' wrapperClassName={ checkboxClass.replace('text-left', '') } />
); } }) );