Skip to content

Instantly share code, notes, and snippets.

@1-800-jono
Last active July 5, 2018 19:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 1-800-jono/af9206b1937c998d95e127550c37eb44 to your computer and use it in GitHub Desktop.
Save 1-800-jono/af9206b1937c998d95e127550c37eb44 to your computer and use it in GitHub Desktop.
React JS file - this is a multi-step form. Upload a CV/Resume then it gets analyzed on the server for keywords. This keywords are sent back as a response and then it populates the proper fields accordingly. Using React.js and Apollo.
import React, { Component } from 'react';
import { gql, graphql, compose } from 'react-apollo';
import request from 'superagent';
import LoadingFetch from '../helpers/LoadingFetch';
import SingleInput from '../forms/SingleInput';
class AddEditTalent extends Component {
constructor() {
super();
this.handleSubmit = this.handleSubmit.bind(this);
this.uploadImage = this.uploadImage.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
this.populateTalent = this.populateTalent.bind(this);
this.uploadPDF = this.uploadPDF.bind(this);
this.displayFileName = this.displayFileName.bind(this);
this.state = {
talent: null,
logoMessage: 'Click to upload CV',
talentSaved: false,
firstName: '',
lastName: '',
email: '',
phone: '',
address: '',
city: '',
state: '',
country: '',
citizenship: '',
postalCode: '',
cv: '',
website: '',
github: '',
bitbucket: '',
stackoverflow: '',
linkedin: '',
medium: '',
quora: '',
blog: '',
eventbrite: '',
typeform: '',
twitter: '',
salaryExpectation: 0,
whyInterview: '',
currentJobTitle: '',
active: true,
uploadFileName: 'No File',
uploadStatus: 'Waiting for file',
}
}
componentDidMount() {
if (this.props.id) {
if (this.props.data.loading) {
return setTimeout(() => this.componentDidMount(), 50);
} else {
if (this.props.data.talent) this.populateTalent(this.props.data.talent);
}
}
}
populateTalent(e) {
this.setState({
firstName: this.props.data.talent.contact[0].firstName || '',
lastName: this.props.data.talent.contact[0].lastName || '',
email: this.props.data.talent.contact[0].email || '',
phone: this.props.data.talent.contact[0].phone || '',
address: this.props.data.talent.contact[0].address || '',
city: this.props.data.talent.contact[0].city || '',
region: this.props.data.talent.contact[0].region || '',
country: this.props.data.talent.contact[0].country || '',
citizenship: this.props.data.talent.profile.citizenship || '',
postalCode: this.props.data.talent.contact[0].postalCode || '',
cv: this.props.data.talent.source.cv || '',
website: this.props.data.talent.source.website || '',
github: this.props.data.talent.source.github || '',
bitbucket: this.props.data.talent.source.bitbucket || '',
stackoverflow: this.props.data.talent.source.stackoverflow || '',
linkedin: this.props.data.talent.source.linkedin || '',
medium: this.props.data.talent.source.medium || '',
quora: this.props.data.talent.source.quora || '',
blog: this.props.data.talent.source.blog || '',
eventbrite: this.props.data.talent.source.eventbrite || '',
typeform: this.props.data.talent.source.typeform || '',
twitter: this.props.data.talent.source.twitter || '',
salaryExpectation: this.props.data.talent.work.salaryExpectation || '',
whyInterview: this.props.data.talent.profile.whyInterview || '',
currentJobTitle: this.props.data.talent.profile.currentJobTitle || '',
talent: this.props.data.talent
})
}
handleInputChange(e) {
const name = e.target.name;
this.setState({
[name]: e.target.value,
talentSaved: false
});
}
uploadImage(e) {
const formData = new FormData();
const logoFile = e.target.files[0];
formData.append('file', logoFile)
request.post(`${process.env.REACT_APP_BRAVE_FILE_UPLOAD}`)
.send(formData)
.end((err, response) => {
if (err) {
console.log(err);
} else if (response.ok) {
const fileURL = JSON.parse(response.text).data.files[0].url;
this.setState({
//Use api image url
logo: fileURL,
//Removes "add logo" text
logoMessage: null
})
}
});
}
//Display file name for input file
displayFileName(e) {
const fileName = this.pdfInput.files[0].name ? this.pdfInput.files[0].name : null;
this.setState({
uploadFileName: fileName,
});
this.uploadPDF(e);
}
//Upload PDF JD to server
uploadPDF(e) {
let formData = new FormData();
const pdfFile = this.pdfInput.files[0];
formData.append('file', pdfFile);
//console.log(`${process.env.REACT_APP_CORS_URL}${process.env.REACT_APP_BRAVE_FILE_UPLOAD}`);
request.post(`${process.env.REACT_APP_BRAVE_FILE_UPLOAD}`)
.send(formData)
.on('progress', e => {
this.setState({ uploadStatus: 'Uploading CV'});
})
.end((err, response) => {
if(err) {
console.log(err);
} else if(response.ok) {
const fileURL = JSON.parse(response.text).data.files[0].url;
this.setState({
cv: fileURL,
//uploadComplete: true,
uploadStatus: 'Upload Complete'
});
}
});
}
render() {
if (this.props.id && this.props.data.loading) {
return (<LoadingFetch />);
}
if (this.props.id && this.props.data.error) {
return (
<p>No Talent with this ID. {this.props.data.error.toString()}</p>
)
}
return (
<form className="add-talent" onSubmit={this.handleSubmit}>
<div className="add-talent__info">
<h2 className="add-talent__heading">{ this.props.id ? `Talent: ${this.props.id}` : 'Add a new talent' }</h2>
<div className="add-talent__top wrapper mb1">
<div className="add-talent-info">
<label className="form__label form__2col add-talent__label pr3">
First Name
<input type="text" className="form__text-input" placeholder="First Name" onChange={this.handleInputChange} value={this.state.firstName} name="firstName"/>
</label>
<label className="form__label form__2col add-talent__label">
Last Name
<input type="text" className="form__text-input" placeholder="Last Name" onChange={this.handleInputChange} value={this.state.lastName} name="lastName"/>
</label>
<label className="form__label form__2col add-talent__label pr3">
Email Address
<input type="text" className="form__text-input" placeholder="Email Address" onChange={this.handleInputChange} value={this.state.email} name="email"/>
</label>
<label className="form__label form__2col add-talent__label">
Phone Number
<input type="tel" className="form__text-input" placeholder="Phone Number" onChange={this.handleInputChange} value={this.state.phone} name="phone"/>
</label>
<label className="form__label add-talent__label">
Address
<input type="text" className="form__text-input" placeholder="Address" onChange={this.handleInputChange} value={this.state.address || ''} name="address"/>
</label>
<label className="form__label form__2col add-talent__label pr3">
City
<input type="text" className="form__text-input" placeholder="City" onChange={this.handleInputChange} value={this.state.city || ''} name="city"/>
</label>
<label className="form__label form__2col add-talent__label">
State or Region
<input type="text" className="form__text-input" placeholder="State or Region" onChange={this.handleInputChange} value={this.state.region || ''} name="region"/>
</label>
<label className="form__label form__2col add-talent__label pr3">
Postal Code
<input type="text" className="form__text-input" placeholder="Postal Code" onChange={this.handleInputChange} value={this.state.postalCode || ''} name="postalCode"/>
</label>
<label className="form__label form__2col add-talent__label">
Country
<input type="text" className="form__text-input" placeholder="Country" onChange={this.handleInputChange} value={this.state.country || ''} name="country"/>
</label>
<label className="form__label form__2col add-talent__label">
Citizenship
<input type="text" className="form__text-input" placeholder="Citizenship" onChange={this.handleInputChange} value={this.state.citizenship || ''} name="citizenship"/>
</label>
</div>
</div>
<div className="add-talent__middle wrapper">
</div>
<div className="add-talent__bio wrapper">
<label className="form__label add-talent__label">
Why Hire
<textarea className="form__text-input form__textarea" placeholder="Brief Paragraph on why to hire or interview" onChange={this.handleInputChange} value={this.state.whyInterview} name="whyInterview"></textarea>
</label>
<SingleInput type="text" label="Salary Expectation" name="salaryExpectation" value={this.state.salaryExpectation || ''} placeholder="$55,000" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="Current Job Title" name="currentJobTitle" value={this.state.currentJobTitle || ''} placeholder="Graphic Designer" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
{/*<SingleInput type="file" label="CV" name="cv" placeholder="URL of CV File" onChange={this.uploadPDF} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3 form__upload-label" />*/}
<label htmlFor="form-file" className="form__upload-label add-talent__label form__2col pr3 form__label">
Upload CV - <span className="form__upload-placeholder">{this.state.uploadFileName}</span><br/>
<div className="btn mb0">Upload</div>
<span className={`black-30 f7 pl3 ${this.state.uploadStatus === 'Upload Complete' && 'color__positive'}`}>{this.state.uploadStatus}</span>
<input type="file" id="form-file" className="form__upload" ref={(input) => this.pdfInput = input} onChange={this.displayFileName}/>
</label>
<SingleInput type="text" label="Website" name="website" value={this.state.website || ''} placeholder="https://www.website.com" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col" />
<SingleInput type="text" label="Github" name="github" value={this.state.github || ''} placeholder="github URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="Bitbucket" name="bitbucket" value={this.state.bitbucket || ''} placeholder="bitbucket URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="StackOverflow" name="stackoverflow" value={this.state.stackoverflow || ''} placeholder="Stackoverflow URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col" />
<SingleInput type="text" label="LinkedIn" name="linkedin" value={this.state.linkedin || ''} placeholder="LinkedIn URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="Medium" name="medium" value={this.state.medium || ''} placeholder="Medium URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col" />
<SingleInput type="text" label="Quora" name="quora" value={this.state.quora || ''} placeholder="Quora URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="Blog" name="blog" value={this.state.blog || ''} placeholder="Blog URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col" />
<SingleInput type="text" label="EventBrite" name="eventbrite" value={this.state.eventbrite || ''} placeholder="EventBrite URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<SingleInput type="text" label="Typeform" name="typeform" value={this.state.typeform || ''} placeholder="Typeform URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col" />
<SingleInput type="text" label="Twitter" name="twitter" value={this.state.twitter || ''} placeholder="Twitter URL" onChange={this.handleInputChange} extraInputClass="form__text-input" extraLabelClass="add-talent__label form__2col pr3" />
<button id="btn-talent-save" className="form__submit right" type="submit" className={"btn btn--ghost "+(this.state.talentSaved ? 'btn--disabled' : '')}>Submit</button>
</div>
</div>
</form>
);
}
handleSubmit(e) {
const submitBtn = document.getElementById('btn-talent-save');
submitBtn.classList.add('btn--processing');
e.preventDefault();
//if (!this.props.id) {}
const id = this.props.id || this.state.id;
const firstName = this.state.firstName;
const lastName = this.state.lastName;
const email = this.state.email;
const phone = this.state.phone;
const address = this.state.address;
const city = this.state.city;
const state = this.state.state;
const country = this.state.country;
const citizenship = this.state.citizenship;
const postalCode = this.state.postalCode;
const cv = this.state.cv;
const website = this.state.website;
const github = this.state.github;
const bitbucket = this.state.bitbucket;
const stackoverflow = this.state.stackoverflow;
const linkedin = this.state.linkedin;
const medium = this.state.medium;
const quora = this.state.quora;
const blog = this.state.blog;
const eventbrite = this.state.eventbrite;
const typeform = this.state.typeform;
const twitter = this.state.twitter;
const salaryExpectation = this.state.salaryExpectation;
const whyInterview = this.state.whyInterview;
const currentJobTitle = this.state.currentJobTitle;
const description = this.state.description;
const active = true;
this.props.mutate({
variables: {
id,
firstName,
lastName,
email,
phone,
address,
city,
state,
country,
citizenship,
postalCode,
cv,
website,
github,
bitbucket,
stackoverflow,
linkedin,
medium,
quora,
blog,
eventbrite,
typeform,
twitter,
salaryExpectation,
whyInterview,
currentJobTitle,
description,
active,
},
})
.then(() => {
// this.props.handleCloseModal();
submitBtn.classList.remove('btn--processing');
this.setState({
talentSaved: true,
});
//this.props.handleCloseModal();
})
.catch(error => {
const getNetworkErrors = error => error.networkError.response.json().then(e => e.errors.map(e => e.message).join(','))
if (error.networkError) {
//this.props.handleCloseModal();
getNetworkErrors(error).then(console.log)
} else {
console.log(error.message)
}
submitBtn.classList.remove('btn--processing');
});
}
}
export const TalentQuery = gql`
query TalentQuery($id: String){
talent(id: $id) {
id
contact {
firstName
lastName
email
phone
address
city
country
region
postalCode
}
source {
cv
website
github
bitbucket
stackoverflow
linkedin
medium
quora
blog
eventbrite
typeform
twitter
}
profile {
whyInterview
citizenship
}
work {
salaryExpectation
currentJobTitle
}
}
}
`
export const pushTalentMutation = gql`
mutation pushTalent(
$id: String,
$firstName: String!,
$lastName: String!,
$email: String!,
$phone: String,
$address: String,
$city: String,
$region: String,
$country: String,
$citizenship: [String],
$postalCode: String,
$cv: String,
$website: String,
$github: String,
$bitbucket: String,
$stackoverflow: String,
$linkedin: String,
$medium: String,
$quora: String,
$blog: String,
$eventbrite: String,
$typeform: String,
$twitter: String,
$salaryExpectation: String,
$whyInterview: String,
$currentJobTitle: String,
) {
pushTalent(
input: {
id: $id
contact: [{
firstName: $firstName
lastName: $lastName
email: $email
phone: $phone
address: $address
city: $city
country: $country
region: $region
postalCode: $postalCode
}]
source: {
cv: $cv
website: $website
github: $github
bitbucket: $bitbucket
stackoverflow: $stackoverflow
linkedin: $linkedin
medium: $medium
quora: $quora
blog: $blog
eventbrite: $eventbrite
typeform: $typeform
twitter: $twitter
}
profile: {
whyInterview: $whyInterview
citizenship: $citizenship
}
work: {
salaryExpectation: $salaryExpectation
currentJobTitle: $currentJobTitle
}
}
) {
id
contact {
firstName
lastName
email
phone
address
city
country
region
postalCode
}
source {
cv
website
github
bitbucket
stackoverflow
linkedin
medium
quora
blog
eventbrite
typeform
twitter
}
profile {
whyInterview
citizenship
}
work {
salaryExpectation
currentJobTitle
}
}
}
`
const TalentFormWithData = compose(
graphql(pushTalentMutation, {
options: (props) => ({
refetchQueries: [
// { query: TalentAllQuery },
{ query: TalentQuery, variables: { id: props.id } },
],
})
}),
graphql(TalentQuery, {
options: (ownProps) => ({
variables: {
id: ownProps.id
}
}),
skip: (ownProps) => !ownProps.id,
})
)(AddEditTalent)
export default TalentFormWithData;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment