ShowAddStationPopup.js Komponent erstellt statt in MapComponent für bessere Organisation in das Projekt

This commit is contained in:
ISA
2024-05-02 12:37:59 +02:00
parent c4e70564ec
commit 7465069e44
5 changed files with 238 additions and 132 deletions

View File

@@ -1,5 +1,6 @@
// components/MapComponent.js // components/MapComponent.js
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom/client"; // Import from 'react-dom/client'
import L, { marker } from "leaflet"; import L, { marker } from "leaflet";
import "leaflet/dist/leaflet.css"; import "leaflet/dist/leaflet.css";
import "leaflet-contextmenu/dist/leaflet.contextmenu.css"; import "leaflet-contextmenu/dist/leaflet.contextmenu.css";
@@ -8,16 +9,19 @@ import * as config from "../config/config.js";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import "leaflet.smooth_marker_bouncing"; import "leaflet.smooth_marker_bouncing";
import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet"; import OverlappingMarkerSpiderfier from "overlapping-marker-spiderfier-leaflet";
import DataSheet from "../components/DataSheet"; import DataSheet from "./DataSheet.js";
import { useRecoilState, useRecoilValue } from "recoil"; import { useRecoilState, useRecoilValue, RecoilRoot } from "recoil";
import { gisStationsStaticDistrictState } from "../store/gisStationState"; import { gisStationsStaticDistrictState } from "../store/gisStationState.js";
import { gisSystemStaticState } from "../store/gisSystemState"; import { gisSystemStaticState } from "../store/gisSystemState.js";
import { mapLayersState } from "../store/mapLayersState"; import { mapLayersState } from "../store/mapLayersState.js";
import { selectedAreaState } from "../store/selectedAreaState"; import { selectedAreaState } from "../store/selectedAreaState.js";
import { zoomTriggerState } from "../store/zoomTriggerState"; import { zoomTriggerState } from "../store/zoomTriggerState.js";
import { poiTypState } from "../store/poiTypState"; import { poiTypState } from "../store/poiTypState.js";
import ShowAddStationPopup from "./ShowAddStationPopup";
//import { createRoot } from "react-dom/client";
const MapComponent = ({ locations, onLocationUpdate }) => { const MapComponent = ({ locations, onLocationUpdate }) => {
const [poiTypData, setPoiTypData] = useRecoilState(poiTypState); // Recoil State verwenden
const poiLayerRef = useRef(null); // Referenz auf die Layer-Gruppe für Datenbank-Marker const poiLayerRef = useRef(null); // Referenz auf die Layer-Gruppe für Datenbank-Marker
const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte const mapRef = useRef(null); // Referenz auf das DIV-Element der Karte
const [map, setMap] = useState(null); // Zustand der Karteninstanz const [map, setMap] = useState(null); // Zustand der Karteninstanz
@@ -322,6 +326,29 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
} }
} }
//---------------------------------- //----------------------------------
//------------------------------------------
// Funktion zum Abrufen der poiTyp Daten
useEffect(() => {
const fetchPoiTypData = async () => {
try {
const response = await fetch("/api/poiTyp");
const data = await response.json();
setPoiTypData(data); // Daten im Recoil State speichern
} catch (error) {
console.error("Fehler beim Abrufen der poiTyp Daten:", error);
}
};
fetchPoiTypData();
}, []);
// Effekt zum Loggen der poiTypData, wenn sie sich ändern
useEffect(() => {
console.log("poiTypData aktualisiert:", poiTypData);
}, [poiTypData]);
//----------------------------------------------------
//-----Kontextmenu---------------- //-----Kontextmenu----------------
const newLink = (e) => { const newLink = (e) => {
try { try {
@@ -382,99 +409,39 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
}; };
//-----Kontextmenu----ende------------ //-----Kontextmenu----ende------------
// Ensure this function is only called when map is initialized and available // Ensure this function is only called when map is initialized and available
const showAddStationPopup = (e) => { const showAddStationPopup = (e, map) => {
if (!initMap) { const container = L.DomUtil.create("div");
return;
}
const popupContent = L.DomUtil.create("div"); // Create a root container for the React component inside the popup
popupContent.innerHTML = ` const root = ReactDOM.createRoot(container);
<form id="addStationForm" class="m-0 p-2 w-full">
<!-- Kommantar von hier
<div class="flex items-center mb-4">
<label for="idPoi" class="block mr-2 flex-none">ID Poi:</label> root.render(
<input <RecoilRoot>
type="text" <ShowAddStationPopup map={map} latlng={e.latlng} />
id="idPoi" </RecoilRoot>
name="idPoi" );
value="2"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="idPoiTyp" class="block mr-2 flex-none">ID idPoiTyp:</label>
<input
type="text"
id="idPoiTyp"
name="idPoiTyp"
value="2"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
Kommantar bis hier-->
<div class="flex items-center mb-4">
<label for="name" class="block mr-2 flex-none">Name:</label>
<input
type="text"
id="name"
name="name"
placeholder="Name der Station"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="idPoi" class="block mr-3 flex-none">Type:</label>
<input
type="text"
id="type"
name="type"
placeholder="Typ der Station"
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="lat" class="block mr-2 flex-none">Breitengrad:</label>
<input
type="text"
id="lat"
name="lat"
value="${e.latlng.lat.toFixed(5)}"
readonly
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
<div class="flex items-center mb-4">
<label for="lng" class="block mr-2 flex-none">Längengrad:</label>
<input
type="text"
id="lng"
name="lng"
value="${e.latlng.lng.toFixed(5)}"
readonly
class="block p-2 flex-grow border-2 border-gray-200 rounded-md text-sm"
/>
</div>
// Create and configure the popup
<button L.popup().setLatLng(e.latlng).setContent(container).openOn(initMap);
type="submit"
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"
>
Station hinzufügen
</button>
</form>
`;
L.popup().setLatLng(e.latlng).setContent(popupContent).openOn(initMap); // Cleanup when the popup is closed
initMap.on("popupclose", () => {
// Attach event listener here root.unmount(); // Use unmount method from the root
L.DomEvent.on(popupContent, "submit", handleSubmit); });
}; };
// Inside your ShowAddStationPopup component
useEffect(() => {
// Cleanup function to unmount React component
return () => {
if (container._reactRoot) {
container._reactRoot.unmount();
}
};
}, []);
//------------------------------------------
// Hinzufügen eines neuen Standorts (Marker) in MySQL-DB-Tabelle (poi) // Hinzufügen eines neuen Standorts (Marker) in MySQL-DB-Tabelle (poi)
async function handleSubmit(event) { async function handleSubmit(event) {
event.preventDefault(); event.preventDefault();
@@ -1507,30 +1474,8 @@ const MapComponent = ({ locations, onLocationUpdate }) => {
} // Ihre bereits existierende Funktion, die Zoom-Out ausführt } // Ihre bereits existierende Funktion, die Zoom-Out ausführt
} }
}, [map, zoomTrigger]); }, [map, zoomTrigger]);
//------------------------------------------
// Funktion zum Abrufen der poiTyp Daten
const [poiTypData, setPoiTypData] = useRecoilState(poiTypState); // Recoil State verwenden
useEffect(() => { //---------------------------------------------------------
const fetchPoiTypData = async () => {
try {
const response = await fetch("/api/poiTyp");
const data = await response.json();
setPoiTypData(data); // Daten im Recoil State speichern
} catch (error) {
console.error("Fehler beim Abrufen der poiTyp Daten:", error);
}
};
fetchPoiTypData();
}, []);
// Effekt zum Loggen der poiTypData, wenn sie sich ändern
useEffect(() => {
console.log("poiTypData aktualisiert:", poiTypData);
}, [poiTypData]);
//----------------------------------------------------
return ( return (
<> <>

View File

@@ -0,0 +1,95 @@
// components/ShowAddStationPopup.js:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { useRecoilState } from "recoil";
import { poiTypState } from "../store/poiTypState";
const ShowAddStationPopup = ({ map, latlng }) => {
const [poiTypData, setPoiTypData] = useRecoilState(poiTypState);
const [name, setName] = useState("");
const [poiTypeId, setPoiTypeId] = useState("");
const [latitude] = useState(latlng.lat.toFixed(5));
const [longitude] = useState(latlng.lng.toFixed(5));
// Effekt zum Ausgeben von poiTypData in der Konsole
useEffect(() => {
console.log("poiTypData in ShowAddStationPopup.js :", poiTypData);
}, [poiTypData]);
const handleSubmit = (event) => {
event.preventDefault();
console.log({ name, poiTypeId, latitude, longitude });
map.closePopup();
};
return (
<form onSubmit={handleSubmit} className="m-0 p-2 w-full ">
<div className="flex items-center mb-4">
<label htmlFor="name" className="block mr-2 flex-none">
Name:
</label>
<input
type="text"
id="name"
name="name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name der Station"
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" // Use w-full for full width
/>
</div>
<div className="flex items-center mb-4">
<label htmlFor="idPoiTyp" className="block mr-2 flex-none">
Typ:
</label>
<select
id="idPoiTyp"
name="idPoiTyp"
value={poiTypeId}
onChange={(e) => setPoiTypeId(e.target.value)}
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" // Adjusted width
>
{poiTypData.map((poiTyp) => (
<option key={poiTyp.id} value={poiTyp.id}>
{poiTyp.name}
</option>
))}
</select>
</div>
<div className="flex items-center mb-4">
<label htmlFor="lat" className="block mr-2 flex-none">
Breitengrad:
</label>
<input
type="text"
id="lat"
name="lat"
value={latitude}
readOnly
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" // Adjusted width
/>
</div>
<div className="flex items-center mb-4">
<label htmlFor="lng" className="block mr-2 flex-none">
Längengrad:
</label>
<input
type="text"
id="lng"
name="lng"
value={longitude}
readOnly
className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" // Adjusted width
/>
</div>
<button
type="submit"
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full"
>
Station hinzufügen
</button>
</form>
);
};
export default ShowAddStationPopup;

85
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{ {
"name": "OpenStreetMapProject-26.04.2024", "name": "OpenStreetMapProject-02.05.2024",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
@@ -13,11 +13,15 @@
"next": "^14.2.0", "next": "^14.2.0",
"overlapping-marker-spiderfier-leaflet": "^0.2.7", "overlapping-marker-spiderfier-leaflet": "^0.2.7",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
"recoil": "^0.7.7" "recoil": "^0.7.7"
}, },
"devDependencies": { "devDependencies": {
"@types/leaflet": "^1.9.12",
"@types/leaflet-contextmenu": "^1.4.3",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"prettier": "^3.2.5", "prettier": "^3.2.5",
@@ -310,6 +314,12 @@
"tslib": "^2.4.0" "tslib": "^2.4.0"
} }
}, },
"node_modules/@types/geojson": {
"version": "7946.0.14",
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz",
"integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==",
"dev": true
},
"node_modules/@types/http-proxy": { "node_modules/@types/http-proxy": {
"version": "1.17.14", "version": "1.17.14",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz",
@@ -318,6 +328,24 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/leaflet": {
"version": "1.9.12",
"resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz",
"integrity": "sha512-BK7XS+NyRI291HIo0HCfE18Lp8oA30H1gpi1tf0mF3TgiCEzanQjOqNZ4x126SXzzi2oNSZhZ5axJp1k0iM6jg==",
"dev": true,
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/leaflet-contextmenu": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@types/leaflet-contextmenu/-/leaflet-contextmenu-1.4.3.tgz",
"integrity": "sha512-S2FCwMDtgyuykW9tZ0Wg99FDDdtpoMhmoqGgbrqXvMlQ2Yfl7ZuHJqcmvLZznr48pZjfPuvdkeGzcGkIM3ihYg==",
"dev": true,
"dependencies": {
"@types/leaflet": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.12.7", "version": "20.12.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz",
@@ -326,6 +354,31 @@
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
}, },
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
"dev": true
},
"node_modules/@types/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz",
"integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.3.0",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz",
"integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/ansi-regex": { "node_modules/ansi-regex": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
@@ -628,6 +681,12 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1531,9 +1590,9 @@
] ]
}, },
"node_modules/react": { "node_modules/react": {
"version": "18.2.0", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
}, },
@@ -1542,15 +1601,15 @@
} }
}, },
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "18.2.0", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0", "loose-envify": "^1.1.0",
"scheduler": "^0.23.0" "scheduler": "^0.23.2"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^18.2.0" "react": "^18.3.1"
} }
}, },
"node_modules/react-leaflet": { "node_modules/react-leaflet": {
@@ -1681,9 +1740,9 @@
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
}, },
"node_modules/scheduler": { "node_modules/scheduler": {
"version": "0.23.0", "version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"dependencies": { "dependencies": {
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }

View File

@@ -8,7 +8,7 @@
"next": "^14.2.0", "next": "^14.2.0",
"overlapping-marker-spiderfier-leaflet": "^0.2.7", "overlapping-marker-spiderfier-leaflet": "^0.2.7",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0", "react-dom": "^18.3.1",
"react-leaflet": "^4.2.1", "react-leaflet": "^4.2.1",
"recoil": "^0.7.7" "recoil": "^0.7.7"
}, },
@@ -19,6 +19,10 @@
"export": "next export" "export": "next export"
}, },
"devDependencies": { "devDependencies": {
"@types/leaflet": "^1.9.12",
"@types/leaflet-contextmenu": "^1.4.3",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.0",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"prettier": "^3.2.5", "prettier": "^3.2.5",

View File

@@ -7,3 +7,6 @@
.tooltip-tailwind .leaflet-tooltip { .tooltip-tailwind .leaflet-tooltip {
@apply bg-white text-black p-2 border border-gray-300 rounded shadow !important; @apply bg-white text-black p-2 border border-gray-300 rounded shadow !important;
} }
.leaflet-popup-content {
min-width: 250px; /* Adjust the width based on your requirements */
}