useGeocodingApi.js 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import axios from 'axios';
  2. const GEOCODING_URL = 'https://maps.googleapis.com/maps/api/geocode/json';
  3. const parseAddressComponents = (components) => {
  4. const get = (type, nameType = 'long_name') =>
  5. components.find((c) => c.types.includes(type))?.[nameType] ?? '';
  6. return {
  7. address: `${get('route')}`.trim(),
  8. number: get('street_number'),
  9. district: get('sublocality_level_1') || get('sublocality') || get('neighborhood'),
  10. city: get('administrative_area_level_2'),
  11. state: get('administrative_area_level_1', 'short_name'),
  12. zip_code: get('postal_code').replace(/\D/g, ''),
  13. };
  14. };
  15. const geocodeViaGoogleMaps = async (request) => {
  16. const geocoder = new window.google.maps.Geocoder();
  17. const { results } = await geocoder.geocode(request);
  18. return results ?? [];
  19. };
  20. export const useGeocodingApi = () => {
  21. const geocodeCep = async (cep) => {
  22. const cleaned = cep.replace(/\D/g, '');
  23. const apiKey = process.env.GOOGLE_MAPS_API_KEY;
  24. const usandoGeocoderNativo = !!window.google?.maps?.Geocoder;
  25. if (usandoGeocoderNativo) {
  26. const results = await geocodeViaGoogleMaps({ address: `${cleaned}, Brazil` });
  27. if (!results.length) return null;
  28. const result = results[0];
  29. const parsed = parseAddressComponents(result.address_components);
  30. return {
  31. lat: result.geometry.location.lat(),
  32. lng: result.geometry.location.lng(),
  33. ...parsed,
  34. };
  35. }
  36. const { data } = await axios.get(GEOCODING_URL, {
  37. params: { address: `${cleaned}, Brazil`, key: apiKey },
  38. });
  39. if (data.status !== 'OK' || !data.results.length) return null;
  40. const result = data.results[0];
  41. const { lat, lng } = result.geometry.location;
  42. return { lat, lng, ...parseAddressComponents(result.address_components) };
  43. };
  44. const reverseGeocode = async (lat, lng) => {
  45. const apiKey = process.env.GOOGLE_MAPS_API_KEY;
  46. const usandoGeocoderNativo = !!window.google?.maps?.Geocoder;
  47. if (usandoGeocoderNativo) {
  48. const results = await geocodeViaGoogleMaps({ location: { lat, lng } });
  49. if (!results.length) return null;
  50. return { lat, lng, ...parseAddressComponents(results[0].address_components) };
  51. }
  52. const { data } = await axios.get(GEOCODING_URL, {
  53. params: { latlng: `${lat},${lng}`, key: apiKey },
  54. });
  55. if (data.status !== 'OK' || !data.results.length) return null;
  56. const result = data.results[0];
  57. return { lat, lng, ...parseAddressComponents(result.address_components) };
  58. };
  59. const geocodeFullAddress = async ({ address, number, district, zip_code, city, state }) => {
  60. const parts = [address, number, district, zip_code, city, state, 'Brazil'].filter(Boolean);
  61. const query = parts.join(', ');
  62. const apiKey = process.env.GOOGLE_MAPS_API_KEY;
  63. const usandoGeocoderNativo = !!window.google?.maps?.Geocoder;
  64. if (usandoGeocoderNativo) {
  65. const results = await geocodeViaGoogleMaps({ address: query });
  66. if (!results.length) return null;
  67. const result = results[0];
  68. return {
  69. lat: result.geometry.location.lat(),
  70. lng: result.geometry.location.lng(),
  71. ...parseAddressComponents(result.address_components),
  72. };
  73. }
  74. const { data } = await axios.get(GEOCODING_URL, {
  75. params: { address: query, key: apiKey },
  76. });
  77. if (data.status !== 'OK' || !data.results.length) return null;
  78. const result = data.results[0];
  79. const { lat, lng } = result.geometry.location;
  80. return { lat, lng, ...parseAddressComponents(result.address_components) };
  81. };
  82. return { geocodeCep, reverseGeocode, geocodeFullAddress };
  83. };