diff --git a/js/apis/GooglePlacesApi.js b/js/apis/GooglePlacesApi.js index 2f6977d..663ad6c 100644 --- a/js/apis/GooglePlacesApi.js +++ b/js/apis/GooglePlacesApi.js @@ -8,6 +8,7 @@ const photosUrl = `https://maps.googleapis.com/maps/api/place/photo?key=${Google const placesFromTextUrl = `https://maps.googleapis.com/maps/api/place/findplacefromtext/json?key=${GoogleAPIKey}`; type GooglePlaceDetailsResponse = { error_message: ?string, result: GooglePlaceObj }; +type GoogleFindPlaceResponse = { status: string, candidates: Array }; const milesToMeters = miles => Math.ceil(miles > 0 ? miles / 0.00062137 : 0); @@ -66,10 +67,10 @@ export const findNearbyPlaces = async ({ const input = `input=${encodeURIComponent(search || '*')}&inputtype=textquery`; const loc = `locationbias=circle:${milesToMeters(radius)}@${latitude},${longitude}`; - const fields = 'fields=id,name,geometry,photos,types'; + const fields = 'fields=id,name,geometry,photos,types,formatted_address,opening_hours'; const reqUrl = `${placesFromTextUrl}&${input}&${loc}&${fields}`; - const { candidates, status } = await (await fetch(reqUrl)).json(); + const { candidates, status }: GoogleFindPlaceResponse = await (await fetch(reqUrl)).json(); if (status !== 'OK') { throw new Error('google find places request failed'); diff --git a/js/streams/PlacesStream.js b/js/streams/PlacesStream.js index 4d3c789..e87089d 100644 --- a/js/streams/PlacesStream.js +++ b/js/streams/PlacesStream.js @@ -1,13 +1,17 @@ // @flow +import { ReplaySubject, Observable } from 'rxjs'; import { buildPlaceRecord } from '../records/PlaceRecord'; import { Map } from 'immutable'; -import { findNearbyPlaces } from '../apis/GooglePlacesApi'; +import { findNearbyPlaces, getPlaceDetails } from '../apis/GooglePlacesApi'; import { memoize } from 'ramda'; import { type GooglePlaceObj } from '../records/PlaceRecord'; import { setById } from '../helpers/ImmutableHelpers'; import location$ from './LocationStream'; import filter$ from './FilterStream'; import FilterRecord from '../records/FilterRecord'; +import foodItems$ from './FoodItemsStream'; +import PlaceRecord from '../records/PlaceRecord'; +import FoodItemRecord from '../records/FoodItemRecord'; /** * always return a promise and swallow exceptions so as not to break the stream @@ -22,7 +26,28 @@ const safeWrapAjax = ajaxFn => const safeFindNearbyPlaces = safeWrapAjax(findNearbyPlaces); -const Places$ = location$ +const safeGetPlaceDetails = safeWrapAjax(getPlaceDetails); + +const placesSubject = new ReplaySubject(); + +export function emitter(val?: ?PlaceRecord) { + placesSubject.next(val); +} + +emitter(null); + +foodItems$ + .mergeMap( + (foodItems: Map = Map()): Observable => { + return Observable.from(foodItems.toArray().map(foodItem => foodItem.placeId)); + } + ) + .distinct() + .mergeMap(safeGetPlaceDetails) + .map(buildPlaceRecord) + .subscribe(emitter); + +location$ .combineLatest(filter$) .mergeMap(([location, filter]: [?Position, FilterRecord]) => safeFindNearbyPlaces({ @@ -32,7 +57,8 @@ const Places$ = location$ }) ) .map((places: Array) => { - return (places || []).map(buildPlaceRecord).reduce(setById, new Map()); - }); + return (places || []).map(buildPlaceRecord); + }) + .subscribe(places => places.map(emitter)); -export default Places$; +export default placesSubject.distinct().scan(setById, new Map());