added Map objekt polygon

This commit is contained in:
PxlLoewe
2025-04-08 09:16:00 -07:00
parent 133eee50fd
commit 5c9134a278
22 changed files with 333 additions and 122 deletions

View File

@@ -1,10 +1,11 @@
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, map: mapStore, setPopup } = useMapStore();
const { popup, setSearchElements, setPopup } = useMapStore();
useEffect(() => {
map.on("contextmenu", (e) => {
@@ -17,9 +18,9 @@ export const ContextMenu = () => {
return (
<Popup position={[popup.lat, popup.lng]}>
{/* // TODO: maske: */}
<div>
<div className="absolute transform -translate-y-1/2 z-1000 opacity-100 pointer-events-auto p-3">
<button
className="btn btn-sm"
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`,
@@ -51,7 +52,48 @@ export const ContextMenu = () => {
};
}}
>
Neues Einsatz hier Erstellen
<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>

View File

@@ -5,6 +5,7 @@ import { MapContainer } from "react-leaflet";
import { BaseMaps } from "(dispatch)/_components/map/BaseMaps";
import { ContextMenu } from "(dispatch)/_components/map/ContextMenu";
import { MissionMarkers } from "(dispatch)/_components/map/MissionMarkers";
import { SearchElements } from "(dispatch)/_components/map/SearchElements";
export default ({}) => {
const { map } = useMapStore();
@@ -12,6 +13,7 @@ export default ({}) => {
return (
<MapContainer className="flex-1" center={map.center} zoom={map.zoom}>
<BaseMaps />
<SearchElements />
<ContextMenu />
<MissionMarkers />
</MapContainer>

View File

@@ -15,7 +15,7 @@ export const MissionMarker = ({
const markerRef = useRef<LMarker<any>>(null);
useEffect(() => {
markerRef.current?.openPopup();
// markerRef.current?.openPopup();
const handleZoom = () => {
setZoom(map.getZoom());

View File

@@ -0,0 +1,74 @@
import { useMapStore } from "_store/mapStore";
import { Marker as LMarker } from "leaflet";
import { Ref, use, useEffect, useRef } from "react";
import { Marker, Polygon, Polyline, Popup } from "react-leaflet";
import L from "leaflet";
export const SearchElements = () => {
const { searchElements, searchPopup, setSearchPopup } = useMapStore();
const poppupRef = useRef<LMarker>(null);
useEffect(() => {
if (searchPopup?.isOpen) {
poppupRef.current?.openPopup();
} else {
poppupRef.current?.closePopup();
}
}, [searchPopup]);
const SearchElement = ({
element,
}: {
element: (typeof searchElements)[1];
}) => {
const ref = useRef<any>(null);
useEffect(() => {
if (ref.current) {
console.log(ref.current);
ref.current.on("click", () => {
console.log("click");
const center = ref.current.getBounds().getCenter();
setSearchPopup({
isOpen: true,
lat: center.lat,
lng: center.lng,
elementId: element.id,
});
console.log(element);
});
}
}, []);
return (
<Polygon
key={element.id}
positions={element.nodes.map((node) => [node.lat, node.lon])}
color="#46b7a3"
ref={ref}
/>
);
};
return (
<>
{searchElements.map((element) => {
return <SearchElement key={element.id} element={element} />;
})}
{searchPopup && (
<Marker
position={[searchPopup.lat, searchPopup.lng]}
ref={poppupRef}
icon={new L.DivIcon()}
opacity={0}
>
<Popup>
<div className="absolute z-1000 opacity-100 pointer-events-auto w-[500px] text-white">
<div className="bg-red-600 w-7 h-6">test</div>
</div>
</Popup>
</Marker>
)}
</>
);
};

View File

@@ -11,7 +11,33 @@ interface MapStore {
center: L.LatLngExpression;
zoom: number;
};
searchElements: {
id: number;
nodes: {
lat: number;
lon: number;
}[];
tags: {
addr: {
city?: string;
housenumber?: string;
postcode?: string;
street?: string;
suburb?: string;
};
building?: string;
};
type: string;
}[];
setSearchElements: (elements: MapStore["searchElements"]) => void;
setPopup: (popup: MapStore["popup"]) => void;
searchPopup?: {
isOpen: boolean;
lat: number;
lng: number;
elementId: number;
};
setSearchPopup: (popup: MapStore["searchPopup"]) => void;
}
export const useMapStore = create<MapStore>((set, get) => ({
@@ -19,9 +45,18 @@ export const useMapStore = create<MapStore>((set, get) => ({
center: [51.5, 10.5],
zoom: 6,
},
searchElements: [],
setSearchPopup: (popup) =>
set((state) => ({
searchPopup: popup,
})),
popup: null,
setPopup: (popup) =>
set((state) => ({
popup: popup,
})),
setSearchElements: (elements) =>
set((state) => ({
searchElements: elements,
})),
}));

View File

@@ -12,6 +12,7 @@ export default {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
rescuetrack: "#46b7a3",
},
transitionProperty: {
width: "width",