photum/frontend/services/googleMapsService.ts
NANDO9322 7a06d4e691 feat(agenda): migração busca POI para Google Maps e correção do horário de término
Frontend:
- Migração da API de Geocoding do Mapbox para o Google Maps Places API (googleMapsService.ts) no formulário de eventos, garantindo a busca correta pelo nome de locais (estádios, teatros) e com autopreenchimento.
- Correção do fluxo de estado do 'horario_fim', propagando e persistindo o 'endTime' pelo DataContext, garantindo a população dos dados na edição do EventForm.
- Adição da visualização do horário final na listagem do Dashboard, no EventCard, painéis de EventDetails e atualização das props defaultEndTime no EventScheduler.

Backend:
- Atualização e migração dos arquivos gerados pelo sqlc (models.go, agenda.sql.go) para suportar operações no novo design do banco.
- Atualização síncrona dos artefatos Swagger de documentação de API (docs.go, swagger.json, swagger.yaml).
2026-02-27 18:48:07 -03:00

130 lines
4.7 KiB
TypeScript

import { MapboxResult } from "./mapboxService";
// Exporting MapboxResult from mapboxService to keep compatibility
// but using Google Maps to fetch the data.
const GOOGLE_MAPS_KEY = import.meta.env.VITE_GOOGLE_MAPS_KEY || "";
/**
* Busca endereços e locais usando a API de Geocoding do Google
*/
export async function searchGoogleLocation(query: string, country: string = "br"): Promise<MapboxResult[]> {
if (!GOOGLE_MAPS_KEY || GOOGLE_MAPS_KEY.includes("YOUR")) {
console.warn("⚠️ Google Maps Token não configurado em .env.local");
return [];
}
try {
const encodedQuery = encodeURIComponent(query);
const url = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodedQuery}&components=country:${country}&language=pt-BR&key=${GOOGLE_MAPS_KEY}`;
const response = await fetch(url);
const data = await response.json();
if (data.status !== "OK" || !data.results) {
if (data.status !== "ZERO_RESULTS") {
console.error("Google Maps API Error:", data.status, data.error_message);
}
return [];
}
return data.results.map((result: any) => {
// Find components
const getComponent = (type: string) => {
const comp = result.address_components.find((c: any) => c.types.includes(type));
return comp ? comp.long_name : "";
};
const getShortComponent = (type: string) => {
const comp = result.address_components.find((c: any) => c.types.includes(type));
return comp ? comp.short_name : "";
};
const street = getComponent("route");
const number = getComponent("street_number");
const city = getComponent("administrative_area_level_2") || getComponent("locality");
const state = getShortComponent("administrative_area_level_1");
const zip = getComponent("postal_code");
// Verify if it's a POI by checking the types of the location
const isPoi = result.types.includes("establishment") || result.types.includes("stadium") || result.types.includes("point_of_interest");
let placeName = undefined;
let finalStreet = street;
if (isPoi) {
// Obter o nome do estabelecimento do formatted_address (ex: "Allianz Parque, Av. Francisco Matarazzo...")
placeName = result.address_components.find((c: any) => c.types.includes("establishment") || c.types.includes("point_of_interest"))?.long_name;
if (!placeName && result.formatted_address) {
placeName = result.formatted_address.split(",")[0];
}
}
// Se a query não conseguiu resolver route/street, usa a formatação
if (!finalStreet) finalStreet = result.formatted_address;
return {
placeName,
description: placeName ? `${placeName} - ${result.formatted_address}` : result.formatted_address,
street: finalStreet,
number,
city,
state,
zip,
lat: result.geometry.location.lat,
lng: result.geometry.location.lng,
mapLink: `https://www.google.com/maps/search/?api=1&query=${result.geometry.location.lat},${result.geometry.location.lng}`,
};
});
} catch (error) {
console.error("Erro ao buscar no Google Maps:", error);
return [];
}
}
/**
* Busca reversa via Google Maps Geocoding
*/
export async function reverseGeocodeGoogle(lat: number, lng: number): Promise<MapboxResult | null> {
if (!GOOGLE_MAPS_KEY) return null;
try {
const url = `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&language=pt-BR&key=${GOOGLE_MAPS_KEY}`;
const response = await fetch(url);
const data = await response.json();
if (data.status === "OK" && data.results.length > 0) {
const result = data.results[0];
const getComponent = (type: string) => {
const comp = result.address_components.find((c: any) => c.types.includes(type));
return comp ? comp.long_name : "";
};
const getShortComponent = (type: string) => {
const comp = result.address_components.find((c: any) => c.types.includes(type));
return comp ? comp.short_name : "";
};
const street = getComponent("route") || result.formatted_address;
const number = getComponent("street_number");
const city = getComponent("administrative_area_level_2") || getComponent("locality");
const state = getShortComponent("administrative_area_level_1");
const zip = getComponent("postal_code");
return {
description: result.formatted_address,
street,
number,
city,
state,
zip,
lat,
lng,
mapLink: `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`,
};
}
return null;
} catch (error) {
console.error("Erro no reverse geocode do Google:", error);
return null;
}
}