From f05fe3dba5cb25db8fdd6f0c030e7e3f7a68d7bd Mon Sep 17 00:00:00 2001 From: Tom Russell Date: Mon, 11 Feb 2019 09:04:19 +0000 Subject: [PATCH] Add postcode search box --- app/src/frontend/map.js | 22 ++++++- app/src/frontend/search-box.css | 29 +++++++++ app/src/frontend/search-box.js | 111 ++++++++++++++++++++++++++++++++ 3 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 app/src/frontend/search-box.css create mode 100644 app/src/frontend/search-box.js diff --git a/app/src/frontend/map.js b/app/src/frontend/map.js index 1efb7cb4..959e8355 100644 --- a/app/src/frontend/map.js +++ b/app/src/frontend/map.js @@ -3,10 +3,12 @@ import { Map, TileLayer, ZoomControl, AttributionControl } from 'react-leaflet-u import '../../node_modules/leaflet/dist/leaflet.css' import './map.css' -import ThemeSwitcher from './theme-switcher'; -import { parseCategoryURL } from '../parse'; -import Legend from './legend'; + import { HelpIcon } from './icons'; +import Legend from './legend'; +import { parseCategoryURL } from '../parse'; +import SearchBox from './search-box'; +import ThemeSwitcher from './theme-switcher'; const OS_API_KEY = 'NVUxtY5r8eA6eIfwrPTAGKrAAsoeI9E9'; @@ -24,9 +26,18 @@ class ColouringMap extends Component { zoom: 16 }; this.handleClick = this.handleClick.bind(this); + this.handleLocate = this.handleLocate.bind(this); this.themeSwitch = this.themeSwitch.bind(this); } + handleLocate(lat, lng, zoom){ + this.setState({ + lat: lat, + lng: lng, + zoom: zoom + }) + } + handleClick(e) { const is_edit = this.props.match.url.match('edit') const mode = is_edit? 'edit': 'view'; @@ -132,6 +143,11 @@ class ColouringMap extends Component { } + { + this.props.match.url !== '/'? ( + + ) : null + } ); } diff --git a/app/src/frontend/search-box.css b/app/src/frontend/search-box.css new file mode 100644 index 00000000..76fb64f2 --- /dev/null +++ b/app/src/frontend/search-box.css @@ -0,0 +1,29 @@ +.search-box { + position: absolute; + top: 3.625rem; + left: 25.5rem; + z-index: 1000; +} +.building.search-box { + top: 0.5rem; +} +.search-box form, +.search-box .search-box-results { + border-radius: 4px; + background: #fff; + box-shadow: 0px 0px 1px 1px #222222; +} +.search-box button { + margin-bottom: 0; +} +.search-box .search-box-results { + margin-top: 0.25rem; + list-style: none; + padding: 0; + overflow: hidden; +} +.search-box-result { + display: block; + padding: 0.25rem 0.5rem; + border-bottom: 1px solid #eee; +} diff --git a/app/src/frontend/search-box.js b/app/src/frontend/search-box.js new file mode 100644 index 00000000..6f838bf6 --- /dev/null +++ b/app/src/frontend/search-box.js @@ -0,0 +1,111 @@ +import React, { Component } from 'react'; + +import './search-box.css'; + +/** + * Search for location + */ +class SearchBox extends Component { + + constructor(props) { + super(props); + this.state = { + q: "", + results: [], + fetching: false + } + this.handleChange = this.handleChange.bind(this); + this.search = this.search.bind(this); + } + + // Update search term + handleChange(e) { + this.setState({ + q: e.target.value + }) + } + + // Query search endpoint + search(e) { + e.preventDefault(); + this.setState({ + fetching: true + }) + + fetch( + '/search?q='+this.state.q + ).then( + (res) => res.json() + ).then((data) => { + if (data && data.results){ + this.setState({ + results: data.results, + fetching: false + }) + } else { + console.error(data); + + this.setState({ + results: [], + fetching: false + }) + } + }).catch((err) => { + console.error(err) + + this.setState({ + results: [], + fetching: false + }) + }) + } + + render() { + const resultsList = this.state.results.length? + + : null; + return ( +
+
+ + +
+ { resultsList } +
+ ) + } +} + +export default SearchBox;