// 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; } export interface MapboxResult { 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); const url = `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodedQuery}.json?` + `access_token=${MAPBOX_TOKEN}&` + `country=${country}&` + `language=pt&` + `limit=5`; 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] || ''; return { description: feature.place_name, street: feature.text, 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; } }