diff --git a/.env b/.env
index 667ad2b324cb604bf2a4a6bacd0d3f69fdd14e87..8593f5822dd9dc7f3bda4ba40a2d1f08cfd122ae 100644
--- a/.env
+++ b/.env
@@ -1,6 +1,7 @@
-mapboxApiAccessToken= 'pk.eyJ1IjoiYmxvY3Bvd2VyIiwiYSI6ImNqd202bngzazE3c2o0OW4wM2IzbG00Y2cifQ.ZdSoYvbdw4fuIul8PQ3sBQ'
+REACT_APP_MAPBOX_TOKEN=pk.eyJ1IjoiYmxvY3Bvd2VyIiwiYSI6ImNqNDdhZ2o2czAwdDcycXJ1YzZ6MHZlNHoifQ.fRQhMFfCCyDk78RI5QD4ow
# Environment
ENVIRONMENT=local
# Services
REACT_APP_BLOCLINK_URL=http://0.0.0.0:5410
+SKIP_PREFLIGHT_CHECK=true
diff --git a/package-lock.json b/package-lock.json
index 47bbb4f2de73057657aa8499d1396c09c3d1e0f4..b12f58fba653b715764f09b7bd332ab4888e7761 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2811,7 +2811,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -2829,11 +2830,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -2846,15 +2849,18 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -2957,7 +2963,8 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -2967,6 +2974,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -2979,17 +2987,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -3006,6 +3017,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -3078,7 +3090,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -3088,6 +3101,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3163,7 +3177,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -3193,6 +3208,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -3210,6 +3226,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3248,11 +3265,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
},
@@ -6968,7 +6987,8 @@
},
"ansi-regex": {
"version": "2.1.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -6986,11 +7006,13 @@
},
"balanced-match": {
"version": "1.0.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -7003,15 +7025,18 @@
},
"code-point-at": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -7114,7 +7139,8 @@
},
"inherits": {
"version": "2.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -7124,6 +7150,7 @@
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -7136,17 +7163,20 @@
"minimatch": {
"version": "3.0.4",
"bundled": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "0.0.8",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -7163,6 +7193,7 @@
"mkdirp": {
"version": "0.5.1",
"bundled": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -7235,7 +7266,8 @@
},
"number-is-nan": {
"version": "1.0.1",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -7245,6 +7277,7 @@
"once": {
"version": "1.4.0",
"bundled": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -7320,7 +7353,8 @@
},
"safe-buffer": {
"version": "5.1.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -7350,6 +7384,7 @@
"string-width": {
"version": "1.0.2",
"bundled": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -7367,6 +7402,7 @@
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -7405,11 +7441,13 @@
},
"wrappy": {
"version": "1.0.2",
- "bundled": true
+ "bundled": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
- "bundled": true
+ "bundled": true,
+ "optional": true
}
}
}
diff --git a/src/AddressSearch.js b/src/AddressSearch.js
index 1708555646591bd7ea481675f23a50ad1243ccbb..0019a3c69e8a6f7fd04ebfd7ba423906fb0df5f7 100644
--- a/src/AddressSearch.js
+++ b/src/AddressSearch.js
@@ -5,7 +5,7 @@ import Geocoder from 'react-mapbox-gl-geocoder';
import location from './utils/images/location.svg'; // with import
const mapAccess = {
- mapboxApiAccessToken: 'pk.eyJ1IjoiYmxvY3Bvd2VyIiwiYSI6ImNqd202bngzazE3c2o0OW4wM2IzbG00Y2cifQ.ZdSoYvbdw4fuIul8PQ3sBQ'
+ mapboxApiAccessToken: process.env.REACT_APP_MAPBOX_TOKEN
}
const queryParams = {
@@ -48,42 +48,61 @@ export default class AddressSearch extends React.Component {
}
render() {
- const {viewport} = this.state
-
+ let url = document.URL
+ let address = decodeURI(url.split('.io/')[1])
let addressData = "";
- if(this.state.addressFound === false){
+ if(address === "undefined"){
+ const {viewport} = this.state;
+ if(this.state.addressFound === false){
+ addressData = (
+
+ )
+ } else {
addressData = (
-
+
)
- } else {
+ }
+ }
+ else{
addressData = (
-
+
)
+ }
+
+ let message = "";
+ if(this.props.message !== '') {
+ message = (
+
+ Sorry. {this.props.message}!
+
+ );
}
+
const content = (
+ {message}
What is your building address?
We'll use this information to determine if BlocPower is available in your area.
-
-
+
+
{addressData}
-
+
Having trouble entering your address?
Please email us at support@blocpower.io
diff --git a/src/App.css b/src/App.css
index c7fe86bcf814bda397c0ded16a243e49a8573a2e..53ddbf8070ceb6def4eb5e96e6770758b3f7124e 100644
--- a/src/App.css
+++ b/src/App.css
@@ -111,6 +111,20 @@
width: 100%;
}
+.addressSearch {
+ width: 70%;
+ margin-left: 15% !important;
+ margin-right: 15% !important;
+}
+
+.addressSearchIcon {
+ background: #333333;
+ color: #FFFFFF;
+ padding-top: 3px;
+ margin-left: 15px;
+ height: 35px;
+}
+
.addressSearchSubTitle {
font-size: 1em;
margin-top: 25px;
@@ -131,6 +145,17 @@
margin-bottom: 20px;
}
+.errorMessage {
+ padding: 15px;
+ border: 2px solid #CCCCCC;
+ width: 50%;
+ margin-left: 25%;
+ margin-right: 25%;
+ margin-bottom: 5%;
+ color: crimson;
+ background: #EFEFEF;
+}
+
.react-geocoder input {
width: 100% !important;
}
@@ -216,7 +241,7 @@
width: 100%;
color: #002F43;
font-weight: bold;
- padding-left: 0;
+ padding-left: 0;
padding-right: 0;
font-family: 'AvenirNext';
}
diff --git a/src/App.js b/src/App.js
index 85a2b2fd785810fe7b763d4ca052de28b7cbb430..38bae9f269abde70c025f569667535ce4431439f 100644
--- a/src/App.js
+++ b/src/App.js
@@ -14,36 +14,30 @@ import ThankYou from './ThankYou';
import Congrats from './Congrats';
import FinanceInterest from './FinanceInterest';
import WaitList from './WaitList';
+import Contact from './Contact';
import ReviewAnswers from './ReviewAnswers';
-import phone from './utils/images/icon-phone.svg';
-import { questionTree, initialQuestions } from './constants';
+import { questionTree } from './constants';
import { connect } from 'react-redux';
-import { verifyUser, verifyToken, submitAnswer, submitBuilding, completeQuestionnaire } from './actions';
+import { submitContact, submitAnswer, submitBuilding, submitQuestionnaire } from './actions';
import './App.css';
import jsonp from "jsonp";
import ReactGA from 'react-ga';
+
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
- isReturningUser: false,
- isNewUser: true,
submitted: false,
disabled: true,
- selectedBuildingId: -1,
- showUserAlert: false,
- showTokenAlert: true,
- token: '',
- userBuildingId: -1,
+ surveyId: -1,
+ buildingId: -1,
buildingQualified: false,
form: {
- FNAME: '',
- LNAME: '',
- EMAIL: '',
- PHONE: '',
- returningEmail: '',
- address: '',
+ firstName: '',
+ lastName: '',
+ email: '',
+ phoneNumber: '',
},
factors: {
fuel: '',
@@ -52,7 +46,8 @@ class App extends React.Component {
heatingSystemPlan: '',
buildingTypes: '',
},
- question: '',
+ prevQuestion: '',
+ question: 'addressSearch',
reviewQuestions: [],
questions: this.resetQuestions(),
pages: {
@@ -70,6 +65,7 @@ class App extends React.Component {
title: 'What is your building address?',
answer: '',
value: '',
+ prev: 'addressSearch',
next: 'fuels',
},
fuels: {
@@ -158,7 +154,7 @@ class App extends React.Component {
value: 0,
answerIds: [1, 2],
prev: '',
- next: 'reviewAnswers',
+ next: 'contact',
},
waitList: {
id: 10,
@@ -167,6 +163,11 @@ class App extends React.Component {
value: 0,
answerIds: [1, 2],
prev: 'buildingTypes',
+ next: 'contact',
+ },
+ contact: {
+ title: 'Your Information',
+ prev: '',
next: 'reviewAnswers',
},
reviewAnswers: {
@@ -176,17 +177,7 @@ class App extends React.Component {
};
}
- componentDidMount() {
- const url = window.location.href;
- const token = url.substring(url.lastIndexOf('/') + 1);
- if(token !== ''){
- this.verifyToken(token);
- }
- }
-
- prevQuestion = (question) => {
- this.setQuestion(this.state.questions[question].prev);
- }
+ componentDidMount() { }
nextQuestion = (question, answer, value) => {
const questionAnswers = {};
@@ -204,30 +195,54 @@ class App extends React.Component {
questionAnswers[questions[question].id] = value;
}
+ questions.financeInterest.next = "contact";
this.setState({ questions }, () => {
this.setQuestion(this.state.questions[question].next);
if (question === 'addressSearch') {
this.props.onSubmitBuilding({
address: this.state.questions[question].value,
- token: this.state.token,
});
} else {
- const userBuildingId = Object.keys(this.props.buildings.data)[0] === undefined
- ? this.state.userBuildingId : Object.keys(this.props.buildings.data)[0];
Object.keys(questionAnswers).forEach(questionId => {
this.props.onSubmitAnswer({
questionId: questionId,
answerId: questionAnswers[questionId],
- userBuildingId,
- // userBuildingId: Object.keys(this.props.buildings.data)[0],
+ surveyId: this.props.building.data.surveyId,
+ buildingId: this.props.building.data.buildingId,
+ userId: this.props.building.data.userId,
});
});
}
});
}
+ submitContact = (contact) => {
+ this.setQuestion(this.state.questions['contact'].next);
+ this.setState({
+ form: {
+ firstName: contact.firstName,
+ lastName: contact.lastName,
+ phoneNumber: contact.phoneNumber,
+ email: contact.email,
+ buildingId: this.props.building.data.buildingId,
+ userId: this.props.building.data.userId,
+ },
+ }, () => {
+ this.props.onSubmitContact(this.state.form);
+ });
+ }
+
+ prevQuestion = (question) => {
+ this.setQuestion(this.state.questions[question].prev);
+ }
+
setQuestion = (question) => {
- this.setState({ question });
+ this.setState({
+ question,
+ prevQuestion: Object.keys(this.state.questions).includes(question) ? this.state.questions[question].prev : '',
+ }, () => {
+ console.log(this.state.question);
+ });
}
setFuelType = (fuel) => {
@@ -293,7 +308,6 @@ class App extends React.Component {
tree.input.buildingTypes.includes(this.state.factors.buildingTypes)
) {
found = true;
-
const questions = this.state.questions;
questions.buildingTypes.next = tree.output.nextQuestion;
questions[tree.output.finalQuestion].next = tree.output.finalPage;
@@ -313,6 +327,7 @@ class App extends React.Component {
questions.financeInterest.prev = 'buildingTypes';
}
+ questions.contact.next = "reviewAnswers";
this.setState({ questions }, () => {
this.setQuestion(tree.output.nextQuestion);
});
@@ -325,114 +340,36 @@ class App extends React.Component {
questions.financeInterest.next = 'reviewAnswers';
questions.financeInterest.prev = 'buildingTypes';
questions.reviewAnswers.next = 'thankYou';
+ questions.contact.next = "reviewAnswers";
this.setState({ questions }, () => {
this.setQuestion('financeInterest');
});
}
- const userBuildingId = Object.keys(this.props.buildings.data)[0] === undefined
- ? this.state.userBuildingId : Object.keys(this.props.buildings.data)[0];
this.props.onSubmitAnswer({
questionId: 6,
answerId: answer,
- userBuildingId,
+ buildingId: this.props.building.data.buildingId,
+ surveyId: this.props.building.data.surveyId,
+ userId: this.props.building.data.userId,
});
}
- newUser = () => {
- this.setState({
- isNewUser: !this.state.isNewUser,
- isReturningUser: false,
- showUserAlert: false,
- showTokenAlert: false,
- })
- }
-
- returningUser = () => {
- this.setState({
- isReturningUser: !this.state.isReturningUser,
- isNewUser: false,
- showUserAlert: false,
- showTokenAlert: false,
- })
- }
-
- validateInputs() {
- if (this.state.isNewUser === true && this.validateNewUser() === false) {
- return false;
- }
-
- if (this.state.isReturningUser === true && this.validateReturningUser() === false) {
- return false;
- }
-
- return true;
- }
-
- validateNewUser() {
- const emptyFields = [];
- const invalidFields = [];
- const errorMessage = [];
- const validEmail = /^$|^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/;
- 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 (!(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;
- }
-
- validateReturningUser() {
- const validEmail = /^$|^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/;
- if (this.state.form.returningEmail.toString().replace(/^\s+|\s+$/g, '') === '') {
- alert('Email address is empty!');
- return false;
- }
- if (!(validEmail.test(this.state.form.returningEmail))) {
- alert('Email address is invalid!');
- return false;
- }
- return true;
- }
-
-
submit = () => {
- const userBuildingId = Object.keys(this.props.buildings.data)[0] === undefined
- ? this.state.userBuildingId : Object.keys(this.props.buildings.data)[0];
- this.setState({
- submitted: true,
- }, () => {
- this.props.onSubmitQuestionnaire({
- token: this.state.token,
- userBuildingId,
- buildingQualified: this.state.buildingQualified,
- });
+ this.setState({
+ submitted: true,
+ }, () => {
+ this.props.onSubmitQuestionnaire({
+ firstName: this.state.form.firstName,
+ lastName: this.state.form.lastName,
+ email: this.state.form.email,
+ phone: this.state.form.phoneNumber,
+ surveyId: this.props.building.data.surveyId,
+ buildingId: this.props.building.data.buildingId,
+ buildingQualified: this.state.buildingQualified,
});
- this.setQuestion(this.state.questions.reviewAnswers.next);
+ });
+ this.setQuestion(this.state.questions.reviewAnswers.next);
}
handleInputChange = (event) => {
@@ -446,44 +383,9 @@ class App extends React.Component {
});
}
- verifyUser = (userType) => {
- let userData = {};
- // New user
- if (userType == 1) {
- if (this.state.form.EMAIL !== '') {
- this.handleSubmit();
- }
- userData = {
- firstName: this.state.form.FNAME,
- lastName: this.state.form.LNAME,
- phoneNumber: this.state.form.PHONE,
- email: this.state.form.EMAIL,
- userType: 1,
- };
- }
- // Returning user
- if (userType == 2) {
- userData = {
- email: this.state.form.returningEmail,
- userType: 2,
- };
- }
-
- if (this.validateInputs()) {
- this.props.onVerifyUser(userData);
- this.setState({
- showUserAlert: true,
- showTokenAlert: false,
- });
- }
- }
-
handleSubmit() {
const action = process.env.REACT_APP_MAILCHIMP_URL;
- const fields = ['FNAME',
- 'LNAME',
- 'EMAIL',
- 'PHONE']
+ const fields = ['FNAME', 'LNAME', 'EMAIL', 'PHONE'];
const values = fields.map(field => {
return `${field}=${encodeURIComponent(this.state.form[field])}`;
}).join("&");
@@ -492,385 +394,112 @@ class App extends React.Component {
jsonp(url, { param: "c" });
};
- verifyToken = (token) => {
- this.props.onVerifyToken({ token: token.toString() });
- this.setState({
- showUserAlert: false,
- showTokenAlert: true,
- token,
- });
- }
-
- chooseBuilding = (buildingId, questionAnswers, userBuildingId) => {
- // Update questions state
- this.setState({
- userBuildingId,
- questions: this.resetQuestions(),
- }, () => {
- const questionIds = Object.keys(questionAnswers);
- const questions = this.state.questions;
- Object.keys(initialQuestions).forEach(question => {
- const questionId = initialQuestions[question].id;
- if (
- questionId !== undefined &&
- (
- questionIds.includes(questionId) ||
- questionIds.includes(questionId.toString())
- )
- ) {
- questions[question].value = questionAnswers[questionId];
- if (questions[question].answers !== undefined) {
- questions[question].answer = questions[question].answers[questionAnswers[questionId]];
- } else {
- questions[question].answer = questionAnswers[questionId];
- }
- }
-
- if (questionId === undefined &&
- questions[question].questions !== undefined &&
- Array.isArray(questions[question].questions) === true) {
- questions[question].questions.forEach((question_, id) => {
- if (
- questionIds.includes(question_.id) ||
- questionIds.includes(question_.id.toString())
- ) {
- questions[question].questions[id].value = questionAnswers[question_.id];
- questions[question].questions[id].answer = questionAnswers[question_.id];
- }
- });
- }
- });
-
- this.setState({
- selectedBuildingId: buildingId,
- questions: buildingId === 0 ? initialQuestions : questions,
- }, () => {
- console.log(this.state.questions);
- });
- });
- }
-
render() {
ReactGA.initialize('UA-67611405-11');
ReactGA.pageview('/intake');
- let content = "";
- let alert = "";
-
- if (this.props.token.data !== undefined && this.props.token.data !== null && this.props.token.data.success === true) {
- const answers = this.props.token.data.data.answers;
- const buildings = this.props.token.data.data.buildings;
- const user = this.props.token.data.data.user;
- const questions = {
- addressSearch: ,
- fuels: ,
- heatDistribution: ,
- heatingSystemAge: ,
- heatingSystemPlan: ,
- buildingTypes: ,
- utilityBills: ,
- comfortIssues: ,
- financeInterest: ,
- waitList: ,
- reviewAnswers: ,
- };
-
- let userBuildingId = 0;
- if (this.props.buildings.data !== undefined && Object.keys(this.props.buildings.data).length > 0) {
- userBuildingId = Object.keys(this.props.buildings.data)[0];
- }
-
- if (Object.keys(this.state.pages).includes(this.state.question)) {
- content = this.state.pages[this.state.question];
- } else if (Object.keys(questions).includes(this.state.question)) {
- content = questions[this.state.question];
- } else if (buildings.length > 0) {
- const completedIcon = (✔ Completed
);
- const incompletedIcon = (⚠ Incomplete
);
-
- content = (
-
-
- Welcome, {user.firstName} {user.lastName}
-
-
- Select a building to continue
-
- {
- buildings.map(building => {
- let buttonStyle = "";
- if (this.state.selectedBuildingId === building.buildingId) {
- buttonStyle = "selectedBuildingButton";
- } else {
- buttonStyle = "buildingButton";
- }
-
- if (building.completed === true) {
- buttonStyle += " completedButton";
- } else {
- buttonStyle += " incompletedButton";
- }
-
- return (
-
this.chooseBuilding(building.buildingId, building.questions, building.userBuildingId)}
- >
- { building.completed === true ? completedIcon : incompletedIcon }
- {building.address}
-
- );
- })
- }
-
this.chooseBuilding(0, {}, 0)}
- >
- + New Building
-
-
-
-
-
-
-
- );
- } else {
- content = questions.addressSearch;
- }
- } else if (this.props.user.data !== undefined && this.props.user.data !== null && this.props.user.data.success === true) {
- content = (
-
-
Successful.
- We have sent you an email, please click on the link in your email to continue the questionniare.
-
- );
- } else {
- if(this.props.user.loading === true && this.state.showUserAlert == true) {
- alert = (
-
- Processing ...
-
- );
- } else if (this.props.user.data !== undefined &&
- this.props.user.data !== null &&
- this.props.user.data.success === false &&
- this.state.showUserAlert == true
- ) {
- alert = (
-
- {this.props.user.data.message}
-
- );
- }
-
- if (this.props.token.data !== undefined &&
- this.props.token.data !== null &&
- this.props.token.data.success === false &&
- this.state.showTokenAlert == true
- ) {
- alert = (
-
- {this.props.token.data.message}
-
- );
- }
- let title = "";
- let newUserButton = "";
- let returningUserButton = "";
- let newUser = "";
- let returningUser = "";
- let note = "";
-
- if (this.state.isNewUser === false && this.state.isReturningUser === false) {
- newUserButton = (
-
- );
- returningUserButton = (
-
- );
- }
-
- if (this.state.isNewUser === true || this.state.isReturningUser === true) {
- title = (
-
- See if your building qualifies
-
- );
- note = (
-
-

{' '}
- If you prefer to find out on the phone, call 646-504-2236
-
- )
- }
+ const building = this.props.building;
+ // const questions = this.props.questions;
+ const contact = this.props.contact;
+ const complete = this.props.complete;
- if (this.state.isNewUser === true) {
- newUser = (
-
-
-
- this.handleInputChange(e)}
- className="input"
- />
-
-
-
-
- this.handleInputChange(e)}
- className="input"
- />
-
-
- this.handleInputChange(e)}
- className="input"
- />
- this.handleInputChange(e)}
- className="input"
- />
-
-
-
-
-
-
- );
- }
+ let addressSearchMessage = "";
+ if (building.data !== undefined && building.data.success === false && building.data.message !== undefined) {
+ addressSearchMessage = this.props.building.data.message;
+ }
- if (this.state.isReturningUser === true) {
- returningUser = (
-
- this.handleInputChange(e)}
- className="input"
- />
-
-
-
- );
- }
+ const questions = {
+ addressSearch: ,
+ fuels: ,
+ heatDistribution: ,
+ heatingSystemAge: ,
+ heatingSystemPlan: ,
+ buildingTypes: ,
+ utilityBills: ,
+ comfortIssues: ,
+ financeInterest: ,
+ waitList: ,
+ contact: ,
+ reviewAnswers: ,
+ };
- content = (
-
- {alert}
- {newUserButton}
- {returningUserButton}
- {title}
- {newUser}
- {returningUser}
- {note}
-
- )
+ let content = "";
+ if (this.props.building.data !== undefined && this.props.building.data.buildingId !== undefined && Object.keys(this.state.questions).indexOf(this.state.question) > -1) {
+ content = questions[this.state.question];
+ } else if (Object.keys(this.state.pages).indexOf(this.state.question) > -1) {
+ content = this.state.pages[this.state.question];
+ } else {
+ content = questions[this.state.questions[this.state.question].prev];
}
return (
@@ -894,19 +523,19 @@ class App extends React.Component {
const mapStatetoProps = state => {
return {
- user: state.user,
- token: state.token,
- buildings: state.buildings,
+ building: state.building,
+ questions: state.questions,
+ contact: state.contact,
+ complete: state.complete,
}
}
const mapDispatchtoProps = dispatch => {
return {
- onVerifyUser: (userData) => dispatch(verifyUser(userData)),
- onVerifyToken: (token) => dispatch(verifyToken(token)),
onSubmitBuilding: (data) => dispatch(submitBuilding(data)),
onSubmitAnswer: (data) => dispatch(submitAnswer(data)),
- onSubmitQuestionnaire: (data) => dispatch(completeQuestionnaire(data)),
+ onSubmitContact: (data) => dispatch(submitContact(data)),
+ onSubmitQuestionnaire: (data) => dispatch(submitQuestionnaire(data)),
}
};
diff --git a/src/BuildingTypes.js b/src/BuildingTypes.js
index a41eef050d7a6ca96b3e891453253e1bdac989aa..3acb862538944e5a9d6cab1c24bc16f5e8c74e7d 100644
--- a/src/BuildingTypes.js
+++ b/src/BuildingTypes.js
@@ -38,7 +38,6 @@ export default class BuildingTypes extends React.Component {
);
}
-
chooseAnswer = (answer) => {
this.setState({ answer });
}
diff --git a/src/Contact.js b/src/Contact.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc7af3497725303e342eb529c6de5c4c61ab3462
--- /dev/null
+++ b/src/Contact.js
@@ -0,0 +1,151 @@
+import React from "react";
+import { Row, Col, Input, Button } from 'reactstrap';
+import './index.css';
+
+
+export default class Contact extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ form: this.props.form,
+ message: '',
+ };
+ }
+
+ handleInputChange = (event) => {
+ const val = event.target.value;
+ const name = event.target.name;
+ this.setState({
+ form: {
+ ...this.state.form,
+ [name]: val,
+ },
+ });
+ }
+
+ prevQuestion = () => {
+ this.props.prevQuestion('comfortIssues');
+ }
+
+ submitContact = () => {
+ if (this.validateContact()) {
+ const form = this.state.form;
+ if (this.state.form.phoneNumber.trim().length === 0) {
+ form.phoneNumber = 0;
+ }
+ this.props.submitContact(form);
+ }
+ }
+
+ validateContact() {
+ const emptyFields = [];
+ const invalidFields = [];
+ const errorMessage = [];
+ const validEmail = /^$|^[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[A-Za-z]+$/;
+ const validPhone = /^$|^\(?(\d{3})\)?[- ]?(\d{3})[- ]?(\d{4})$/;
+
+ if (this.state.form.firstName.toString().replace(/^\s+|\s+$/g, '') === '') {
+ emptyFields.push('First Name');
+ }
+ if (this.state.form.lastName.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.phoneNumber.toString().replace(/^\s+|\s+$/g, '') !== '' &&
+ !(validPhone.test(this.state.form.phoneNumber))) {
+ invalidFields.push('Phone number');
+ }
+ 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;
+ }
+
+ render() {
+ const content = (
+
+ );
+
+ return (
+
+ {content}
+
+ );
+ }
+}
diff --git a/src/ReviewAnswers.js b/src/ReviewAnswers.js
index 4f8b6fa823203f4db8d84026572eb20ff5f51fbc..8d1ae31167298ddb02d1cde918e3b236b69b4b35 100644
--- a/src/ReviewAnswers.js
+++ b/src/ReviewAnswers.js
@@ -23,6 +23,8 @@ export default class ReviewAnswers extends React.Component {
render() {
const questions = this.props.questions;
+ const phoneNumber = this.props.form.phoneNumber === 0 ? 'N/A' : this.props.form.phoneNumber;
+
const content = (
@@ -127,6 +129,28 @@ export default class ReviewAnswers extends React.Component {
}
})
}
+
+
+
+
+
+ Your Information
+
+
+ First Name : {this.props.form.firstName}
+ Last Name : {this.props.form.lastName}
+ Email : {this.props.form.email}
+ Phone Number : {phoneNumber}
+
+
+
+
+

this.editAnswer('contact') } />
+
+
+
+
+
{
- const blocLinkUrl = process.env.REACT_APP_BLOCLINK_URL;
- ReactGA.event({
- category: 'Call to Action',
- action: 'Button',
- label: 'Verify User'
- });
- return (dispatch) => {
- dispatch({ type: "UserRequested" });
- return axios.put(
- `${blocLinkUrl}/buildings/bis/verify-user/`,
- user,
- { headers : { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' } },
- )
- .then(res => dispatch(
- { type: "UserSucceeded", data: res }))
- .catch(err => dispatch(
- { type: "UserFailed", msg: err.response.data }));
- }
-}
-
-// asynchronous action creator
-export const verifyToken = (user) => {
- const blocLinkUrl = process.env.REACT_APP_BLOCLINK_URL;
- ReactGA.event({
- category: 'Call to Action',
- action: 'Link',
- label: 'Verify Token'
- });
- return (dispatch) => {
- dispatch({ type: "TokenRequested" });
- return axios.put(
- `${blocLinkUrl}/buildings/bis/verify-token/`,
- user,
- { headers : { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' } },
- )
- .then(res => dispatch(
- { type: "TokenSucceeded", data: res }))
- .catch(err => dispatch(
- { type: "TokenFailed", msg: err.response.data }));
- }
-}
// asynchronous action creator
export const submitBuilding = (data) => {
@@ -95,7 +52,29 @@ export const submitAnswer = (data) => {
}
}
-export const completeQuestionnaire = (user) => {
+// asynchronous action creator
+export const submitContact = (contact) => {
+ const blocLinkUrl = process.env.REACT_APP_BLOCLINK_URL;
+ ReactGA.event({
+ category: 'Call to Action',
+ action: 'Button',
+ label: 'Submit Contact'
+ });
+ return (dispatch) => {
+ dispatch({ type: "ContactRequested" });
+ return axios.put(
+ `${blocLinkUrl}/buildings/bis/submit-contact/`,
+ contact,
+ { headers : { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' } },
+ )
+ .then(res => dispatch(
+ { type: "ContactSucceeded", data: res }))
+ .catch(err => dispatch(
+ { type: "ContactFailed", msg: err.response.data }));
+ }
+}
+
+export const submitQuestionnaire = (data) => {
ReactGA.event({
category: 'Call to Action',
action: 'Button',
@@ -105,8 +84,8 @@ export const completeQuestionnaire = (user) => {
return (dispatch) => {
dispatch({ type: "CompleteRequested" });
return axios.put(
- `${blocLinkUrl}/buildings/bis/complete/`,
- user,
+ `${blocLinkUrl}/buildings/bis/submit-questionnaire/`,
+ data,
{ headers : { 'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8' } },
)
.then(res => dispatch(
diff --git a/src/constants.js b/src/constants.js
index 22ee8771567d2d80d09b4baee9258683830624ff..d8ef6f1fcee2bb7de89a90989c91a5a88c10c0c8 100644
--- a/src/constants.js
+++ b/src/constants.js
@@ -9,7 +9,7 @@ const questionTree = [
},
output: {
nextQuestion: 'financeInterest',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'congrats',
},
},
@@ -23,7 +23,7 @@ const questionTree = [
},
output: {
nextQuestion: 'utilityBills',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'congrats',
},
},
@@ -37,7 +37,7 @@ const questionTree = [
},
output: {
nextQuestion: 'waitList',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'thankYou',
},
},
@@ -51,7 +51,7 @@ const questionTree = [
},
output: {
nextQuestion: 'financeInterest',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'thankYou',
},
},
@@ -65,7 +65,7 @@ const questionTree = [
},
output: {
nextQuestion: 'financeInterest',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'congrats',
},
},
@@ -79,7 +79,7 @@ const questionTree = [
},
output: {
nextQuestion: 'utilityBills',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'congrats',
},
},
@@ -93,7 +93,7 @@ const questionTree = [
},
output: {
nextQuestion: 'financeInterest',
- finalQuestion: 'reviewAnswers',
+ finalQuestion: 'contact',
finalPage: 'congrats',
},
},
@@ -192,7 +192,7 @@ const initialQuestions = {
value: 0,
answerIds: [1, 2],
prev: '',
- next: 'reviewAnswers',
+ next: 'contact',
},
waitList: {
id: 10,
@@ -201,6 +201,10 @@ const initialQuestions = {
value: 0,
answerIds: [1, 2],
prev: 'buildingTypes',
+ next: 'contact',
+ },
+ contact: {
+ prev: '',
next: 'reviewAnswers',
},
reviewAnswers: {
diff --git a/src/reducers/reducer.js b/src/reducers/reducer.js
index d5bc6bddc8c6af7e34840506a14674654f563cab..459b690805a7e806dbf8d1cc2ee7d7726c299be0 100644
--- a/src/reducers/reducer.js
+++ b/src/reducers/reducer.js
@@ -1,17 +1,17 @@
const intialState = {
- user: {
+ building: {
loading: false,
- data: null,
+ data: {},
error: false,
},
- token: {
+ questions: {
loading: false,
- data: null,
+ data: {},
error: false,
},
- buildings: {
+ contact: {
loading: false,
- data: {},
+ data: null,
error: false,
},
complete: {
@@ -23,77 +23,47 @@ const intialState = {
const reducer = (state = intialState, action) => {
switch (action.type) {
- case "UserRequested":
+ case "ContactRequested":
return {
...state,
- user: {
- ...state.user,
+ contact: {
+ ...state.contact,
loading: true,
error: false,
},
};
- case "UserSucceeded":
+ case "ContactSucceeded":
return {
...state,
- user: {
+ contact: {
data: action.data.data,
loading: false,
error: false,
},
};
- case "UserFailed":
+ case "ContactFailed":
return {
...state,
- user: {
+ contact: {
data: action.msg,
loading: false,
error: true,
},
};
- case "TokenRequested":
- return {
- ...state,
- token: {
- ...state.token,
- loading: true,
- error: false,
- },
- };
- case "TokenSucceeded":
- return {
- ...state,
- token: {
- data: action.data.data,
- loading: false,
- error: false,
- },
- };
- case "TokenFailed":
- return {
- ...state,
- token: {
- data: action.msg,
- loading: false,
- error: true,
- },
- };
case "BuildingRequested":
return {
...state,
- buildings: {
- ...state.buildings,
+ building: {
+ ...state.building,
loading: true,
error: false,
},
};
case "BuildingSucceeded": {
- const userBuildingId = action.data.data.data.userBuildingId;
- const buildings = state.buildings;
- buildings.data[userBuildingId] = {};
return {
...state,
- buildings: {
- data: buildings.data,
+ building: {
+ data: action.data.data.data,
loading: false,
error: false,
},
@@ -102,7 +72,7 @@ const reducer = (state = intialState, action) => {
case "BuildingFailed":
return {
...state,
- buildings: {
+ building: {
data: action.msg,
loading: false,
error: true,
@@ -180,7 +150,6 @@ const reducer = (state = intialState, action) => {
},
};
case "CompleteFailed":
- console.log('CompleteFailed');
return {
...state,
complete: {