import React, { Component } from 'react'; import PropTypes from 'prop-types'; import './search-box.css'; import { SearchIcon } from './icons'; /** * Search for location */ class SearchBox extends Component { // TODO: add proper types static propTypes = { // TODO: generate propTypes from TS onLocate: PropTypes.func, isBuilding: PropTypes.bool }; constructor(props) { super(props); this.state = { q: '', results: [], fetching: false, //track the state of the search box i.e. collapsed or expanded. Default to true collapsedSearch: true, //is this a small screen device? if not we will disable collapse option smallScreen: false } this.handleChange = this.handleChange.bind(this); this.search = this.search.bind(this); this.handleKeyPress = this.handleKeyPress.bind(this); this.clearResults = this.clearResults.bind(this); this.clearQuery = this.clearQuery.bind(this); this.expandSearch = this.expandSearch.bind(this); this.onResize= this.onResize.bind(this); } // Update search term handleChange(e) { this.setState({ q: e.target.value }); // If the ‘clear’ icon has been clicked, clear results list as well if(e.target.value === '') { this.clearResults(); } } // Clear search results on ESC handleKeyPress(e){ if(e.keyCode === 27) { //ESC is pressed this.clearQuery(); this.clearResults(); } } clearResults(){ this.setState({ results: [] }); } clearQuery(){ this.setState({ q: '' }); } expandSearch(e){ this.setState(state => ({ collapsedSearch: !state.collapsedSearch })); } // Query search endpoint search(e) { e.preventDefault(); this.setState({ fetching: true }) fetch( '/api/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 }) }) } componentDidMount() { window.addEventListener('resize', this.onResize); if (window && window.innerHeight) { // if we're in the browser, pass in as though from event to initialise this.onResize({target: window}); } } componentWillUnmount() { window.removeEventListener('resize', this.onResize); } // On a real mobile device onResize() gets called when the virtual keyboard pops up (e.g. when entering search text) // so be careful what states are changed in this method (i.e. don't collapse the search box here) onResize(e) { this.setState({smallScreen: (e.target.innerWidth < 768)}); } render() { // if the current state is collapsed (and a mobile device) just render the icon if(this.state.collapsedSearch && this.state.smallScreen){ return(
) } const resultsList = this.state.results.length? : null; return (
{ resultsList }
) } } export default SearchBox;