Fix missing Address, rename Btns, add copy coords #5
This commit is contained in:
@@ -1,28 +1,25 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
import { OSMWay } from "@repo/db";
|
import { OSMWay } from "@repo/db";
|
||||||
|
import { useDispatchConnectionStore } from "_store/dispatch/connectionStore";
|
||||||
import { useMapStore } from "_store/mapStore";
|
import { useMapStore } from "_store/mapStore";
|
||||||
import { usePannelStore } from "_store/pannelStore";
|
import { usePannelStore } from "_store/pannelStore";
|
||||||
import {
|
import { MapPin, MapPinned, Radius, Ruler, Search, RulerDimensionLine, Scan } from "lucide-react";
|
||||||
MapPin,
|
|
||||||
MapPinned,
|
|
||||||
Radius,
|
|
||||||
Ruler,
|
|
||||||
Search,
|
|
||||||
RulerDimensionLine,
|
|
||||||
Scan,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
import { Popup, useMap } from "react-leaflet";
|
import { Popup, useMap } from "react-leaflet";
|
||||||
|
|
||||||
export const ContextMenu = () => {
|
export const ContextMenu = () => {
|
||||||
const map = useMap();
|
const map = useMap();
|
||||||
const { contextMenu, setContextMenu, setSearchElements, setSearchPopup } =
|
const { contextMenu, setContextMenu, setSearchElements, setSearchPopup } = useMapStore();
|
||||||
useMapStore();
|
const { missionFormValues, setMissionFormValues, setOpen, isOpen } = usePannelStore(
|
||||||
const { setMissionFormValues, setOpen } = usePannelStore((state) => state);
|
(state) => state,
|
||||||
|
);
|
||||||
const [showRulerOptions, setShowRulerOptions] = useState(false);
|
const [showRulerOptions, setShowRulerOptions] = useState(false);
|
||||||
const [rulerHover, setRulerHover] = useState(false);
|
const [rulerHover, setRulerHover] = useState(false);
|
||||||
const [rulerOptionsHover, setRulerOptionsHover] = useState(false);
|
const [rulerOptionsHover, setRulerOptionsHover] = useState(false);
|
||||||
|
|
||||||
|
const dispatcherConnected = useDispatchConnectionStore((s) => s.status) === "connected";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setShowRulerOptions(rulerHover || rulerOptionsHover);
|
setShowRulerOptions(rulerHover || rulerOptionsHover);
|
||||||
}, [rulerHover, rulerOptionsHover]);
|
}, [rulerHover, rulerOptionsHover]);
|
||||||
@@ -45,7 +42,9 @@ export const ContextMenu = () => {
|
|||||||
};
|
};
|
||||||
}, [map, contextMenu, setContextMenu, setSearchPopup]);
|
}, [map, contextMenu, setContextMenu, setSearchPopup]);
|
||||||
|
|
||||||
if (!contextMenu) return null;
|
if (!contextMenu || !dispatcherConnected) return null;
|
||||||
|
|
||||||
|
const einsatzBtnText = missionFormValues && isOpen ? "Position übernehmen" : "Einsatz erstellen";
|
||||||
|
|
||||||
const addOSMobjects = async () => {
|
const addOSMobjects = async () => {
|
||||||
const res = await fetch(
|
const res = await fetch(
|
||||||
@@ -67,9 +66,7 @@ export const ContextMenu = () => {
|
|||||||
return {
|
return {
|
||||||
wayID: e.id,
|
wayID: e.id,
|
||||||
nodes: e.nodes.map((nodeId: string) => {
|
nodes: e.nodes.map((nodeId: string) => {
|
||||||
const node = data.elements.find(
|
const node = data.elements.find((element: any) => element.id === nodeId);
|
||||||
(element: any) => element.id === nodeId,
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
lat: node.lat,
|
lat: node.lat,
|
||||||
lon: node.lon,
|
lon: node.lon,
|
||||||
@@ -100,45 +97,44 @@ export const ContextMenu = () => {
|
|||||||
{/* Top Button */}
|
{/* Top Button */}
|
||||||
<button
|
<button
|
||||||
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute left-1/2 top-0 pointer-events-auto opacity-80 tooltip tooltip-top tooltip-accent"
|
className="btn btn-circle bg-rescuetrack w-10 h-10 absolute left-1/2 top-0 pointer-events-auto opacity-80 tooltip tooltip-top tooltip-accent"
|
||||||
data-tip="Nächstes Element übernehmen"
|
data-tip={einsatzBtnText}
|
||||||
style={{ transform: "translateX(-50%)" }}
|
style={{ transform: "translateX(-50%)" }}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const address = await fetch(
|
const address = await fetch(
|
||||||
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
||||||
);
|
);
|
||||||
const data = (await address.json()) as {
|
const data = (await address.json()) as {
|
||||||
address: {
|
address?: {
|
||||||
ISO3166_2_lvl4: string;
|
ISO3166_2_lvl4?: string;
|
||||||
country: string;
|
country?: string;
|
||||||
country_code: string;
|
country_code?: string;
|
||||||
county: string;
|
county?: string;
|
||||||
house_number: string;
|
house_number?: string;
|
||||||
municipality: string;
|
municipality?: string;
|
||||||
postcode: string;
|
postcode?: string;
|
||||||
road: string;
|
road?: string;
|
||||||
state: string;
|
state?: string;
|
||||||
city: string;
|
city?: string;
|
||||||
town: string;
|
town?: string;
|
||||||
};
|
};
|
||||||
display_name: string;
|
display_name?: string;
|
||||||
importance: number;
|
importance?: number;
|
||||||
lat: string;
|
lat?: string;
|
||||||
licence: string;
|
licence?: string;
|
||||||
lon: string;
|
lon?: string;
|
||||||
name: string;
|
name?: string;
|
||||||
osm_id: number;
|
osm_id?: number;
|
||||||
osm_type: string;
|
osm_type?: string;
|
||||||
place_id: number;
|
place_id?: number;
|
||||||
place_rank: number;
|
place_rank?: number;
|
||||||
type: string;
|
type?: string;
|
||||||
};
|
};
|
||||||
|
const addressObj = data.address ?? {};
|
||||||
const objects = await addOSMobjects();
|
const objects = await addOSMobjects();
|
||||||
const exactAddress = objects.find((object) => {
|
const exactAddress = objects.find((object) => {
|
||||||
return (
|
return (
|
||||||
object.tags["addr:street"] == data.address.road &&
|
object.tags["addr:street"] == addressObj.road &&
|
||||||
object.tags["addr:housenumber"]?.includes(
|
object.tags["addr:housenumber"]?.includes(addressObj.house_number ?? "")
|
||||||
data.address.house_number,
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
const closestToContext = objects.reduce((prev, curr) => {
|
const closestToContext = objects.reduce((prev, curr) => {
|
||||||
@@ -147,24 +143,21 @@ export const ContextMenu = () => {
|
|||||||
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
||||||
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
||||||
const prevDistance = Math.sqrt(
|
const prevDistance = Math.sqrt(
|
||||||
Math.pow(prevLat - contextMenu.lat, 2) +
|
Math.pow(prevLat - contextMenu.lat, 2) + Math.pow(prevLon - contextMenu.lng, 2),
|
||||||
Math.pow(prevLon - contextMenu.lng, 2),
|
|
||||||
);
|
);
|
||||||
const currDistance = Math.sqrt(
|
const currDistance = Math.sqrt(
|
||||||
Math.pow(currLat - contextMenu.lat, 2) +
|
Math.pow(currLat - contextMenu.lat, 2) + Math.pow(currLon - contextMenu.lng, 2),
|
||||||
Math.pow(currLon - contextMenu.lng, 2),
|
|
||||||
);
|
);
|
||||||
return prevDistance < currDistance ? prev : curr;
|
return prevDistance < currDistance ? prev : curr;
|
||||||
});
|
}, [] as any);
|
||||||
|
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
console.log(data.address.road);
|
|
||||||
setMissionFormValues({
|
setMissionFormValues({
|
||||||
addressLat: contextMenu.lat,
|
addressLat: contextMenu.lat,
|
||||||
addressLng: contextMenu.lng,
|
addressLng: contextMenu.lng,
|
||||||
addressCity: data.address.city || data.address.town || "",
|
addressCity: addressObj.city || addressObj.town || "",
|
||||||
addressStreet: `${data.address.road || "keine Straße"}, ${data.address.house_number || "keine HN"}`,
|
addressStreet: `${addressObj.road || "keine Straße"}, ${addressObj.house_number || "keine HN"}`,
|
||||||
addressZip: data.address.postcode || "",
|
addressZip: addressObj.postcode || "",
|
||||||
state: "draft",
|
state: "draft",
|
||||||
addressOSMways: [(exactAddress || closestToContext) as any],
|
addressOSMways: [(exactAddress || closestToContext) as any],
|
||||||
});
|
});
|
||||||
@@ -187,70 +180,9 @@ export const ContextMenu = () => {
|
|||||||
data-tip="Koordinaten kopieren"
|
data-tip="Koordinaten kopieren"
|
||||||
style={{ transform: "translateX(-50%)" }}
|
style={{ transform: "translateX(-50%)" }}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const address = await fetch(
|
const coords = `${contextMenu.lat}, ${contextMenu.lng}`;
|
||||||
`https://nominatim.openstreetmap.org/reverse?lat=${contextMenu.lat}&lon=${contextMenu.lng}&format=json`,
|
await navigator.clipboard.writeText(coords);
|
||||||
);
|
toast.success("Koordinaten in die Zwischenablage kopiert!");
|
||||||
const data = (await address.json()) as {
|
|
||||||
address: {
|
|
||||||
ISO3166_2_lvl4: string;
|
|
||||||
country: string;
|
|
||||||
country_code: string;
|
|
||||||
county: string;
|
|
||||||
house_number: string;
|
|
||||||
municipality: string;
|
|
||||||
postcode: string;
|
|
||||||
road: string;
|
|
||||||
state: string;
|
|
||||||
city: 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;
|
|
||||||
};
|
|
||||||
const objects = await addOSMobjects();
|
|
||||||
const exactAddress = objects.find((object) => {
|
|
||||||
return (
|
|
||||||
object.tags["addr:street"] == data.address.road &&
|
|
||||||
object.tags["addr:housenumber"]?.includes(
|
|
||||||
data.address.house_number,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
const closestToContext = objects.reduce((prev, curr) => {
|
|
||||||
const prevLat = prev.nodes?.[0]?.lat ?? 0;
|
|
||||||
const prevLon = prev.nodes?.[0]?.lon ?? 0;
|
|
||||||
const currLat = curr.nodes?.[0]?.lat ?? 0;
|
|
||||||
const currLon = curr.nodes?.[0]?.lon ?? 0;
|
|
||||||
const prevDistance = Math.sqrt(
|
|
||||||
Math.pow(prevLat - contextMenu.lat, 2) +
|
|
||||||
Math.pow(prevLon - contextMenu.lng, 2),
|
|
||||||
);
|
|
||||||
const currDistance = Math.sqrt(
|
|
||||||
Math.pow(currLat - contextMenu.lat, 2) +
|
|
||||||
Math.pow(currLon - contextMenu.lng, 2),
|
|
||||||
);
|
|
||||||
return prevDistance < currDistance ? prev : curr;
|
|
||||||
}, [] as any);
|
|
||||||
|
|
||||||
setOpen(true);
|
|
||||||
setMissionFormValues({
|
|
||||||
addressLat: contextMenu.lat,
|
|
||||||
addressLng: contextMenu.lng,
|
|
||||||
addressCity: data.address.city || data.address.town || "",
|
|
||||||
addressStreet: `${data.address.road || "keine Straße"}, ${data.address.house_number || "keine HN"}`,
|
|
||||||
addressZip: data.address.postcode || "",
|
|
||||||
state: "draft",
|
|
||||||
addressOSMways: [(exactAddress || closestToContext) as any],
|
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MapPin size={20} />
|
<MapPin size={20} />
|
||||||
|
|||||||
Reference in New Issue
Block a user