// Mapbox Geocoding Service // Docs: https://docs.mapbox.com/api/search/geocoding/ export interface MapboxFeature { id: string; place_name: string; center: [number, number]; // [longitude, latitude] geometry: { coordinates: [number, number]; }; context?: Array<{ id: string; text: string; short_code?: string; }>; place_type: string[]; text: string; address?: string; properties?: any; } export interface MapboxResult { placeName?: string; description: string; street: string; number: string; city: string; state: string; zip: string; lat: number; lng: number; mapLink: string; } // Token do Mapbox configurado no arquivo .env.local const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_TOKEN || ""; /** * Busca endereços usando a API de Geocoding do Mapbox * @param query - Texto de busca (endereço, local, etc) * @param country - Código do país (ex: 'br' para Brasil) */ export async function searchMapboxLocation( query: string, country: string = "br" ): Promise { if (!MAPBOX_TOKEN || MAPBOX_TOKEN.startsWith("YOUR_")) { console.warn( "⚠️ Mapbox Token não configurado. Configure em services/mapboxService.ts" ); return []; } try { const encodedQuery = encodeURIComponent(query); let url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodedQuery}.json?` + `access_token=${MAPBOX_TOKEN}&` + `country=${country}&` + `language=pt&` + `types=poi,address&` + `limit=10`; // Removed proximity bias to prevent Mapbox from hiding national POIs (like Estádio Pacaembu) // when the user's region is set far away from the POI. console.log("🔍 Buscando endereço:", query); const response = await fetch(url); if (!response.ok) { console.error("❌ Erro na API Mapbox:", response.statusText); throw new Error(`Mapbox API error: ${response.statusText}`); } const data = await response.json(); console.log("✅ Resultados encontrados:", data.features?.length || 0); if (!data.features || data.features.length === 0) { return []; } return data.features.map((feature: MapboxFeature) => { // Extrair informações do contexto const context = feature.context || []; const place = context.find((c) => c.id.startsWith("place")); const region = context.find((c) => c.id.startsWith("region")); const postcode = context.find((c) => c.id.startsWith("postcode")); // Extrair número do endereço const addressMatch = feature.address || feature.text.match(/\d+/)?.[0] || ""; let placeName = undefined; let street = feature.text; if (feature.place_type.includes("poi")) { placeName = feature.text; street = feature.properties?.address || feature.place_name.split(",")[0]; } return { placeName, description: feature.place_name, street, number: addressMatch, city: place?.text || "", state: region?.short_code?.replace("BR-", "") || region?.text || "", zip: postcode?.text || "", lat: feature.center[1], lng: feature.center[0], mapLink: `https://www.google.com/maps/search/?api=1&query=${feature.center[1]},${feature.center[0]}`, }; }); } catch (error) { console.error("Erro ao buscar localização no Mapbox:", error); return []; } } /** * Busca reversa: converte coordenadas em endereço * Retorna o endereço completo baseado nas coordenadas do pin */ export async function reverseGeocode( lat: number, lng: number ): Promise { if (!MAPBOX_TOKEN || MAPBOX_TOKEN.startsWith("YOUR_")) { console.warn("⚠️ Mapbox Token não configurado"); return null; } try { const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${lng},${lat}.json?` + `access_token=${MAPBOX_TOKEN}&` + `language=pt&` + `types=address,place`; const response = await fetch(url); const data = await response.json(); if (data.features && data.features.length > 0) { const feature = data.features[0]; const context = feature.context || []; const place = context.find((c: any) => c.id.startsWith("place")); const region = context.find((c: any) => c.id.startsWith("region")); const postcode = context.find((c: any) => c.id.startsWith("postcode")); // Extrair número se houver const addressMatch = feature.address || ""; return { description: feature.place_name, street: feature.text, number: addressMatch.toString(), city: place?.text || "", state: region?.short_code?.replace("BR-", "") || region?.text || "", zip: postcode?.text || "", lat, lng, mapLink: `https://www.google.com/maps/search/?api=1&query=${lat},${lng}`, }; } return null; } catch (error) { console.error("Erro no reverse geocode:", error); return null; } }