From a1368063a8a78363c3f4f3d8730e7c9f64a68e44 Mon Sep 17 00:00:00 2001 From: karimkawambwa <4308339+karimkawambwa@users.noreply.github.com> Date: Fri, 6 Mar 2020 11:42:01 -0330 Subject: [PATCH] Locate me feature --- src/assets/images/icons/locate.svg | 3 + .../ShareButton/SocialMediaButtons.js | 6 +- src/components/DocumentHead/PageHeads.js | 1 + src/components/Embeds/AirMap.js | 4 +- .../AirCityHeaderContent/RadialGauge.js | 4 +- src/components/SearchBar.js | 90 ++++++++++++++++--- src/pages/air/City.js | 5 +- src/pages/air/index.js | 4 +- 8 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 src/assets/images/icons/locate.svg diff --git a/src/assets/images/icons/locate.svg b/src/assets/images/icons/locate.svg new file mode 100644 index 00000000..4a72e139 --- /dev/null +++ b/src/assets/images/icons/locate.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/City/HostSensors/ShareButton/SocialMediaButtons.js b/src/components/City/HostSensors/ShareButton/SocialMediaButtons.js index b77e71bf..944f7c12 100644 --- a/src/components/City/HostSensors/ShareButton/SocialMediaButtons.js +++ b/src/components/City/HostSensors/ShareButton/SocialMediaButtons.js @@ -20,7 +20,11 @@ function SocialMediaButtons({ classes, city }) { ({ position: 'absolute' }, gaugeWhoGuidelineText: { - font: `bold ${theme.typography.body1.fontSize} ${theme.typography.h6.fontFamily}`, + font: `bold ${theme.typography.body1.fontSize} ${ + theme.typography.h6.fontFamily + }`, fill: 'white' }, gaugeNeedleItem: { diff --git a/src/components/SearchBar.js b/src/components/SearchBar.js index cf36e2d8..153fa536 100644 --- a/src/components/SearchBar.js +++ b/src/components/SearchBar.js @@ -1,10 +1,18 @@ -import React from 'react'; +import React, { useState } from 'react'; import PropTypes from 'prop-types'; import Select from 'react-select'; -import { MenuItem, Paper, TextField, Typography } from '@material-ui/core'; +import { + MenuItem, + Paper, + TextField, + Typography, + Grid +} from '@material-ui/core'; import { withStyles } from '@material-ui/core/styles'; +import { CITIES_LOCATION } from '../api'; +import locateIcon from '../assets/images/icons/locate.svg'; const styles = theme => ({ root: { @@ -132,7 +140,16 @@ Control.defaultProps = { selectProps: null }; -function Option({ children, innerProps, innerRef, isFocused, isSelected }) { +function Option({ + data, + children, + innerProps: { onClick, ...props }, + innerRef, + isFocused, + isSelected, + selectOption +}) { + const [label, setLabel] = useState(children); return ( { + if (data.value === 'locate-me') { + setLabel('LOCATING...'); + navigator.geolocation.getCurrentPosition( + async ({ coords: { latitude, longitude } }) => { + const { error, address } = await fetch( + `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${latitude}&lon=${longitude}` + ).then(res => res.json()); + + // If not really there + if (error || !address) { + setLabel('COULD NOT LOCATE'); + } else { + // Find country + const foundEntry = Object.entries(CITIES_LOCATION).find( + ([, country]) => address.country === country.name + ); + if (foundEntry) { + const [slug] = foundEntry; + selectOption({ value: slug }); + } else { + setLabel( +

+ {address.city}, {address.country} +
+ + Is not covered by sensorsAFRICA + +

+ ); + } + } + }, + failure => setLabel(failure.message.toUpperCase()), + { + timeout: 10000 + } + ); + } else { + onClick(e); + } + }} > - {children} + + {label} + + {data.value === 'locate-me' && ( + + icon + + )} +
); } Option.propTypes = { + selectOption: PropTypes.func.isRequired, + data: PropTypes.shape({}).isRequired, children: PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node @@ -275,11 +344,12 @@ const components = { DropdownIndicator: null }; -const DEFAULT_OPTIONS = [ - { value: 'nairobi', label: 'Nairobi, Kenya' }, - { value: 'lagos', label: 'Lagos, Nigeria' }, - { value: 'dar-es-salaam', label: 'Dar-es-Salaam, Tanzania' } -]; +const DEFAULT_OPTIONS = [{ value: 'locate-me', label: 'LOCATE ME' }].concat( + Object.values(CITIES_LOCATION).map(({ slug: value, name: label }) => ({ + value, + label + })) +); class SearchBar extends React.Component { constructor(props) { diff --git a/src/pages/air/City.js b/src/pages/air/City.js index e751c424..de098f87 100644 --- a/src/pages/air/City.js +++ b/src/pages/air/City.js @@ -102,8 +102,6 @@ const styles = () => ({ } }); -const CITY_PATHNAME = '/air/city'; - class City extends React.Component { constructor() { super(); @@ -207,7 +205,8 @@ class City extends React.Component { const searchedCity = (option && option.value) || DEFAULT_CITY; const { city } = this.state; if (searchedCity !== city) { - const path = `${CITY_PATHNAME}/${searchedCity}`; + const path = + city === 'locate-me' ? '/air/locate-me' : `/air/city/${searchedCity}`; const { history } = this.props; history.push(path); diff --git a/src/pages/air/index.js b/src/pages/air/index.js index a380590f..2ccd4036 100644 --- a/src/pages/air/index.js +++ b/src/pages/air/index.js @@ -19,7 +19,6 @@ import Support from '../../components/Support'; import HealthAndClimateImpacts from './HealthAndClimateImpacts'; import Showcase from '../../components/Showcase'; -const CITY_PATHNAME = '/air/city'; class AirHome extends React.Component { constructor(props) { super(props); @@ -28,7 +27,8 @@ class AirHome extends React.Component { } handleSearch(city) { - const path = `${CITY_PATHNAME}/${city.value}`; + const path = + city.value === 'locate-me' ? '/air/locate-me' : `/air/city/${city.value}`; const { history } = this.props; history.push(path); }