Files
freeCodeCamp/common/app/routes/Jobs/components/NewJob.jsx

396 lines
11 KiB
JavaScript
Raw Normal View History

2016-03-01 20:31:43 -08:00
import { CompositeDisposable, helpers } from 'rx';
2015-09-14 17:31:48 -07:00
import React, { PropTypes } from 'react';
2016-02-25 18:30:10 -08:00
import { reduxForm } from 'redux-form';
2016-02-28 15:45:38 -08:00
// import debug from 'debug';
import dedent from 'dedent';
2015-09-24 20:28:04 -07:00
import {
2016-02-28 15:45:38 -08:00
isAscii,
isEmail,
isURL
} from 'validator';
2015-09-24 20:28:04 -07:00
2015-09-14 17:31:48 -07:00
import {
2015-09-23 13:31:27 -07:00
Button,
2015-09-14 17:31:48 -07:00
Col,
Input,
Row
2015-09-14 17:31:48 -07:00
} from 'react-bootstrap';
2015-09-24 20:28:04 -07:00
2016-02-28 15:45:38 -08:00
import { saveJob } from '../redux/actions';
2015-09-14 17:31:48 -07:00
2016-02-28 15:45:38 -08:00
// const log = debug('fcc:jobs:newForm');
2015-09-24 20:28:04 -07:00
2015-10-16 20:05:22 -07:00
const hightlightCopy = `
2015-11-30 14:33:39 -08:00
Highlight my post to make it stand out. (+$250)
2015-10-16 20:05:22 -07:00
`;
const isRemoteCopy = `
2015-10-20 15:01:05 -07:00
This job can be performed remotely.
`;
2015-10-20 16:03:22 -07:00
const howToApplyCopy = dedent`
Examples: click here to apply yourcompany.com/jobs/33
Or email jobs@yourcompany.com
`;
const checkboxClass = dedent`
2015-10-20 15:30:25 -07:00
text-left
jobs-checkbox-spacer
col-sm-offset-2
col-sm-6 col-md-offset-3
`;
2016-02-28 15:45:38 -08:00
const certTypes = {
isFrontEndCert: 'isFrontEndCert',
isBackEndCert: 'isBackEndCert'
};
function isValidURL(data) {
return isURL(data, { 'require_protocol': true });
}
2016-02-28 15:45:38 -08:00
const fields = [
'position',
'locale',
'description',
'email',
'url',
'logo',
'company',
'isHighlighted',
'isRemoteOk',
'isFrontEndCert',
'isBackEndCert',
'howToApply'
];
const fieldValidators = {
position: makeRequired(isAscii),
locale: makeRequired(isAscii),
description: makeRequired(helpers.identity),
email: makeRequired(isEmail),
2016-03-01 20:31:43 -08:00
url: makeRequired(isValidURL),
logo: makeOptional(isValidURL),
2016-02-28 15:45:38 -08:00
company: makeRequired(isAscii),
howToApply: makeRequired(isAscii)
};
2016-03-01 20:31:43 -08:00
function makeOptional(validator) {
return val => val ? validator(val) : true;
}
2015-10-11 21:11:27 -07:00
function makeRequired(validator) {
2016-03-01 20:31:43 -08:00
return (val) => val ? validator(val) : false;
2015-10-11 21:11:27 -07:00
}
2016-02-28 15:45:38 -08:00
function validateForm(values) {
return Object.keys(fieldValidators)
.map(field => {
if (fieldValidators[field](values[field])) {
return null;
}
2016-03-01 20:31:43 -08:00
return { [field]: !fieldValidators[field](values[field]) };
2016-02-28 15:45:38 -08:00
})
.filter(Boolean)
.reduce((errors, error) => ({ ...errors, ...error }), {});
}
function getBsStyle(field) {
if (field.pristine) {
return null;
}
return field.error ?
'error' :
'success';
2016-02-25 18:30:10 -08:00
}
export class NewJob extends React.Component {
2016-03-01 20:31:43 -08:00
constructor(...args) {
super(...args);
this._subscriptions = new CompositeDisposable();
}
2016-02-25 18:30:10 -08:00
static displayName = 'NewJob';
static propTypes = {
fields: PropTypes.object,
2016-03-01 20:31:43 -08:00
handleSubmit: PropTypes.func,
saveJob: PropTypes.func
2016-02-25 18:30:10 -08:00
};
componentDidMount() {
2016-02-28 15:45:38 -08:00
// this.prop.getSavedForm();
}
2016-02-25 18:30:10 -08:00
2016-03-01 20:31:43 -08:00
componentWillUnmount() {
this._subscriptions.dispose();
}
handleSubmit(job) {
const subscription = this.props.saveJob(job).subscribe();
this._subscriptions.add(subscription);
}
2016-02-25 18:30:10 -08:00
handleCertClick(name) {
2016-02-28 15:45:38 -08:00
const { fields } = this.props;
Object.keys(certTypes).forEach(certType => {
if (certType === name) {
return fields[certType].onChange(true);
}
fields[certType].onChange(false);
2016-02-25 18:30:10 -08:00
});
2016-02-28 15:45:38 -08:00
}
2016-02-25 18:30:10 -08:00
render() {
const {
2016-02-28 15:45:38 -08:00
fields: {
position,
locale,
description,
email,
url,
logo,
company,
isHighlighted,
isRemoteOk,
howToApply,
isFrontEndCert,
isBackEndCert
},
handleSubmit
2016-02-25 18:30:10 -08:00
} = this.props;
const { handleChange } = this;
const labelClass = 'col-sm-offset-1 col-sm-2';
const inputClass = 'col-sm-6';
return (
<div>
<Row>
<Col
md={ 10 }
mdOffset={ 1 }>
<div className='text-center'>
<form
className='form-horizontal'
2016-02-28 15:45:38 -08:00
onSubmit={ handleSubmit(data => this.handleSubmit(data)) }>
2016-02-25 18:30:10 -08:00
<div className='spacer'>
<h2>First, select your ideal applicant: </h2>
</div>
<Row>
<Col
xs={ 6 }
xsOffset={ 3 }>
<Row>
<Button
bsStyle='primary'
2016-02-28 15:45:38 -08:00
className={ isFrontEndCert.value ? 'active' : '' }
2016-02-25 18:30:10 -08:00
onClick={ () => {
2016-02-28 15:45:38 -08:00
if (!isFrontEndCert.value) {
this.handleCertClick(certTypes.isFrontEndCert);
2016-02-25 18:30:10 -08:00
}
}}>
<h4>Front End Development Certified</h4>
You can expect each applicant
to have a code portfolio using the
following technologies:
HTML5, CSS, jQuery, API integrations
<br />
<br />
</Button>
</Row>
<div className='button-spacer' />
<Row>
<Button
bsStyle='primary'
2016-02-28 15:45:38 -08:00
className={ isBackEndCert.value ? 'active' : ''}
2016-02-25 18:30:10 -08:00
onClick={ () => {
2016-02-28 15:45:38 -08:00
if (!isBackEndCert.value) {
this.handleCertClick(certTypes.isBackEndCert);
2016-02-25 18:30:10 -08:00
}
}}>
<h4>Back End Development Certified</h4>
You can expect each applicant to have a code
portfolio using the following technologies:
HTML5, CSS, jQuery, API integrations, MVC Framework,
JavaScript, Node.js, MongoDB, Express.js
<br />
<br />
</Button>
</Row>
</Col>
</Row>
<div className='spacer'>
<h2>Tell us about the position</h2>
</div>
<hr />
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(position) }
2016-02-25 18:30:10 -08:00
label='Job Title'
labelClassName={ labelClass }
placeholder={
'e.g. Full Stack Developer, Front End Developer, etc.'
}
required={ true }
type='text'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...position }
/>
2016-02-25 18:30:10 -08:00
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(locale) }
2016-02-25 18:30:10 -08:00
label='Location'
labelClassName={ labelClass }
placeholder='e.g. San Francisco, Remote, etc.'
required={ true }
type='text'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...locale }
/>
2016-02-25 18:30:10 -08:00
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(description) }
2016-02-25 18:30:10 -08:00
label='Description'
labelClassName={ labelClass }
required={ true }
rows='10'
type='textarea'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...description }
/>
2016-02-25 18:30:10 -08:00
<Input
label={ isRemoteCopy }
type='checkbox'
2016-02-28 15:45:38 -08:00
wrapperClassName={ checkboxClass }
{ ...isRemoteOk }
/>
2016-02-25 18:30:10 -08:00
<div className='spacer' />
<hr />
<Row>
2015-10-20 16:03:22 -07:00
<div>
2016-02-25 18:30:10 -08:00
<h2>How should they apply?</h2>
2015-09-23 13:31:27 -07:00
</div>
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(howToApply) }
2016-02-25 18:30:10 -08:00
label=' '
2015-09-23 13:31:27 -07:00
labelClassName={ labelClass }
2016-02-25 18:30:10 -08:00
placeholder={ howToApplyCopy }
2015-10-11 21:11:27 -07:00
required={ true }
2016-02-25 18:30:10 -08:00
rows='2'
type='textarea'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...howToApply }
/>
2016-02-25 18:30:10 -08:00
</Row>
<div className='spacer' />
<hr />
<div>
<h2>Tell us about your organization</h2>
</div>
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(company) }
2016-02-25 18:30:10 -08:00
label='Company Name'
labelClassName={ labelClass }
onChange={ (e) => handleChange('company', e) }
type='text'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...company }
/>
2016-02-25 18:30:10 -08:00
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(email) }
2016-02-25 18:30:10 -08:00
label='Email'
labelClassName={ labelClass }
placeholder='This is how we will contact you'
required={ true }
type='email'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...email }
/>
2016-02-25 18:30:10 -08:00
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(url) }
2016-02-25 18:30:10 -08:00
label='URL'
labelClassName={ labelClass }
placeholder='http://yourcompany.com'
type='url'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...url }
/>
2016-02-25 18:30:10 -08:00
<Input
2016-02-28 15:45:38 -08:00
bsStyle={ getBsStyle(logo) }
2016-02-25 18:30:10 -08:00
label='Logo'
labelClassName={ labelClass }
placeholder='http://yourcompany.com/logo.png'
type='url'
2016-02-28 15:45:38 -08:00
wrapperClassName={ inputClass }
{ ...logo }
/>
2016-02-25 18:30:10 -08:00
<div className='spacer' />
<hr />
<div>
<div>
2016-02-25 18:30:10 -08:00
<h2>Make it stand out</h2>
</div>
2016-02-25 18:30:10 -08:00
<div className='spacer' />
2015-09-23 13:31:27 -07:00
<Row>
<Col
2016-02-25 18:30:10 -08:00
md={ 6 }
mdOffset={ 3 }>
Highlight this ad to give it extra attention.
<br />
2016-02-28 15:45:38 -08:00
Featured listings receive more clicks and more applications.
2015-09-23 13:31:27 -07:00
</Col>
</Row>
2016-02-25 18:30:10 -08:00
<div className='spacer' />
<Row>
<Input
bsSize='large'
bsStyle='success'
label={ hightlightCopy }
type='checkbox'
wrapperClassName={
checkboxClass.replace('text-left', '')
2016-02-28 15:45:38 -08:00
}
{ ...isHighlighted }
/>
2016-02-25 18:30:10 -08:00
</Row>
</div>
<Row>
<Col
className='text-left'
lg={ 6 }
lgOffset={ 3 }>
<Button
block={ true }
bsSize='large'
bsStyle='primary'
type='submit'>
Preview My Ad
</Button>
</Col>
</Row>
</form>
</div>
</Col>
</Row>
</div>
);
}
}
export default reduxForm(
2016-02-28 15:45:38 -08:00
{
form: 'NewJob',
fields,
validate: validateForm
},
null,
{
2016-03-01 20:31:43 -08:00
saveJob
2016-02-28 15:45:38 -08:00
}
2016-02-25 18:30:10 -08:00
)(NewJob);