diff --git a/frontend/sportsmatch-app/src/hooks/UseLocation.tsx b/frontend/sportsmatch-app/src/hooks/UseLocation.tsx new file mode 100644 index 00000000..77ab03ff --- /dev/null +++ b/frontend/sportsmatch-app/src/hooks/UseLocation.tsx @@ -0,0 +1,93 @@ +import { useEffect, useState } from 'react' + +// source https://gist.github.com/KristofferEriksson/ee5af0a52e1fea0acc028e9b10aa0969 + +interface LocationOptions { + enableHighAccuracy?: boolean + timeout?: number + maximumAge?: number +} + +interface LocationState { + coords: { + latitude: number | null + longitude: number | null + accuracy: number | null + altitude: number | null + altitudeAccuracy: number | null + heading: number | null + speed: number | null + } + locatedAt: number | null + error: string | null +} + +const useLocation = (options: LocationOptions = {}) => { + const [location, setLocation] = useState({ + coords: { + latitude: null, + longitude: null, + accuracy: null, + altitude: null, + altitudeAccuracy: null, + heading: null, + speed: null, + }, + locatedAt: null, + error: null, + }) + + useEffect(() => { + // Ensuring this runs only in a client-side environment + if (typeof window === 'undefined' || !('geolocation' in navigator)) { + setLocation((prevState) => ({ + ...prevState, + error: + 'Geolocation is not supported by your browser or not available in the current' + + ' environment', + })) + return + } + + const handleSuccess = (position: GeolocationPosition) => { + setLocation({ + coords: { + latitude: position.coords.latitude, + longitude: position.coords.longitude, + accuracy: position.coords.accuracy, + altitude: position.coords.altitude, + altitudeAccuracy: position.coords.altitudeAccuracy, + heading: position.coords.heading, + speed: position.coords.speed, + }, + locatedAt: position.timestamp, + error: null, + }) + } + + const handleError = (error: GeolocationPositionError) => { + setLocation((prevState) => ({ + ...prevState, + error: error.message, + })) + } + + const geoOptions = { + enableHighAccuracy: options.enableHighAccuracy || false, + timeout: options.timeout || Infinity, + maximumAge: options.maximumAge || 0, + } + + const watcher = navigator.geolocation.watchPosition( + handleSuccess, + handleError, + geoOptions, + ) + + return () => navigator.geolocation.clearWatch(watcher) + }, [options.enableHighAccuracy, options.timeout, options.maximumAge]) + + return location +} + +export default useLocation diff --git a/frontend/sportsmatch-app/src/pages/Index.tsx b/frontend/sportsmatch-app/src/pages/Index.tsx index 6849cbd1..5adea504 100644 --- a/frontend/sportsmatch-app/src/pages/Index.tsx +++ b/frontend/sportsmatch-app/src/pages/Index.tsx @@ -9,6 +9,7 @@ import { ApiError, EventDTO, EventsControllerService } from '../generated/api' import useModal from '../hooks/UseModal' import Modal from '../components/Modal' import JoinEventComponent from '../components/JoinEventComponent' +import useLocation from '../hooks/UseLocation' export default function MainPage() { const [searchQuery, setSearchQuery] = useState('') @@ -21,6 +22,8 @@ export default function MainPage() { const [page, setPage] = useState(0) const size = 3 + const userCoords = useLocation().coords + // handle sports name selected from sportButtoncomponent const handleSportSelectionChange = (selectedButtonSports: string[]) => { setSelectedSports(selectedButtonSports) @@ -45,8 +48,8 @@ export default function MainPage() { try { const response = await EventsControllerService.getNearbyEvents( selectedSports, - 0, - 0, + userCoords.longitude || undefined, + userCoords.latitude || undefined, searchQuery, page, size, @@ -71,7 +74,13 @@ export default function MainPage() { } // call the method fetchData() - }, [selectedSports, page, searchQuery]) + }, [ + selectedSports, + page, + searchQuery, + userCoords.latitude, + userCoords.longitude, + ]) // handle join event pop up after cliking on the event const handleEventSelection = (e: EventDTO) => {