vue-componentes/src/componentes/EliEntrada/utils/coordenadas.ts
2026-06-06 15:05:40 -03:00

63 lines
2.2 KiB
TypeScript

import type { zCoordenadas } from "p-comuns"
import type z from "zod"
export type TipoCoordenadas = z.infer<typeof zCoordenadas>
/** Centro padrão do Brasil (Brasília) */
export const COORDENADAS_PADRAO: TipoCoordenadas = {
formato: "decimal",
datum: "EPSG:4326",
latitude: -15.7801,
longitude: -47.9292,
}
/** Zoom padrão do mapa */
export const ZOOM_PADRAO = 4
/** Altura padrão do mapa em pixels */
export const ALTURA_MAPA_PADRAO = 300
/** Limites válidos para latitude (-90 a 90) e longitude (-180 a 180) */
export function coordenadaValida(lat: number, lng: number): boolean {
return lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180
}
/** Formata número de coordenada para exibição com vírgula (padrão BR) */
export function formatarCoordenada(valor: number): string {
return valor.toFixed(6).replace(".", ",")
}
/** Converte texto digitado (aceita vírgula ou ponto) em número. Retorna null se inválido. */
export function parseCoordenada(v: string | number): number | null {
if (typeof v === "number") return Number.isNaN(v) ? null : v
const normalizado = v.replace(",", ".")
const n = Number.parseFloat(normalizado)
return Number.isNaN(n) ? null : n
}
/** Tenta geolocalização do navegador; se falhar, usa GeoIP como fallback */
export async function obterLocalizacao(): Promise<{ latitude: number; longitude: number }> {
try {
return await obterViaBrowser()
} catch {
return await obterViaGeoIp()
}
}
function obterViaBrowser(): Promise<{ latitude: number; longitude: number }> {
return new Promise((resolve, reject) => {
if (!navigator.geolocation) return reject(new Error("Geolocation indisponível"))
navigator.geolocation.getCurrentPosition(
(pos) => resolve({ latitude: pos.coords.latitude, longitude: pos.coords.longitude }),
(err) => reject(err),
{ enableHighAccuracy: true, timeout: 10000 },
)
})
}
async function obterViaGeoIp(): Promise<{ latitude: number; longitude: number }> {
const resp = await fetch("https://ipapi.co/json/")
if (!resp.ok) throw new Error(`GeoIP falhou: ${resp.status}`)
const dados: { latitude: number; longitude: number } = await resp.json()
return { latitude: dados.latitude, longitude: dados.longitude }
}