import { useState, useEffect, useCallback } from 'react'; import { geolocationApi } from '../api/geolocation.api'; import type { Geolocation, GeolocationFilters, GeolocationsResponse, CreateGeolocationDto, UpdateGeolocationDto, GeolocationQuery, } from '../../shared/types/api.types'; // Hook para obtener lista de geolocalizaciones con filtros export function useGeolocations(filters?: GeolocationFilters) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const fetch = useCallback(async () => { setIsLoading(true); setError(null); try { const response = await geolocationApi.getAll(filters); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener geolocalizaciones'); } finally { setIsLoading(false); } }, [ filters?.search, filters?.page, filters?.limit, filters?.sortBy, filters?.sortOrder, filters?.countryId, filters?.regionId, filters?.cityId, filters?.postalCode, ]); useEffect(() => { fetch(); }, [fetch]); const create = useCallback(async (createData: CreateGeolocationDto): Promise => { const created = await geolocationApi.create(createData); await fetch(); return created; }, [fetch]); const update = useCallback(async (id: string, updateData: UpdateGeolocationDto): Promise => { const updated = await geolocationApi.update(id, updateData); await fetch(); return updated; }, [fetch]); const remove = useCallback(async (id: string): Promise => { await geolocationApi.delete(id); await fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch, create, update, remove }; } // Hook para obtener una geolocalización por ID export function useGeolocation(id: string) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const fetch = useCallback(async () => { if (!id) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.getById(id); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener geolocalización'); } finally { setIsLoading(false); } }, [id]); useEffect(() => { fetch(); }, [fetch]); const update = useCallback(async (updateData: UpdateGeolocationDto): Promise => { const updated = await geolocationApi.update(id, updateData); setData(updated); return updated; }, [id]); const remove = useCallback(async (): Promise => { await geolocationApi.delete(id); setData(null); }, [id]); return { data, isLoading, error, refresh: fetch, update, remove }; } // Hook para obtener países export function useCountries() { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const fetch = useCallback(async () => { setIsLoading(true); setError(null); try { const response = await geolocationApi.getCountries(); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener países'); } finally { setIsLoading(false); } }, []); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para obtener regiones de un país export function useRegions(countryId: string) { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const fetch = useCallback(async () => { if (!countryId) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.getRegions(countryId); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener regiones'); } finally { setIsLoading(false); } }, [countryId]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para obtener ciudades de una región export function useCities(regionId: string) { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const fetch = useCallback(async () => { if (!regionId) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.getCities(regionId); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener ciudades'); } finally { setIsLoading(false); } }, [regionId]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para geocodificación (dirección a coordenadas) export function useGeocode(query: GeolocationQuery) { const [data, setData] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const isEnabled = !!(query.address || query.postalCode || query.city || query.country); const fetch = useCallback(async () => { if (!isEnabled) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.geocode(query); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error en geocodificación'); } finally { setIsLoading(false); } }, [query.address, query.postalCode, query.city, query.country, query.limit, isEnabled]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para geocodificación inversa (coordenadas a dirección) export function useReverseGeocode(latitude: number, longitude: number) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const isEnabled = !!(latitude && longitude); const fetch = useCallback(async () => { if (!isEnabled) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.reverseGeocode(latitude, longitude); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error en geocodificación inversa'); } finally { setIsLoading(false); } }, [latitude, longitude, isEnabled]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para obtener zona horaria export function useTimezone(latitude: number, longitude: number) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const isEnabled = !!(latitude && longitude); const fetch = useCallback(async () => { if (!isEnabled) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.getTimezone(latitude, longitude); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al obtener zona horaria'); } finally { setIsLoading(false); } }, [latitude, longitude, isEnabled]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Hook para calcular distancia entre dos puntos export function useDistance( fromLat: number, fromLng: number, toLat: number, toLng: number, unit: 'km' | 'miles' = 'km' ) { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const isEnabled = !!(fromLat && fromLng && toLat && toLng); const fetch = useCallback(async () => { if (!isEnabled) return; setIsLoading(true); setError(null); try { const response = await geolocationApi.calculateDistance(fromLat, fromLng, toLat, toLng, unit); setData(response); } catch (err) { setError(err instanceof Error ? err.message : 'Error al calcular distancia'); } finally { setIsLoading(false); } }, [fromLat, fromLng, toLat, toLng, unit, isEnabled]); useEffect(() => { fetch(); }, [fetch]); return { data, isLoading, error, refresh: fetch }; } // Función para crear geolocalización (sin hook) export async function createGeolocation(data: CreateGeolocationDto): Promise { return geolocationApi.create(data); } // Función para actualizar geolocalización (sin hook) export async function updateGeolocation(id: string, data: UpdateGeolocationDto): Promise { return geolocationApi.update(id, data); } // Función para eliminar geolocalización (sin hook) export async function deleteGeolocation(id: string): Promise { return geolocationApi.delete(id); } // Función para validar código postal (sin hook) export async function validatePostalCode(postalCode: string, countryId?: string): Promise { return geolocationApi.validatePostalCode(postalCode, countryId); }