From 57fefd85e65154789517b634f8137df4740be9f9 Mon Sep 17 00:00:00 2001 From: miles-grant-ibigroup Date: Mon, 9 Dec 2024 13:00:19 -0500 Subject: [PATCH] feat(nearby view): add location field --- i18n/en-US.yml | 1 + lib/components/viewers/nearby/nearby-view.tsx | 52 ++++++++++++++++++- lib/components/viewers/viewers.css | 21 ++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/i18n/en-US.yml b/i18n/en-US.yml index 9bb360c76..efa1b74c8 100644 --- a/i18n/en-US.yml +++ b/i18n/en-US.yml @@ -379,6 +379,7 @@ components: headsign: "{destination}" nearbyListIntro: List of {count} nearby entities. nothingNearby: There are no places nearby. + searchNearby: Search nearby... spacesAvailable: "{spacesAvailable} empty spaces available" NewAccountWizard: createNewAccount: Create a new account diff --git a/lib/components/viewers/nearby/nearby-view.tsx b/lib/components/viewers/nearby/nearby-view.tsx index 1405f9eae..23294de6d 100644 --- a/lib/components/viewers/nearby/nearby-view.tsx +++ b/lib/components/viewers/nearby/nearby-view.tsx @@ -2,12 +2,17 @@ import { connect } from 'react-redux' import { FormattedMessage, useIntl } from 'react-intl' import { Location } from '@opentripplanner/types' import { MapRef, useMap } from 'react-map-gl' +import { Search } from '@styled-icons/fa-solid' +import getGeocoder from '@opentripplanner/geocoder' +import LocationField from '@opentripplanner/location-field' import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import * as apiActions from '../../../actions/api' +import * as locationActions from '../../../actions/location' import * as mapActions from '../../../actions/map' import * as uiActions from '../../../actions/ui' import { AppReduxState } from '../../../util/state-types' +import { GeocoderConfig } from '../../../util/config-types' import { getCurrentServiceWeek } from '../../../util/current-service-week' import { SetLocationHandler, ZoomToPlaceHandler } from '../../util/types' import Loading from '../../narrative/loading' @@ -45,6 +50,8 @@ type Props = { radius?: number, currentServiceWeek?: ServiceWeek ) => void + geocoderConfig: GeocoderConfig + getCurrentPosition: TODO hideBackButton?: boolean location: string mobile?: boolean @@ -114,6 +121,8 @@ function NearbyView({ displayedCoords, entityId, fetchNearby, + geocoderConfig, + getCurrentPosition, location, mobile, nearby, @@ -127,6 +136,7 @@ function NearbyView({ const map = useMap().default const intl = useIntl() const [loading, setLoading] = useState(true) + const [reversedPoint, setReversedPoint] = useState('') const firstItemRef = useRef(null) const finalNearbyCoords = useMemo( () => @@ -139,6 +149,12 @@ function NearbyView({ [nearbyViewCoords, currentPosition, map] ) + const reverseCoords = (coords) => { + getGeocoder(geocoderConfig) + .reverse({ point: coords }) + .then((result) => setReversedPoint(result.name)) + } + // Make sure the highlighted location is cleaned up when leaving nearby useEffect(() => { return function cleanup() { @@ -149,10 +165,12 @@ function NearbyView({ useEffect(() => { const moveListener = (e: mapboxgl.EventData) => { if (e.geolocateSource) { - setViewedNearbyCoords({ + const coords = { lat: e.viewState.latitude, lon: e.viewState.longitude - }) + } + setViewedNearbyCoords(coords) + reverseCoords(coords) } } @@ -162,9 +180,11 @@ function NearbyView({ lon: e.viewState.longitude } setViewedNearbyCoords(coords) + reverseCoords(coords) // Briefly flash the highlight to alert the user that we've moved setHighlightedLocation(coords) + setTimeout(() => { setHighlightedLocation(null) }, 500) @@ -286,6 +306,32 @@ function NearbyView({ > {/* This is used to scroll to top */}
+ ( + + )} + locationType="to" + onLocationSelected={(selection) => { + const { location } = selection + setViewedNearbyCoords(location) + map && zoomToPlace(map, location) + setReversedPoint(location.name || '') + }} + sortByDistance + /> {loading && ( @@ -327,6 +373,7 @@ const mapStateToProps = (state: AppReduxState) => { defaultLatLon, displayedCoords: nearby?.coords, entityId: entityId && decodeURIComponent(entityId), + geocoderConfig: config.geocoder, homeTimezone: config.homeTimezone, location: state.router.location.hash, nearby: nearby?.data, @@ -337,6 +384,7 @@ const mapStateToProps = (state: AppReduxState) => { const mapDispatchToProps = { fetchNearby: apiActions.fetchNearby, + getCurrentPosition: locationActions.getCurrentPosition, setHighlightedLocation: uiActions.setHighlightedLocation, setLocation: mapActions.setLocation, setMainPanelContent: uiActions.setMainPanelContent, diff --git a/lib/components/viewers/viewers.css b/lib/components/viewers/viewers.css index 1ea4637a9..c06fb1df2 100644 --- a/lib/components/viewers/viewers.css +++ b/lib/components/viewers/viewers.css @@ -249,3 +249,24 @@ justify-content: center; padding-top: 10px; } + +/* Nearby View Location Field Styles */ +.nearby-view-location-field { + background-color: rgba(255, 255, 255, 0.85); + transition: background-color 0.1s ease-out; + border-radius: 10px; + height: 50px; + color: #111; + display: flex !important; + border: none !important; + box-shadow: 0px 0px 5px 1px inset rgb(0 0 0 / 0.05); +} +.nearby-view-location-field:hover, +.nearby-view-location-field:active { + background-color: rgba(255, 255, 255, 0.95); + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); +} +.nearby-view-location-field input { + width: 100% !important; + background: transparent !important; +}