// @flow import { type GooglePlaceObj } from "../records/PlaceRecord"; import { GoogleAPIKey } from "../constants/AppConstants"; import { memoizeWith, identity } from "ramda"; const placesDetailUrl = `https://maps.googleapis.com/maps/api/place/details/json?key=${GoogleAPIKey}`; const photosUrl = `https://maps.googleapis.com/maps/api/place/photo?key=${GoogleAPIKey}`; const placesFromTextUrl = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?key=${GoogleAPIKey}`; type GooglePlaceDetailsResponse = { error_message: ?string, result: GooglePlaceObj }; type GoogleFindPlaceResponse = { status: string, results: Array, next_page_token?: string }; const milesToMeters = miles => Math.ceil(miles > 0 ? miles / 0.00062137 : 0); /** * always return a promise and swallow exceptions so as not to break the stream */ const safeWrapAjax = ajaxFn => memoizeWith(identity, (...args) => { return ajaxFn(...args).catch(error => { console.log("ERROR: ", error); //eslint-disable-line no-console return null; }); }); export const getPlaceDetails = safeWrapAjax( async ({ distance, placeId }: { distance: number, placeId: ?string }): Promise => { if (!placeId || typeof placeId !== "string") { throw new Error("placeid looks wrong"); } const res = await fetch(`${placesDetailUrl}&placeid=${placeId}`); const { error_message, result }: GooglePlaceDetailsResponse = await res.json(); if (error_message) { throw new Error(error_message); } return { ...result, distance }; } ); export const getURLForPhotoReference = (opts?: { maxheight?: number, maxwidth?: number } = {}) => ( photoReference: string ) => { if (!photoReference) { return ""; } const { maxheight, maxwidth } = opts; const maxHeight = `&maxheight=${maxheight || 600}`; const maxWidth = maxwidth ? `&maxwidth=${maxwidth}` : ""; const photoref = `&photoreference=${photoReference}`; return `${photosUrl}${photoref}${maxHeight}${maxWidth}`; }; // const getPageResults = async ({ pageToken }: { pageToken: string }) => { // const reqUrl = `${placesFromTextUrl}&pageToken=${pageToken}`; // return (await fetch(reqUrl)).toJson(); // }; export const findNearbyPlaces = safeWrapAjax( async ({ location, search, radius }: { location?: Position, search?: string, radius: number }): Promise => { if (!location) { return null; } const { coords: { latitude, longitude } } = location; const keyword = search ? `keyword=${encodeURIComponent(search)}` : ""; const loc = `location=${latitude},${longitude}`; const rad = `radius=${milesToMeters(radius)}`; const reqUrl = `${placesFromTextUrl}&${keyword}&${loc}&${rad}&type=restaurant`; let error; let places; try { const response: GoogleFindPlaceResponse = await (await fetch(reqUrl)).json(); // if (response.next_page_token) { // const page = await getPageResults({ pageToken: response.next_page_token }); // return concat(response.results, page.results); // } if (response.status !== "OK") { throw new Error("google find places request failed"); } places = response.results; } catch (err) { console.error(error); // eslint-disable-line no-console error = err; } return { error, location, places }; } );