diff --git a/package-lock.json b/package-lock.json index aaa3942ee6a2625bfebaf9b596d0dae82440d894..cac1c10c7f5d6f2293652485080a0f466feff199 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "integrity": "sha1-zs/PrXVLTCdl/l0puBswGImtbC4=", "optional": true, "requires": { - "@types/react": "15.6.7" + "@types/react": "*" } }, "abab": { @@ -5008,6 +5008,11 @@ "is-symbol": "^1.0.1" } }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -6163,6 +6168,11 @@ "assert-plus": "^1.0.0" } }, + "gl-matrix": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.2.1.tgz", + "integrity": "sha512-YYVO8jUSf6+SakL4AJmx9Jc7zAZhkJQ+WhdtX3VQe5PJdCOX6/ybY4x1vk+h94ePnjRn6uml68+QxTAJneUpvA==" + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -8905,6 +8915,15 @@ "object-visit": "^1.0.0" } }, + "mapbox": { + "version": "1.0.0-beta10", + "resolved": "https://registry.npmjs.org/mapbox/-/mapbox-1.0.0-beta10.tgz", + "integrity": "sha1-A3VhvLlcvcBm0d/34s4dbIU5y44=", + "requires": { + "es6-promise": "^4.0.5", + "rest": "^2.0.0" + } + }, "math-expression-evaluator": { "version": "1.2.17", "resolved": "https://registry.npmjs.org/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz", @@ -13397,6 +13416,15 @@ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" }, + "react-mapbox-gl-geocoder": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/react-mapbox-gl-geocoder/-/react-mapbox-gl-geocoder-1.1.0.tgz", + "integrity": "sha512-U8fVUlj7Sb19KOgkKvfr3MPuqiGZ+ldHwwfo4BxBv7cyr397PQ/0o2XiC/Nz4PvN7dbIFHz7JfuVaq/MFZ5oHw==", + "requires": { + "mapbox": "^1.0.0-beta10", + "viewport-mercator-project": "^6.0.0" + } + }, "react-measure": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/react-measure/-/react-measure-2.0.2.tgz", @@ -14214,6 +14242,11 @@ } } }, + "rest": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rest/-/rest-2.0.0.tgz", + "integrity": "sha1-bfrfZqQFxJz71bS9JbWf0pzYYbw=" + }, "restore-cursor": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", @@ -16326,6 +16359,15 @@ "extsprintf": "^1.2.0" } }, + "viewport-mercator-project": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/viewport-mercator-project/-/viewport-mercator-project-6.2.3.tgz", + "integrity": "sha512-QQb0/qCLlP4DdfbHHSWVYXpghB2wkLIiiZQnoelOB59mXKQSyZVxjreq1S+gaBJFpcGkWEcyVtre0+2y2DTl/Q==", + "requires": { + "@babel/runtime": "^7.0.0", + "gl-matrix": "^3.0.0" + } + }, "vm-browserify": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", diff --git a/package.json b/package.json index ec70e9e35cdf2146befdee5a88a946d049faa7d6..fa67fa9efc87cd5749d4849dc24b26d0cc0d55fc 100644 --- a/package.json +++ b/package.json @@ -90,6 +90,7 @@ "react-highcharts": "^12.0.0", "react-json-tree": "^0.10.9", "react-leaflet": "^1.4.1", + "react-mapbox-gl-geocoder": "^1.1.0", "react-modal": "^3.8.1", "react-number-format": "^4.2.0", "react-placeholder": "^1.0.6", diff --git a/src/containers/SearchBar/index.js b/src/containers/SearchBar/index.js index ee34c163ef653fd321608b4670b45ce59190eac1..e2748b310d22d30304b2b59da1b2327162c6b64e 100644 --- a/src/containers/SearchBar/index.js +++ b/src/containers/SearchBar/index.js @@ -1,9 +1,8 @@ import React, { Component } from 'react'; -import ReactGA from 'react-ga'; import PropTypes from 'prop-types'; +import Geocoder from 'react-mapbox-gl-geocoder'; import { - Nav, NavItem, Form, Input, - Dropdown, DropdownToggle, DropdownMenu, DropdownItem, + Row, Col, Nav, NavItem, } from 'reactstrap'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; @@ -15,51 +14,33 @@ import { import './styles.css'; import { buildingListPropTypes } from './propTypes'; -/* eslint-disable quote-props */ -const SEARCH_TYPE_LIST = { - 'address': 'address', - 'address + zip': 'address', - 'address + borough': 'address', - 'bbl': 'bbl', - 'building id': 'building_id', -}; -const SEARCH_BOROUGH_LIST = { - 'Manhattan': 1, - 'Bronx': 2, - 'Brooklyn': 3, - 'Queens': 4, - 'Staten Island': 5, +const mapAccess = { + mapboxApiAccessToken: process.env.REACT_APP_MAPBOX_TOKEN, }; -const SEARCH_CITY_LIST = { - 'NYC': 1, +const queryParams = { + country: 'us', }; class SearchBar extends Component { constructor(props) { super(props); this.state = { - type: this.props.buildingList.type, - borough: this.props.buildingList.borough, - zipcode: this.props.buildingList.zipcode, - term: this.props.buildingList.term, - city: this.props.buildingList.city, - cityDropdownOpen: false, - searchByDropdownOpen: false, - boroughDropdownOpen: false, + viewport: {}, + addressFound: false, + address: '', + loadingAddressSearchBtn: false, + disabledAddressSearchBtn: true, + subscribed: false, }; } componentDidMount() { - if (!(this.state.term === '' && this.state.type === 'address')) { - this.getBuildings(this.state); - } else { - // Use the buildings stored in cookies to populate the buildingList - const buildingList = localStorage.activeBuildings; - if (buildingList !== undefined) { - this.props.buildingsSearched(JSON.parse(buildingList)); - } + // Use the buildings stored in cookies to populate the buildingList + const buildingList = localStorage.activeBuildings; + if (buildingList !== undefined) { + this.props.buildingsSearched(JSON.parse(buildingList)); } } @@ -68,279 +49,59 @@ class SearchBar extends Component { this.props.buildingList !== nextProps.buildingList ) { this.setState({ - type: nextProps.buildingList.type, - borough: nextProps.buildingList.borough, - zipcode: nextProps.buildingList.zipcode, - term: nextProps.buildingList.term, - city: nextProps.buildingList.city, + address: nextProps.buildingList.address, }); } } - onTermInputChange = (event) => { - this.setState({ - term: event.target.value, - }); - } - - onZipInputChange = (event) => { - this.setState({ - zipcode: event.target.value, - }); - } - - onFormSubmit = (event) => { - event.preventDefault(); - if (!(this.checkTermLength() || this.checkTermType())) { - this.getBuildings(this.state); - this.props.setNavbar(true); - } - } - getBuildings = (stateSource) => { - this.props.updateBuildingSearchParams( - stateSource.term, - stateSource.type, - stateSource.borough, - stateSource.zipcode, - stateSource.city, - ); - // Input the actual search type parameter here - const actualType = SEARCH_TYPE_LIST[stateSource.type]; - const args = {}; - args[actualType] = stateSource.term; - ReactGA.event({ category: 'Search', action: 'Request', label: `Address Searched: ${stateSource.term}` }); - ReactGA.event({ category: 'Search Type', action: 'Request', label: `${actualType}` }); - if (stateSource.type === 'address + zip' && stateSource.zipcode) { - args.zip = stateSource.zipcode; - } - if (stateSource.type === 'address + borough' && stateSource.borough) { - args.boro = SEARCH_BOROUGH_LIST[stateSource.borough]; - } - this.props.searchBuildings(args); - } - - checkTermLength = () => { - if (this.state.type === 'bbl') return this.state.term.length > 20; - else if (this.state.type === 'building id') return this.state.term.length > 10; - else if (this.state.type === 'lot id') return this.state.term.length > 10; - return false; - } - - checkTermEmpty = () => { - if (this.state.type === 'address + zip') { - if (this.state.zipcode && !this.state.term) { - return true; - } - } - if (this.state.type === 'address + borough') { - if (this.state.borough && !this.state.term) { - return true; - } - } - return false; - } - - checkTermType = () => { - if ( - this.state.type !== 'address' && - this.state.type !== 'address + zip' && - this.state.type !== 'address + borough' - ) { - return isNaN(this.state.term); - } - return false; - } - - showWarning = () => { - let warning = null; - if (this.checkTermLength()) warning = 'is too long'; - if (this.checkTermEmpty()) warning = 'cannot be empty'; - if (this.checkTermType()) warning = 'can only have numbers'; - if (this.checkTermLength() || this.checkTermType() || this.checkTermEmpty()) { - let type = this.state.type; - if (type === 'address + zip' || type === 'address + borough') { - type = 'address'; - } - return ( -