Last active
April 11, 2024 08:35
-
-
Save quentin-decre/ed6ed417637edf7c4e4570b3f6954321 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Extend a dataProvider to add a Google Maps API Geocoding Places resource. | |
* Then you will be able to add location autocomplete using ReferenceInput and AutocompleteInput | |
* @example | |
* | |
* const dataProvider = withGoogleMapsPlacesResource( | |
* jsonServerProvider("http://localhost:3000"), | |
* [....] | |
* ); | |
* | |
* <ReferenceInput | |
* reference="google_maps_places" | |
* source={source} | |
* enableGetChoices={({ q }) => q && q.length >= 2} // minimum 2 characters to trigger search | |
* > | |
* <AutocompleteInput optionText="formatted_address" {...props} /> | |
* </ReferenceInput> | |
*/ | |
import { Client, GeocodeResult } from '@googlemaps/google-maps-services-js' | |
import { DataProvider, GetListParams } from 'react-admin' | |
const client = new Client({ | |
config: { | |
adapter: ['xhr', 'http'], | |
}, | |
}) | |
export const searchGoogleMapsPlaces = async (search: string): Promise<GeocodeResult[]> => { | |
const response = await client.geocode({ | |
params: { | |
address: search.trim(), | |
key: import.meta.env.REACT_APP_GOOGLE_MAPS_PWA_APIKEY ?? '', | |
}, | |
}) | |
return (response.data?.results ?? []).map((place) => ({ | |
id: place.formatted_address, | |
...place, | |
})) | |
} | |
export const withGoogleMapsPlacesResource = (dataProvider: DataProvider) => ({ | |
...dataProvider, | |
getList: async (resource: string, params: GetListParams) => { | |
if (resource === 'google_maps_places') { | |
// search parameter is mandatory | |
if (!params.filter?.q) { | |
return { | |
data: [], | |
total: 0, | |
} | |
} | |
const response = await searchGoogleMapsPlaces(params.filter.q) | |
return { | |
data: response, | |
total: response.length, | |
} | |
} | |
return dataProvider.getList(resource, params) | |
}, | |
getOne: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
const response = await searchGoogleMapsPlaces(params.id) | |
return { | |
data: response[0], | |
} | |
} | |
return dataProvider.getOne(resource, params) | |
}, | |
getMany: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
const response = await Promise.all(params.ids.map((id: string) => searchGoogleMapsPlaces(id))) | |
return { | |
data: response?.flat() ?? [], | |
} | |
} | |
return dataProvider.getMany(resource, params) | |
}, | |
update: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
throw new Error('google_maps_places resource is read-only') | |
} | |
return dataProvider.update(resource, params) | |
}, | |
updateMany: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
throw new Error('google_maps_places resource is read-only') | |
} | |
return dataProvider.updateMany(resource, params) | |
}, | |
create: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
throw new Error('google_maps_places resource is read-only') | |
} | |
return dataProvider.create(resource, params) | |
}, | |
delete: async (resource: string, params: any) => { | |
if (resource === 'google_maps_places') { | |
throw new Error('google_maps_places resource is read-only') | |
} | |
return dataProvider.delete(resource, params) | |
}, | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment