Skip to content

Commit

Permalink
add sightings location filter
Browse files Browse the repository at this point in the history
  • Loading branch information
erinz2020 committed Jan 24, 2025
1 parent ef3f372 commit 2f38998
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 6 deletions.
7 changes: 7 additions & 0 deletions frontend/src/components/Chip.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,13 @@ function Chip({ children }) {
}
}

if (query?.geo_distance) {
const { lat, lon, bearing, distance } = query.geo_distance;
entries.push(
`Location within ${distance} km of latitude: ${lat}, longitude: ${lon}`,
);
}

return entries.length > 0 ? `${entries.join(", ")}` : `No filters set`;
}

Expand Down
158 changes: 152 additions & 6 deletions frontend/src/components/filterFields/SightingsLocationFilter.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,158 @@
import React from "react";
import LocationFilterMap from "./LocationFilterMap";
import LocationFilterText from "./LocationFilterText";
import { FormattedMessage } from "react-intl";
import { useEffect, useRef, useState } from "react";
import { FormControl, FormGroup, FormLabel } from "react-bootstrap";
import { Loader } from "@googlemaps/js-api-loader";
import { useIntl } from "react-intl";

export default function SightingsLocationFilter({ onChange, data }) {

const intl = useIntl();
const mapCenterLat = data?.mapCenterLat || 51;
const mapCenterLon = data?.mapCenterLon || 7;
const mapZoom = data?.mapZoom || 4;
const mapKey = data?.googleMapsKey || "";
const mapRef = useRef(null);
const markerRef = useRef(null);
const [map, setMap] = useState(null);
const [pan, setPan] = useState(false);
const [location, setLocation] = useState({});

useEffect(() => {
const allFieldsFilled =
Object.values(location).length === 4 &&
Object.values(location).every(
(value) => value !== undefined && value !== "",
);
if (location && allFieldsFilled) {
onChange({
filterId: "sightingslocationMap",
clause: "term",
query: {
geo_distance: {
lat: location.lat,
lon: location.lng,
bearing: location.bearing,
distance: location.distance,
},
},
});
} else {
onChange(null, "sightingslocationMap");
}
}, [location]);

useEffect(() => {
if (!mapKey) {
return;
}
const loader = new Loader({
apiKey: mapKey,
});

loader
.load()
.then(() => {
const googleMap = new window.google.maps.Map(mapRef.current, {
center: { lat: mapCenterLat, lng: mapCenterLon },
zoom: mapZoom,
});

googleMap.addListener("click", (e) => {
setPan(false);
const lat = e.latLng.lat();
const lng = e.latLng.lng();
setLocation((prevLocation) => ({
...prevLocation,
lat: e.latLng.lat(),
lng: e.latLng.lng(),
}));

if (markerRef.current) {
markerRef.current.setPosition({ lat: location.lat, lng: location.lng });
} else {
markerRef.current = new window.google.maps.Marker({
position: { lat: location.lat, lng: location.lng },
map: googleMap,
});
}
});

setMap(googleMap);
})
.catch((error) => {
console.error("Error loading Google Maps", error);
});
}, [mapCenterLat, mapCenterLon, mapZoom, mapKey]);

useEffect(() => {

if (map && !isNaN(location.lat) && !isNaN(location.lng)) {
if (pan) {
map.panTo({ lat: location.lat, lng: location.lng });
}

if (markerRef.current) {
markerRef.current.setPosition({ lat: location.lat, lng: location.lng });
} else {
markerRef.current = new window.google.maps.Marker({
position: { lat: location.lat, lng: location.lng },
map: map,
});
}
} else if (markerRef.current) {
markerRef.current.setMap(null);
markerRef.current = null;
}
}, [location.lat, location.lng, map, pan]);

export default function LocationFilter({ onChange, data }) {
return (
<div>
<LocationFilterMap onChange={onChange} data={data} />
<LocationFilterText onChange={onChange} />
{[
{ LATITUDE: "lat" },
{ LONGITUDE: "lng" },
{ BEARING: "bearing" },
{ DISTANCE: "distance" },
].map((item, index) => {
return (
<FormGroup
key={index}
style={{
marginRight: "10px",
}}
>
<FormLabel>
<FormattedMessage id={Object.keys(item)[0]} />
</FormLabel>
<FormControl
type="number"
placeholder={
intl.formatMessage({ id: "TYPE_NUMBER" })
}
value={location[Object.values(item)[0]]}
onChange={(e) => {
console.log("onChange");
setLocation((prevLocation) => ({
...prevLocation,
[Object.values(item)[0]]: e.target.value,
}));
}}
/>
</FormGroup>
);
})}

<div
className="mt-4"
style={{
width: "100%",
height: "400px",
borderRadius: "15px",
overflow: "hidden",
}}
>
<div ref={mapRef} style={{ width: "100%", height: "100%" }}></div>
</div>
</div>
);
)
}

0 comments on commit 2f38998

Please sign in to comment.