Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/search location marker #2

Merged
merged 3 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .eslintcache

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/img/map-marker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 10 additions & 2 deletions src/App.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
.leaflet-container { display: flex;
.leaflet-container {
display: flex;
align-items: top;
justify-content: center;
width: 100vw; height: 100vh; }
width: 100vw; height: 100vh;
z-index: 0;
}

.leaflet-div-icon {
background: none;
border: none;
}
17 changes: 12 additions & 5 deletions src/actions/brewery.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import axios from 'axios';

export const BREWERIES_SET = 'BREWERIES_SET';
export const POSTCODE_QUERY_MADE = 'POSTCODE_QUERY_MADE';
export const INPUT_LOCATION_SET = 'INPUT_LOCATION_SET';
export const INPUT_LOCATION_NOT_FOUND = 'INPUT_LOCATION_NOT_FOUND';

export function setBreweries(payload) {
return {
Expand All @@ -10,21 +11,27 @@ export function setBreweries(payload) {
}
}

export function makePostcodeQuery(payload) {
export function setInputLocation(payload) {
return {
type: POSTCODE_QUERY_MADE,
type: INPUT_LOCATION_SET,
payload
}
}

export function setNotFoundError() {
return {
type: INPUT_LOCATION_NOT_FOUND,
}
}

export const getPostcodeCoordinates = (request) => (dispatch) => {
return new Promise(async () => {
await axios.get(`https://api.geoapify.com/v1/geocode/search?text=${request}&apiKey=4680392dcd4944afad13f1d18834846e`)
.then(res => {
if (res.data.features.length > 0) {
dispatch(makePostcodeQuery(res.data.features[0].properties))
dispatch(setInputLocation(res.data.features[0].properties))
} else {
console.log('no results found for input')
dispatch(setNotFoundError())
}
})
.catch(err => console.error(err))
Expand Down
Binary file added src/assets/pointing-down.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions src/assets/pointing-down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/you-are-here-marker.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions src/components/locations/Brewery.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { useEffect, useState } from "react";
import { useSelector } from "react-redux";
import LocationMarker from "../map/LocationMarker"
import BreweryMarker from "./BreweryMarker"

const Brewery = ({brewery}) => {
const {lat, lng} = brewery.locationProperties;
const [isClosest, setIsClosest] = useState(false);
const breweryStore = useSelector(state => state.brewery);

useEffect(() => {
if(breweryStore.closest && breweryStore.closest.name == brewery.name) {
if(breweryStore.searchResult && breweryStore.searchResult.name == brewery.name) {
setIsClosest(true);
}
}, [breweryStore, brewery]);



return(<>
{brewery && brewery.locationProperties && <LocationMarker markerPosition={{lat, lng}} brewery={brewery} closest={isClosest}/>}
{brewery && brewery.locationProperties && <BreweryMarker markerPosition={{lat, lng}} brewery={brewery} closest={isClosest}/>}
</>
)
}
Expand Down
46 changes: 46 additions & 0 deletions src/components/locations/BreweryMarker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { useMapEvents } from 'react-leaflet';
import { Marker, Popup } from 'react-leaflet';
import L from 'leaflet';

L.Icon.Default.imagePath='img/'

function BreweryMarker({ markerPosition, brewery, closest }) {
const markerRef = useRef(null);
const [position, setPosition] = useState(null);

const map = useMapEvents({
click() {
map.locate()
},
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})

function openPopup(closest) {
if(closest) {
markerRef.current.openPopup();
}
}

useCallback(
openPopup(closest)
, [closest]);

useEffect(() => {
//watch position change of marker
setPosition([markerPosition.lat, markerPosition.lng])
}, [markerPosition])

return position === null ? null : (<>
<Marker ref={markerRef} position={position} popupOpen={closest}>
<Popup>
{brewery.name}
</Popup>
</Marker>
</>)
}

export default BreweryMarker;
50 changes: 50 additions & 0 deletions src/components/locations/LocationMarker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useEffect, useRef, useState } from 'react';
import { useMapEvents } from 'react-leaflet';
import { Marker, Popup } from 'react-leaflet';
import L from 'leaflet';

import pointingDown from '../../assets/you-are-here-marker.svg';

L.Icon.Default.imagePath='img/'

const pointingDownIcon = new L.Icon({
iconUrl: pointingDown,
iconRetinaUrl: pointingDown,
iconSize: [32, 40],
iconAnchor: [16, 40],
popupAnchor: [1,-15],
shadowUrl: null,
shadowSize: null,
shadowAnchor: null,
className: 'leaflet-div-icon'
});

function LocationMarker({ markerPosition }) {
const markerRef = useRef(null);
const [position, setPosition] = useState(null);

const map = useMapEvents({
click() {
map.locate()
},
locationfound(e) {
setPosition(e.latlng)
map.flyTo(e.latlng, map.getZoom())
},
})

useEffect(() => {
//watch position change of marker
setPosition([markerPosition.lat, markerPosition.lng])
}, [markerPosition])

return position === null ? null : (
<Marker ref={markerRef} position={position} icon={pointingDownIcon}>
<Popup>
You are here!
</Popup>
</Marker>
)
}

export default LocationMarker;
44 changes: 0 additions & 44 deletions src/components/map/LocationMarker.js

This file was deleted.

34 changes: 20 additions & 14 deletions src/components/map/MapView.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
import React, { useEffect, useState } from 'react';
import { LayerGroup, LayersControl, MapContainer, TileLayer, useMap, useMapEvent } from 'react-leaflet'
import { LayerGroup, LayersControl, MapContainer, TileLayer } from 'react-leaflet'
import { useDispatch, useSelector } from 'react-redux';

import ViewControl from './ViewControl';
import SearchBar from '../search/SearchBar';
import Brewery from '../locations/Brewery';
import LocationMarker from './LocationMarker';
import LocationMarker from '../locations/LocationMarker';

import {setBreweries} from '../../actions/brewery';
// import SearchResultModal from '../search/SearchResults';

const MapView = ({breweries}) => {
const [currentLocation, setCurrentLocation] = useState({lat: 52.3389066, lng: 4.9415677});
const [zoom, setZoom] = useState(16);
const [currentLocation, setCurrentLocation] = useState({lat: 52.3727598, lng: 4.8936041});
const [zoom, setZoom] = useState(14);
const [showSearchResults, setShowSearchResults] = useState(false);
const dispatch = useDispatch();
const breweryStore = useSelector(state => state.brewery);

// const onShowModal = () => {
// setShowSearchResults(!showSearchResults)
// setCurrentLocation({lat: 52.3666601, lng: 4.9263454});
// }

const outerBounds = [
[50.505, -29.09],
[52.505, 29.09],
]

useEffect(() => {
dispatch(setBreweries(breweries))
}, [dispatch, breweries]);

useEffect(() => {
if(breweryStore.closest) {
if(breweryStore.searchResult) {
setShowSearchResults(true);
}
}, [breweryStore]);

return (<>
{currentLocation && currentLocation.lat &&
<MapContainer
bounds={outerBounds}
center={currentLocation}
zoom={zoom}
scrollWheelZoom={true}>
{showSearchResults ? <ViewControl center={{lat: breweryStore.closest.locationProperties.lat, lng: breweryStore.closest.locationProperties.lng }} zoom={zoom}/> : <ViewControl center={currentLocation} zoom={zoom}/> }
{showSearchResults ?
<ViewControl center={{lat: breweryStore.searchResult.locationProperties.lat, lng: breweryStore.searchResult.locationProperties.lng }} zoom={zoom} outerBounds={outerBounds}/> :
<ViewControl center={currentLocation} zoom={zoom} outerBounds={outerBounds}/> }
<LayersControl position="topright">
<LayersControl.BaseLayer checked name="OpenStreetMap.Mapnik">
<TileLayer
Expand All @@ -56,15 +58,19 @@ const MapView = ({breweries}) => {
<LayerGroup>
<SearchBar/>
</LayerGroup>
{/* <SearchResultModal showModal={showSearchResults} onShowModal={onShowModal} result={breweryStore.closest}/> */}
{/* <SearchResultModal showModal={showSearchResults} onShowModal={onShowModal} result={breweryStore.searchResult}/> */}
</LayersControl.Overlay>
<LayersControl.Overlay checked name="Breweries">
<LayerGroup>
{breweries && breweries.map(brewery => <Brewery key={breweries.indexOf(brewery)} brewery={brewery}/>)}
</LayerGroup>
</LayersControl.Overlay>
<LayersControl.Overlay checked name="Input Location">
<LayerGroup>
{breweryStore && breweryStore.searchLocation && <LocationMarker markerPosition={{lat: breweryStore.searchLocation.lat, lng: breweryStore.searchLocation.lon}}/>}
</LayerGroup>
</LayersControl.Overlay>
</LayersControl>
{currentLocation && currentLocation.lat && <LocationMarker markerPosition={currentLocation}/>}
</MapContainer>}
</>
);
Expand Down
Loading