diff --git a/src/AnotherBuilding.js b/src/AnotherBuilding.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e6e1d86cb31f8e54d141909d2c3987cd0948dfa
--- /dev/null
+++ b/src/AnotherBuilding.js
@@ -0,0 +1,336 @@
+import React from "react";
+import { Row, Col, Button, Input, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
+import './index.css';
+import Geocoder from 'react-mapbox-gl-geocoder';
+import location from './utils/images/location.svg'; // with import
+import jsonp from "jsonp";
+import ReactGA from 'react-ga';
+
+const mapAccess = {
+ mapboxApiAccessToken: process.env.REACT_APP_MAPBOX_TOKEN
+}
+
+const queryParams = {
+ country: 'us'
+}
+
+export default class AnotherBuilding extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ viewport: {},
+ addressFound: false,
+ answer: this.props.answer,
+ loadingAddressSearchBtn: false,
+ disabledAddressSearchBtn: true,
+ showModal: true,
+ form: {
+ FNAME: '',
+ LNAME: '',
+ EMAIL: '',
+ PHONE: '',
+ },
+ subscribed: false,
+ };
+ }
+ componentDidMount () {
+ let url = document.URL
+ let key = url.split('?')[1]
+ if(key !== undefined){
+ let address = decodeURI(key).split('address=')[1]
+ if (address !== "undefined"){
+ if (address.length !== 0){
+ this.setState({
+ answer: address,
+ addressFound: true,
+ });
+ }
+ }
+ }
+ if(process.env.REACT_APP_ENVIRONMENT==='production'){
+ ReactGA.pageview('/address-search');
+ }
+ }
+
+ handleOnSelected = (viewport, item) => {
+ this.setState({viewport});
+ this.setState({
+ answer: item.place_name,
+ addressFound: true,
+ }, () => {
+ this.validateEmptyInputs();
+ });
+ }
+
+ validateEmptyInputs = () => {
+ this.state.answer.length > 0 ?
+ this.setState({ disabled: false }) : this.setState({ disabled: true });
+ }
+
+ existAddressSubmitted = () => {
+ this.props.nextQuestion('anotherBuilding', this.props.answer, this.props.answer);
+ }
+
+ newAddressSubmitted = () => {
+ if(process.env.REACT_APP_ENVIRONMENT==='production'){
+ ReactGA.event({
+ category: "Intake Survey NYC",
+ action: "Clicked continue button",
+ label: "address-search"
+ });
+ }
+ this.setState({
+ loadingAddressSearchBtn: true,
+ disabledAddressSearchBtn: true,
+ showModal: true,
+ });
+ this.props.nextQuestion('anotherBuilding', this.state.answer, this.state.answer);
+ }
+
+ disableText = () => {
+ this.setState({
+ addressFound: false ,
+ loadingAddressSearchBtn: false,
+ disabledAddressSearchBtn: true,
+ });
+ }
+
+ validateContact() {
+ const emptyFields = [];
+ const invalidFields = [];
+ const errorMessage = [];
+ const validFirstName = /^[a-zA-Z ]{2,30}$/;
+ const validLastName = /^[a-zA-Z ]{2,30}$/;
+ const validEmail = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w+)+$/;
+ const validPhone = /^$|^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;
+
+ if (this.state.form.FNAME.toString().replace(/^\s+|\s+$/g, '') === '') {
+ emptyFields.push('First Name');
+ }
+ if (this.state.form.LNAME.toString().replace(/^\s+|\s+$/g, '') === '') {
+ emptyFields.push('Last Name');
+ }
+ if (this.state.form.EMAIL.toString().replace(/^\s+|\s+$/g, '') === '') {
+ emptyFields.push('Email address');
+ }
+ if (emptyFields.length > 0) {
+ errorMessage.push(`Please fill in:\n${emptyFields.join('\n')}`);
+ alert(errorMessage);
+ return false;
+ }
+ if (this.state.form.PHONE.toString().replace(/^\s+|\s+$/g, '') !== '' &&
+ !(validPhone.test(this.state.form.PHONE))) {
+ invalidFields.push('Phone number');
+ }
+ if (!(validFirstName.test(this.state.form.FNAME))) {
+ invalidFields.push('First Name');
+ }
+ if (!(validLastName.test(this.state.form.LNAME))) {
+ invalidFields.push('Last Name');
+ }
+ if (!(validEmail.test(this.state.form.EMAIL))) {
+ invalidFields.push('Email address');
+ }
+ if (invalidFields.length > 0) {
+ errorMessage.push(`\nInvalid input in:\n${invalidFields.join('\n')}`);
+ alert(errorMessage);
+ return false;
+ }
+ return true;
+ }
+
+ handleInputChange = (event) => {
+ const val = event.target.value;
+ const name = event.target.name;
+ this.setState({
+ form: {
+ ...this.state.form,
+ [name]: val,
+ },
+ });
+ }
+
+ subscribe = () => {
+ if (this.validateContact() && process.env.NODE_ENV === 'production') {
+ const action = process.env.REACT_APP_MAILCHIMP_URL;
+ const fields = ['FNAME', 'LNAME', 'EMAIL', 'PHONE'];
+ const values = fields.map(field => {
+ return `${field}=${encodeURIComponent(this.state.form[field])}`;
+ }).join("&");
+ const path = `${action}&${values}`;
+ const url = path.replace('/post?', '/post-json?');
+ jsonp(url, { param: "c" });
+ this.setState({
+ subscribed: true,
+ });
+ }
+ // If environment is not production close the form.
+ // Commenting out the below code because it closes the form on invalid inputs.
+ // else {
+ // this.setState({
+ // showModal: false,
+ // })
+ // }
+ }
+
+ closeModal = () => {
+ this.setState({
+ showModal: false,
+ })
+ }
+
+ render() {
+ let addressData = "";
+ const {viewport} = this.state;
+ if(this.state.addressFound === false){
+ addressData = (
+
+ )
+ }
+ else {
+ addressData = (
+
+ )
+ }
+
+ let modalHeader = 'Oops, something is wrong';
+ let modalBody = this.props.message;
+ let modalFooter = (
+
+ this.closeModal() }>Got it
+
+ );
+
+ if (this.props.message === 'Sorry! Area not covered at the moment.') {
+ modalHeader = this.state.subscribed ? 'Congratulations!' : 'Sorry, we\'re not in your city yet!';
+ modalBody = this.state.subscribed ? 'You have been successfully subscribed.' : (
+
+ );
+ modalFooter = this.state.subscribed ? (
+
+ this.closeModal() }>Done
+
+ ) : (
+
+ this.subscribe() }>Subscribe {' '}
+ this.closeModal() }>Later
+
+ );
+ }
+
+ let message = (
+
+
+ {modalHeader}
+
+
+ {modalBody}
+
+
+ {modalFooter}
+
+
+ );
+
+ const content = (
+
+ {message}
+
+ The next building I want to tell you about is at the same address (click the button below)
+
+ {this.props.answer}
+
+
+
+
+ The next building I want to tell you about is at a new address (enter address below)
+
+
+
+
+
+
+ {addressData}
+
+
+
+
+
+ Having trouble entering your address?
+ Please email us at support@blocpower.io
+
+
+
+ { this.state.loadingAddressSearchBtn && }
+ {' '}
+ Continue >
+
+
+
+
+ );
+
+ return (
+
+ {content}
+
+ );
+ }
+}
diff --git a/src/App.css b/src/App.css
index 42eef8fb04b581266e6e2890ba1b4fd3cdcbdcc1..ea210ab9fc668848c8a5ddba6b43a44211ec1c6d 100644
--- a/src/App.css
+++ b/src/App.css
@@ -244,6 +244,18 @@
width: 60%;
}
+.anotherBuildingExistBuilding {
+ margin-bottom: 8%;
+}
+
+.anotherBuildingExistBuildingButton {
+ margin-top: 2%;
+}
+
+.anotherBuildingNewBuildingNote {
+ margin-bottom: 15px;
+}
+
@media (max-width: 1367px) {
.main-content {
padding: 300px 20% 4% 10%;
diff --git a/src/App.js b/src/App.js
index e88f1ed07b900d568e58e4c3612b2c5d44b71697..49375cfc5d602b4d82ec1f9a51640ecdf779c7f1 100644
--- a/src/App.js
+++ b/src/App.js
@@ -33,6 +33,7 @@ import ChurchCoolingSystemAge from './ChurchCoolingSystemAge';
import ChurchBuildingType from './ChurchBuildingType';
import ChurchHoursPerWeek from './ChurchHoursPerWeek';
import OperationalSeasons from './OperationalSeasons';
+import AnotherBuilding from './AnotherBuilding';
import { questionTree } from './constants';
import { connect } from 'react-redux';
import { submitContact, submitAnswer, submitBuilding, submitQuestionnaire, submitUserAnswer } from './actions';
@@ -64,16 +65,34 @@ class App extends React.Component {
waitList={false}
oakland={false}
milwaukee={false}
+ anotherBuilding={this.anotherBuilding}
/>,
congrats: ,
},
multiFamilyAnswerId: 21,
miniSplitCheckBox: false,
+ anotherBuildingSubmitted: false,
};
}
+ componentWillReceiveProps(nextProps) {
+ // If user submitted another building search, use the new building object data
+ if (nextProps.building !== undefined && this.props.building !== undefined &&
+ nextProps.building.data.userId !== this.props.building.data.userId &&
+ this.state.anotherBuildingSubmitted === true) {
+ this.props.onSubmitAnswer({
+ questionId: ["6"],
+ answerId: [32],
+ surveyId: nextProps.building.data.surveyId,
+ buildingId: nextProps.building.data.buildingId,
+ userId: nextProps.building.data.userId,
+ });
+ }
+ }
+
resetQuestions = () => {
return {
addressSearch: {
@@ -290,7 +309,8 @@ class App extends React.Component {
81: 'HelpFindingContractors',
82: 'AdviceOnEnergyWaterEfficiency',
83: 'HelpFinancingEnergyProject',
- 33: 'other' },
+ 33: 'other',
+ },
prev: 'buildingTypeSubType',
next: 'buildingOperatingChallenges',
},
@@ -705,6 +725,13 @@ class App extends React.Component {
prev: 'buildingPastImprovement',
next: '',
},
+ anotherBuilding: {
+ title: '',
+ answer: '',
+ value: '',
+ prev: 'anotherBuilding',
+ next: 'churchBuildingType',
+ },
order: [],
};
}
@@ -733,15 +760,23 @@ class App extends React.Component {
questionAnswers[questions[question].id] = value;
}
+ if (question === 'anotherBuilding') {
+ questions['churchBuildingType']['prev'] = 'anotherBuilding';
+ }
+
const updatedOrder = questions.order.filter(item => item !== question);
updatedOrder.push(question);
questions.order = updatedOrder;
this.setState({ questions }, () => {
- if (question === 'addressSearch') {
+ if (['addressSearch', 'anotherBuilding'].includes(question)) {
this.props.onSubmitBuilding({
address: this.state.questions[question].value,
});
+ // If user clicks on 'continue' button on another building search page
+ if (question === 'anotherBuilding') {
+ this.setState({ anotherBuildingSubmitted: true });
+ }
} else if (question === 'unitBreakdown' || question === 'feedback'){
this.setQuestion(this.state.questions[question].next);
this.props.onSubmitUserAnswer({
@@ -751,6 +786,7 @@ class App extends React.Component {
buildingId: this.props.building.data.buildingId,
userId: this.props.building.data.userId,
});
+ this.setState({ anotherBuildingSubmitted: false });
} else {
this.setQuestion(this.state.questions[question].next);
this.props.onSubmitAnswer({
@@ -760,6 +796,7 @@ class App extends React.Component {
buildingId: this.props.building.data.buildingId,
userId: this.props.building.data.userId,
});
+ this.setState({ anotherBuildingSubmitted: false });
}
});
@@ -844,15 +881,33 @@ class App extends React.Component {
}
// If building type is not single fam and fuel type is natural gas or dual fuel -> display congrats page.
- if (questions['unitBreakdown']['value'] !== 20 &&
- question === 'fuels' && [4,6].includes(value)){
+ if (questions['unitBreakdown']['value'] !== 20 && question === 'fuels' && [4,6].includes(value)){
this.setState({ buildingQualified: true});
this.state.pages.congrats = ;
+ } else {
+ this.state.pages.congrats = ;
}
}
+ anotherBuilding = () => {
+ // When user starts new loop of questionnaire, we reset all the answers
+ const questions = this.resetQuestions();
+ questions['addressSearch'].value = this.state.questions['addressSearch'].value;
+ questions['buildingTypes'].value = this.state.questions['buildingTypes'].value;
+ this.setState({
+ questions,
+ question: 'anotherBuilding',
+ });
+ }
+
submitContact = (contact) => {
this.setQuestion(this.state.questions['contact'].next);
this.setState({
@@ -878,6 +933,7 @@ class App extends React.Component {
prevQuestion = (question) => {
this.setQuestion(this.state.questions[question].prev);
+ this.setState({ anotherBuildingSubmitted: false });
}
setQuestion = (question) => {
@@ -912,34 +968,22 @@ class App extends React.Component {
}
submit = () => {
- // 20 is the id for single family building type
- if (this.state.questions.buildingTypes.value === 20) {
- this.state.pages.thankYou = ;
- }
+ // Assign property values for last pages (thankyou and congrats)
+ const isSingleFamily = this.state.questions.buildingTypes.value === 20 || this.state.questions.waitList.value === 1 ? true : false;
+ const isWorshipBuilding = this.state.questions.buildingTypes.value === 32 ? true : false;
+ const anotherBuilding = this.state.questions.buildingTypes.value === 32 ? this.anotherBuilding : null;
+ const isWaitList = this.state.questions.waitList.value === 1 ? true : false;
+ const isOakland = this.props.building.data.surveyId === 2 ? true : false;
+ const isMilwaukee = this.props.building.data.surveyId === 3 ? true : false;
- // 1 - Yes & 2 - No for joining the waitlist
- if(this.state.questions.waitList.value === 1) {
- this.state.pages.thankYou = ;
- }
-
- // Oakland Survey ID = 2
- if(this.props.building.data.surveyId === 2) {
- this.state.pages.thankYou = ;
- }
-
- // Milwaukee Survey ID = 3
- if(this.props.building.data.surveyId === 3) {
- this.state.pages.thankYou = ;
- }
+ this.state.pages.thankYou = ;
this.setState({
submitted: true,
@@ -1187,6 +1231,13 @@ class App extends React.Component {
nextQuestion={this.nextQuestion}
questions={this.state.questions['buildingFutureImprovement'].questions}
/>,
+ anotherBuilding: ,
};
let content = "";
@@ -1196,9 +1247,10 @@ class App extends React.Component {
Object.keys(this.state.questions).indexOf(this.state.question) > -1) {
if (this.state.question === 'addressSearch' && this.props.building.data.surveyId === 1) {
content = questions['buildingTypes'];
- }
- else if (this.state.question === 'addressSearch' && [2,3].includes(this.props.building.data.surveyId)){
+ } else if (this.state.question === 'addressSearch' && [2,3].includes(this.props.building.data.surveyId)){
content = questions['buildingTypeSubType'];
+ } else if (this.state.anotherBuildingSubmitted) {
+ content = questions['churchBuildingType'];
} else {
content = questions[this.state.question];
}
diff --git a/src/CompleteButtons.js b/src/CompleteButtons.js
index 68dedc9e1b79f642c191f786657f53e0c08e48e1..d5524c744913d308778f69c390eb5f78c5cd8710 100644
--- a/src/CompleteButtons.js
+++ b/src/CompleteButtons.js
@@ -3,12 +3,19 @@ import { Row, Col, Button } from 'reactstrap';
import './index.css';
export default class CompleteButtons extends React.Component {
- addBuilding = () => {
- console.log('yes');
+ anotherBuilding = () => {
+ // if(process.env.REACT_APP_ENVIRONMENT==='production'){
+ // ReactGA.event({
+ // category: "Intake Survey General",
+ // action: "Clicked continue button",
+ // label: "building-needs"
+ // });
+ // }
+ this.props.anotherBuilding();
}
closePage = () => {
- window.close();
+ window.open('location', '_self', '').close();
}
render() {
@@ -18,7 +25,7 @@ export default class CompleteButtons extends React.Component {
+ Another building
diff --git a/src/Congrats.js b/src/Congrats.js
index d90ad302b7ccb907b007661a6576de0df6e64fd1..40aad92cfd7677b686e12125f99320de08ec299a 100644
--- a/src/Congrats.js
+++ b/src/Congrats.js
@@ -1,6 +1,7 @@
import React from "react";
import congrats from './utils/images/spot-results-congratulations.svg'; // with import
import './index.css';
+import CompleteButtons from './CompleteButtons';
import ReactGA from 'react-ga';
export default class Congrats extends React.Component {
@@ -14,6 +15,10 @@ export default class Congrats extends React.Component {
}
}
+ anotherBuilding = () => {
+ this.props.anotherBuilding();
+ }
+
render() {
const items = [
'Air source heat pumps use less energy than your current system',
@@ -29,6 +34,17 @@ export default class Congrats extends React.Component {
const data = this.props.naturalGas === true ?
items.slice(1).map(item => { return ({item} ) }) :
items.map(item => { return ({item} ) });
+
+
+ let buttons = '';
+ if (this.props.worshipBuilding === true) {
+ buttons = (
+
+ );
+ }
+
const content = (
@@ -48,6 +64,7 @@ export default class Congrats extends React.Component {
We'll send you an email to find a time to chat or you can call us at {process.env.REACT_APP_BLOCPOWER_CONTACT} .
+ { buttons }
);
diff --git a/src/ThankYou.js b/src/ThankYou.js
index 7194812a6ab7b71ec5f73b5a18bd058578eac69a..f87d0ef0bb7b09d577d8691f1715b58e4bf74dfc 100644
--- a/src/ThankYou.js
+++ b/src/ThankYou.js
@@ -1,6 +1,7 @@
import React from "react";
import result from './utils/images/spot-results-more-info.svg'; // with import
import './index.css';
+import CompleteButtons from './CompleteButtons';
import ReactGA from 'react-ga';
export default class ThankYou extends React.Component {
@@ -14,29 +15,33 @@ export default class ThankYou extends React.Component {
}
}
+ anotherBuilding = () => {
+ this.props.anotherBuilding();
+ }
+
render() {
// If building type is not single family (for NYC BIS) and for other surveys
- var data =
+ var data =
Looks like we need more information to see if your building is a good fit for air source heat pumps.
We'll send you an email to find a time to chat or you can {' '}
- call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}.
+ call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}.
// If building type is single family and user has joined the waitlist
if (this.props.singleFamily === true) {
- data =
+ data =
this.props.waitList === true ?
Thanks for joining our waitlist!
We'll be in touch as soon as we expand our services!
- If you’d like to reach out to us in the meantime you can call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}.
+ If you’d like to reach out to us in the meantime you can call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}.
:
Sorry to see you go! Come back any time if you change your mind!
- }
+ }
if (this.props.oakland === true ||this.props.milwaukee === true) {
const email = this.props.milwaukee === true ?
@@ -45,16 +50,25 @@ export default class ThankYou extends React.Component {
const emailURL = this.props.milwaukee === true ?
"mailto:welcome.milwaukee@blocpower.io":
"mailto:welcome.oakland@blocpower.io"
- data =
+ data =
Looks like we need more information to see what energy saving projects are a good fit for your building.
- We’ll send you an email to find a time to chat or you
- can
call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}
+ We’ll send you an email to find a time to chat or you
+ can
call us at {process.env.REACT_APP_BLOCPOWER_CONTACT}
or
email us at {email} .
-
- }
-
+
+ }
+
+ let buttons = '';
+ if (this.props.worshipBuilding === true) {
+ buttons = (
+
+ );
+ }
+
const content = (
@@ -62,6 +76,7 @@ export default class ThankYou extends React.Component {
Thank You!
{ data }
+ { buttons }
);