102 lines
2.6 KiB
TypeScript
102 lines
2.6 KiB
TypeScript
import { useMapStore } from "_store/mapStore";
|
|
import { MapPinned, Search } from "lucide-react";
|
|
import { useEffect } from "react";
|
|
import { Popup, useMap } from "react-leaflet";
|
|
|
|
export const ContextMenu = () => {
|
|
const map = useMap();
|
|
const { popup, setSearchElements, setPopup } = useMapStore();
|
|
|
|
useEffect(() => {
|
|
map.on("contextmenu", (e) => {
|
|
setPopup({ isOpen: true, lat: e.latlng.lat, lng: e.latlng.lng });
|
|
});
|
|
}, [popup]);
|
|
|
|
if (!popup) return null;
|
|
|
|
return (
|
|
<Popup position={[popup.lat, popup.lng]}>
|
|
{/* // TODO: maske: */}
|
|
<div className="absolute transform -translate-y-1/2 z-1000 opacity-100 pointer-events-auto p-3">
|
|
<button
|
|
className="btn btn-sm rounded-full bg-amber-600 hover:bg-amber-700 aspect-square"
|
|
onClick={async () => {
|
|
const address = await fetch(
|
|
`https://nominatim.openstreetmap.org/reverse?lat=${popup.lat}&lon=${popup.lng}&format=json`,
|
|
);
|
|
const data = (await address.json()) as {
|
|
address: {
|
|
ISO3166_2_lvl4: string;
|
|
country: string;
|
|
country_code: string;
|
|
county: string;
|
|
hamlet: string;
|
|
municipality: string;
|
|
postcode: string;
|
|
road: string;
|
|
state: string;
|
|
town: string;
|
|
};
|
|
display_name: string;
|
|
importance: number;
|
|
lat: string;
|
|
licence: string;
|
|
lon: string;
|
|
name: string;
|
|
osm_id: number;
|
|
osm_type: string;
|
|
place_id: number;
|
|
place_rank: number;
|
|
type: string;
|
|
};
|
|
}}
|
|
>
|
|
<MapPinned size={20} />
|
|
</button>
|
|
<button
|
|
className="btn btn-sm rounded-full bg-amber-600 hover:bg-amber-700 aspect-square"
|
|
onClick={async () => {
|
|
const res = await fetch(
|
|
`https://overpass-api.de/api/interpreter?data=${encodeURIComponent(`
|
|
[out:json];
|
|
(
|
|
way["building"](around:50, ${popup.lat}, ${popup.lng});
|
|
relation["building"](around:50, ${popup.lat}, ${popup.lng});
|
|
);
|
|
out body;
|
|
>;
|
|
out skel qt;
|
|
`)}`,
|
|
);
|
|
const data = await res.json();
|
|
setSearchElements(
|
|
data.elements
|
|
.filter((e: any) => e.type === "way")
|
|
.map((e: any) => {
|
|
return {
|
|
id: e.id,
|
|
nodes: e.nodes.map((nodeId: string) => {
|
|
const node = data.elements.find(
|
|
(element: any) => element.id === nodeId,
|
|
);
|
|
return {
|
|
lat: node.lat,
|
|
lon: node.lon,
|
|
};
|
|
}),
|
|
tags: e.tags,
|
|
type: e.type,
|
|
};
|
|
}),
|
|
);
|
|
console.log(data);
|
|
}}
|
|
>
|
|
<Search size={20} />
|
|
</button>
|
|
</div>
|
|
</Popup>
|
|
);
|
|
};
|