Skip to content

Instantly share code, notes, and snippets.

@benthehenten
Created June 12, 2018 22:17
Show Gist options
  • Save benthehenten/3a1e1a7d69ac7d1d2f12967f3b8516f8 to your computer and use it in GitHub Desktop.
Save benthehenten/3a1e1a7d69ac7d1d2f12967f3b8516f8 to your computer and use it in GitHub Desktop.
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import PropTypes from 'prop-types';
import Airtable from 'airtable';
import { StyleSheet, css } from 'aphrodite';
import {
Button,
FormControl,
FormGroup,
ControlLabel,
HelpBlock,
DropdownButton,
MenuItem,
} from 'react-bootstrap';
import ProgressBar from './ProgressBar';
Airtable.configure({
endpointUrl: 'https://api.airtable.com',
apiKey: 'keyNstMCEnR92EJYX'
});
const contactsBase = Airtable.base('appscOBKDISMzd0ry');
const crmBase = Airtable.base('app4VDKpmUVWJsCXX');
const styles = StyleSheet.create({
app: {
position: 'relative',
textAlign: 'center',
width: '100%',
},
formWrapper: {
width: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
paddingTop: '5rem',
},
formContainer: {
width: '60rem',
right: '0',
left: '0',
textAlign: 'left',
},
title: {
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem',
},
imgContainer: {
width: '70rem',
},
demoFoundText: {
fontSize: '2rem',
marginTop: '2rem',
fontWeight: 'bold',
},
});
const PERSON_FIELDS = {
email: {
airtableName: 'Email',
},
phone: {
airtableName: 'Phone',
},
domain: {
airtableName: 'Domain',
},
}
const initialFormState = {};
Object.keys(PERSON_FIELDS).map(field => {
initialFormState[field] = '';
});
class App extends Component {
state = {
...initialFormState,
shouldShowLoadingDemo: false,
loadingDemoImg: '',
isLoading: false,
showCompletedMessage: false,
showNoDemoFound: false,
};
handleChange = field => {
return (e) => {
this.setState({ [field]: e.target.value });
}
}
getValidationState() {
return field => {
const length = this.state[field].length;
if (length > 0) return 'success';
// else if (length > 5) return 'warning';
// else if (length > 0) return 'error';
return null;
}
}
isFormSubmittable = () => {
return Object.values(Object.keys(initialFormState).reduce((obj, item) => {
obj[item] = this.state[item]
return obj;
}, {})).every(val => val)
}
async findExistingAccount(domain) {
return new Promise((res, rej) => {
crmBase('Accounts').select({
filterByFormula: `FIND("${domain}",{Domain})`,
}).eachPage(function page(records, fetchNextPage) {
records.forEach(function(record) {
res(record);
});
// if no records
res(null)
}, function done(error) {
console.log(error)
});
})
}
onSubmit = async () => {
this.setState({
isLoading: true,
});
const payload = {};
const { domain } = this.state;
// search the CRM for an existing demo
const existingAccount = await this.findExistingAccount(domain);
Object.keys(PERSON_FIELDS).map(key => {
const airtableName = PERSON_FIELDS[key].airtableName;
payload[airtableName] = this.state[key];
});
const existingDemoURL = existingAccount && existingAccount.fields['Demo URL'];
if (existingDemoURL){
const created = await contactsBase('Demo Contacts').create({
...payload,
['Needs Demo']: false,
});
this.setState({
isLoading: false,
});
// show loading screen
this.setState({
shouldShowLoadingDemo: true,
loadingDemoImg: existingAccount.fields['Screenshot URL'],
isLoading: true,
})
setTimeout(() => {
window.location.href = existingDemoURL;
}, 4000);
} else {
const created = await contactsBase('Demo Contacts').create({
...payload,
['Needs Demo']: true,
});
this.setState({
isLoading: false,
});
fetch('https://hooks.slack.com/services/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', {
method: 'POST',
body: JSON.stringify({text: `Demo Requested!:
domain: ${domain}
`})
});
this.setState({
showCompletedMessage: true,
});
setTimeout(() => {
this.props.onReset();
}, 4000)
}
}
async lookupDemo(domain) {
return new Promise((res, rej) => {
contactsBase('Demo Contacts').select({
filterByFormula: `FIND("${domain}",{Domain})`,
}).eachPage(function page(records, fetchNextPage) {
records.forEach(function(record) {
res(record);
});
// if no records
res(null)
}, function done(error) {
console.log(error)
});
})
}
onLookup = async () => {
const { domain } = this.state;
const existingAccount = await this.lookupDemo(domain);
const foundDemoURL = existingAccount && existingAccount.fields['Demo URL'];
if (foundDemoURL) {
window.location.href = foundDemoURL;
} else {
this.setState({
showNoDemoFound: true,
});
setTimeout(() => {
this.props.onReset();
}, 4000);
}
}
render() {
const { isLoading, shouldShowLoadingDemo, loadingDemoImg, showCompletedMessage, showNoDemoFound } = this.state;
let middleView;
if (showCompletedMessage) {
middleView = (
<div className={css(styles.demoFoundText)}>Thanks for requesting a demo. We will text you shortly when your demo is ready!</div>
);
} else if (shouldShowLoadingDemo) {
middleView = (
<div>
<div className={css(styles.demoFoundText)}>Demo Found!</div>
<img
className={css(styles.imgContainer)}
src={loadingDemoImg}
/>
</div>
)
} else if (showNoDemoFound) {
middleView = (
<div className={css(styles.demoFoundText)}>No demo found!</div>
);
} else {
middleView = (
<div className={css(styles.formWrapper)}>
<div className={css(styles.formContainer)}>
<form>
<FormGroup
controlId="formBasicText"
validationState={this.getValidationState()}
>
{Object.keys(PERSON_FIELDS).map(field => (
<div style={{marginBottom: '1rem'}} key={field}>
<ControlLabel>{PERSON_FIELDS[field].airtableName}</ControlLabel>
<FormControl
type="text"
value={this.state[field]}
placeholder={PERSON_FIELDS[field].airtableName}
onChange={this.handleChange(field)}
/>
<FormControl.Feedback />
</div>
))}
</FormGroup>
</form>
<div style={{marginTop: '4rem'}}>
<Button
bsStyle="success"
onClick={this.onSubmit}
disabled={!this.isFormSubmittable()}
>
Submit
</Button>
</div>
<div style={{marginTop: '4rem'}}>
<Button
bsStyle="info"
onClick={this.onLookup}
disabled={!this.state.domain}
>
Lookup Demo
</Button>
</div>
</div>
</div>
)
}
return (
<div className={css(styles.app)}>
<header className="App-header">
{isLoading && <ProgressBar />}
<img src={logo} className="App-logo" alt="logo" />
</header>
{middleView}
</div>
);
}
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment