diff --git a/front/src/common/hook/useGeolocation.ts b/front/src/common/hook/useGeolocation.ts new file mode 100644 index 0000000..8b93649 --- /dev/null +++ b/front/src/common/hook/useGeolocation.ts @@ -0,0 +1,79 @@ +"use client"; +import { useState, useCallback, useEffect } from "react"; + +export interface UserLocation { + latitude: number; + longitude: number; +} + +export type GeolocationStatus = + | "granted" + | "denied"; + +export interface UseGeolocationReturn { + location: UserLocation | null; + status: GeolocationStatus; + requestLocation: () => void; + clearLocation: () => void; +} + +export function useGeolocation(): UseGeolocationReturn { + const [location, setLocation] = useState(null); + const [status, setStatus] = useState("denied"); + + //esto es para el check de permisos cuando se cambia desde el navegador + + useEffect(() => { + if (!navigator.permissions) return; + + navigator.permissions.query({ name: "geolocation" }).then((result) => { + setStatus(result.state === "granted" ? "granted" : "denied"); + + result.addEventListener("change", () => { + setStatus(result.state === "granted" ? "granted" : "denied"); + if (result.state === "denied") { + setLocation(null); + } + }); + }); + }, []); + + const requestLocation = useCallback(() => { + if (!navigator.geolocation) { + setStatus("denied"); + return; + } + + navigator.geolocation.getCurrentPosition( + (position) => { + setLocation({ + latitude: position.coords.latitude, + longitude: position.coords.longitude, + }); + setStatus("granted"); + }, + (error) => { + if (error.code === error.PERMISSION_DENIED) { + setStatus("denied"); + } + }, + { + enableHighAccuracy: true, + timeout: 10000, + maximumAge: 0, + } + ); + }, []); + + const clearLocation = useCallback(() => { + setLocation(null); + setStatus("denied"); + }, []); + + return { + location, + status, + requestLocation, + clearLocation, + }; +} diff --git a/front/src/pods/embalse-search/embalse-search.tsx b/front/src/pods/embalse-search/embalse-search.tsx index aeaffe8..695adb4 100644 --- a/front/src/pods/embalse-search/embalse-search.tsx +++ b/front/src/pods/embalse-search/embalse-search.tsx @@ -9,6 +9,11 @@ import { EmbalseSearchModel } from "./embalse-search.vm"; import { getFilteredEmbalses as getFilteredEmbalsesBusiness } from "./embalse-search.business"; import { FilteredList } from "./components/filtered-list"; import { Input } from "./components/input"; +import { useGeolocation } from "@/common/hook/useGeolocation"; + + + + interface Props { embalses: Embalse[]; @@ -22,10 +27,20 @@ export const EmbalseSearch: React.FC = (props) => { >([]); const [isNavigating, setIsNavigating] = useState(false); const [inputValue, setInputValue] = useState(""); + const { location, status, requestLocation, clearLocation } = useGeolocation(); - const getFilteredEmbalses = (inputValue: string): EmbalseSearchModel[] => { - return getFilteredEmbalsesBusiness(inputValue, embalses); + const handleLocationClick = () => { + if (location) { + clearLocation(); + } else { + requestLocation(); + } }; + + + function getFilteredEmbalses(inputValue: string): EmbalseSearchModel[] { + return getFilteredEmbalsesBusiness(inputValue, embalses); + } const { isOpen, getMenuProps, @@ -83,10 +98,20 @@ export const EmbalseSearch: React.FC = (props) => { Encuentra toda la información disponible de los embalses de España

+ + {location && ( +

📍 {location.latitude.toFixed(4)}, {location.longitude.toFixed(4)}

+ )} + ); };