From 47932534ec1947524bcb0a100a41ea43550addf1 Mon Sep 17 00:00:00 2001 From: Heather Houde <114454164+hhoude36@users.noreply.github.com> Date: Tue, 23 May 2023 20:17:32 -0400 Subject: [PATCH] =?UTF-8?q?closest=20tap=20function=20added=20on=20mobile?= =?UTF-8?q?=20and=20desktop=20version=20(=20no=20button=20=E2=80=A6=20(#31?= =?UTF-8?q?5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * closest tap function added on mobile and desktop version ( no button on desktop). The water resources work fine, but the rest of the resources will show the closest food org because the component does not have access to the foraging/bathroom data. * Switches setClosest behavior to use switch statement and adds defaults for foraging and bathroom state data --------- Co-authored-by: Gabriel Cardona <2278918+gcardonag@users.noreply.github.com> --- src/actions/actions.js | 2 +- src/components/ClosestTap/ClosestTap.js | 2 +- src/components/Foot/Foot.js | 2 +- src/components/SelectedTap/SelectedTap.js | 55 ++++++------ src/components/Toolbar/Toolbar.js | 103 +++++++++++++++------- src/reducers/filterMarkers.js | 6 ++ 6 files changed, 110 insertions(+), 60 deletions(-) diff --git a/src/actions/actions.js b/src/actions/actions.js index 8f089cb4..622e476c 100644 --- a/src/actions/actions.js +++ b/src/actions/actions.js @@ -106,7 +106,7 @@ export const getBathroomTaps = () => dispatch => { return onValue(ref(database, '/'), snapshot => { const snapshotVal = snapshot.val(); - dispatch(getForagingSuccess(snapshotVal)); + dispatch(getBathroomSuccess(snapshotVal)); }); }; diff --git a/src/components/ClosestTap/ClosestTap.js b/src/components/ClosestTap/ClosestTap.js index 22e7f6cd..e272244c 100644 --- a/src/components/ClosestTap/ClosestTap.js +++ b/src/components/ClosestTap/ClosestTap.js @@ -47,8 +47,8 @@ function getClosest(data, v) { closestTap.address = distances[i].address; } } - return closestTap; + } function getCoordinates() { diff --git a/src/components/Foot/Foot.js b/src/components/Foot/Foot.js index 6cf11239..709ebe76 100644 --- a/src/components/Foot/Foot.js +++ b/src/components/Foot/Foot.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; - +import ClosestTap from '../ClosestTap/ClosestTap'; export class Foot extends Component { render() { return ( diff --git a/src/components/SelectedTap/SelectedTap.js b/src/components/SelectedTap/SelectedTap.js index 651c25da..f669b9cf 100644 --- a/src/components/SelectedTap/SelectedTap.js +++ b/src/components/SelectedTap/SelectedTap.js @@ -59,10 +59,11 @@ class SelectedTap extends React.Component { }; getWalkingDurationAndTimes = () => { + if (!this.props.selectedPlace) return; const orsAPIKey = '5b3ce3597851110001cf6248ac903cdbe0364ca9850aa85cb64d8dfc'; fetch(`https://api.openrouteservice.org/v2/directions/foot-walking?api_key=${orsAPIKey}&start=${this.props.userLocation.lng}, - ${this.props.userLocation.lat}&end=${this.props.selectedPlace.lon},${this.props.selectedPlace.lat}`) + ${this.props.userLocation?.lat}&end=${this.props.selectedPlace?.lon},${this.props.selectedPlace?.lat}`) .then(response => response.json()) .then(data => { // duration is returned in seconds @@ -165,7 +166,7 @@ class SelectedTap extends React.Component { ReactGA.event({ category: `Tap - ${this.props.phlaskType}`, action: 'InfoShown', - label: `${this.props.selectedPlace.organization}, ${this.props.selectedPlace.address}` + label: `${this.props.selectedPlace?.organization}, ${this.props.selectedPlace?.address}` }); } @@ -175,13 +176,13 @@ class SelectedTap extends React.Component { const selectedPlace = this.props.selectedPlace; this.setState({ - organization: selectedPlace.organization, - address: selectedPlace.address, - tapDescription: selectedPlace.description - ? selectedPlace.description + organization: selectedPlace?.organization, + address: selectedPlace?.address, + tapDescription: selectedPlace?.description + ? selectedPlace?.description : 'Happy PHLasking', - tapStatement: selectedPlace.statement, - tapNormsAndRules: selectedPlace.norms_rules + tapStatement: selectedPlace?.statement, + tapNormsAndRules: selectedPlace?.norms_rules }); } @@ -213,24 +214,26 @@ class SelectedTap extends React.Component {
{isMobile && (
- this.toggleInfoWindow(true)} - onClose={() => this.toggleInfoWindow(false)} - PaperProps={{ square: false }} - > - this.toggleInfoWindow(true)} + onClose={() => this.toggleInfoWindow(false)} + PaperProps={{ square: false }} > - - - + > + + + + )}
)} {!isMobile && ( @@ -287,11 +290,11 @@ class SelectedTap extends React.Component { {this.props.phlaskType === PHLASK_TYPE_WATER ? ( ) : ( - this.props.selectedPlace.infoIcon + this.props.selectedPlace?.infoIcon )}
diff --git a/src/components/Toolbar/Toolbar.js b/src/components/Toolbar/Toolbar.js index 876002b3..5d419051 100644 --- a/src/components/Toolbar/Toolbar.js +++ b/src/components/Toolbar/Toolbar.js @@ -7,6 +7,7 @@ import { PHLASK_TYPE_FORAGING, PHLASK_TYPE_BATHROOM, setMapCenter, + setUserLocation, setSelectedPlace, toggleInfoWindow, togglePhlaskType, @@ -16,6 +17,7 @@ import FoodFilter from '../FoodFilter/FoodFilter'; import phlaskImg from '../images/PHLASK Button.png'; import Filter from '../ResourceMenu/Filter'; import styles from './Toolbar.module.scss'; +import ClosestTap from '../ClosestTap/ClosestTap'; import { isMobile } from 'react-device-detect'; import AddResourceModalV2 from '../AddResourceModal/AddResourceModalV2'; @@ -56,24 +58,29 @@ function distance(lat1, lon1, lat2, lon2) { // Takes an array of objects with lat and lon properties as well as a single object with lat and lon // properties and finds the closest point (by shortest distance). -function getClosest(data, userLocation) { - var distances = data.map((org, index) => { - return { - lat: org['lat'], - lon: org['lon'], - organization: org['organization'], - address: org['address'], - distance: distance( - userLocation['lat'], - userLocation['lon'], - org['lat'], - org['lon'] - ), - id: index - }; - }); - var minDistance = Math.min(...distances.map(d => d.distance)); +//looping through data to get list of locations + function getClosest(data, userLocation) { + var distances = data.map((org, index) => { + //i added this terniary + if(org?.lat && org?.lon){ + return { + lat: org['lat'], + lon: org['lon'], + organization: org['organization'], + address: org['address'], + distance: distance( + userLocation['lat'], + userLocation['lon'], + org['lat'], + org['lon'] + ), + id: index + }; + } + }).filter(Boolean) + + var minDistance = Math.min(...distances.map(d => d.distance)); var closestTap = { organization: '', address: '', @@ -91,21 +98,26 @@ function getClosest(data, userLocation) { closestTap.id = distances[i].id; } } - return closestTap; + } + + function getCoordinates() { return new Promise(function (resolve, reject) { navigator.geolocation.getCurrentPosition(resolve, reject); }); } + function Toolbar(props) { const [value, setValue] = React.useState(0); const [openResourceModal, setOpenResourceModal] = React.useState(false); const phlaskType = useSelector(phlaskTypeSelector); - + const dispatch = useDispatch(); + const property_name = useSelector(state => state) + const selectedResourceIcon = { [PHLASK_TYPE_WATER]: WaterIcon, [PHLASK_TYPE_FOOD]: FoodIcon, @@ -129,18 +141,38 @@ function Toolbar(props) { }); } - function setClosest() { - const data = - props.phlaskType === PHLASK_TYPE_WATER - ? props.allTaps - : props.allFoodOrgs; + async function setClosest() { + // If the user clicks very fast, it crashes. + // NOTE: This was left as an acceptable scenario for now, + // as it is difficult for a user to do this reliably due to the popup of the location panel. + // This may be reproducible on Desktop. + let data; + switch (props.phlaskType){ + case (PHLASK_TYPE_WATER): + data = props?.allTaps; + break; + case (PHLASK_TYPE_FOOD): + data = props?.allFoodOrgs + break; + case (PHLASK_TYPE_FORAGING): + data = props?.allForagingTaps; + break; + case (PHLASK_TYPE_BATHROOM): + data = props?.allBathroomTaps; + break; + default: + data = props?.allTaps + } + const closest = getClosest(data, { lat: props.userLocation.lat, lon: props.userLocation.lng }); + const place = new Promise(() => { props.setSelectedPlace(closest.id); }); + place .then( props.setMapCenter({ @@ -151,6 +183,10 @@ function Toolbar(props) { .then(props.toggleInfoWindow(true)); } + function closestButtonClicked(){ + setClosest(); + } + return ( <> $ @@ -162,14 +198,15 @@ function Toolbar(props) { > {!isMobile && (

{props.phlaskType === PHLASK_TYPE_WATER ? 'Water Map' @@ -255,6 +292,7 @@ function Toolbar(props) { component={selectedResourceIcon} sx={{ fontSize: 90 }} inheritViewBox={true} + onClick={closestButtonClicked} /> } /> @@ -277,6 +315,8 @@ const mapStateToProps = state => ({ phlaskType: state.phlaskType, allTaps: state.allTaps, allFoodOrgs: state.allFoodOrgs, + allBathroomTaps: state.allBathroomTaps, + allForagingTaps: state.allForagingTaps, userLocation: state.userLocation, isResourceMenuShown: state.isResourceMenuShown }); @@ -288,6 +328,7 @@ const mapDispatchToProps = { setSelectedPlace, toggleInfoWindow, setMapCenter, + setUserLocation, toggleResourceMenu }; diff --git a/src/reducers/filterMarkers.js b/src/reducers/filterMarkers.js index 4fca6f0a..aec2d6b9 100644 --- a/src/reducers/filterMarkers.js +++ b/src/reducers/filterMarkers.js @@ -32,6 +32,8 @@ const initialState = { }, allTaps: [], allFoodOrgs: [], + allBathroomTaps: [], + allForagingTaps: [], selectedPlace: {}, phlaskType: actions.PHLASK_TYPE_WATER }; @@ -97,6 +99,10 @@ export default (state = initialState, act) => { allFoodOrgs: act.allFoodOrgs, filteredOrgs: act.allFoodOrgs }; + + case actions.GET_BATHROOM_SUCCESS: + return { ...state, allBathroomTaps: act.allBathroomTaps }; + case actions.SET_FILTER_FUNCTION: // console.log('set filter func');