diff --git a/TODO.md b/TODO.md index dd2ad79be..4830cea4a 100644 --- a/TODO.md +++ b/TODO.md @@ -49,3 +49,4 @@ optimiert besser als setInterval, zuerst nur für TALAS.web WebServices erstelle die Daten von DB auch mit WebSocket gelöst werden - [ ] TODO: POI bearbeiten funktioniert es nicht +- [ ] TODO: Linien Links noch mit Port 3000 diff --git a/components/mainComponent/MapComponent.js b/components/mainComponent/MapComponent.js index 5f52cda61..a6245c83a 100644 --- a/components/mainComponent/MapComponent.js +++ b/components/mainComponent/MapComponent.js @@ -7,7 +7,7 @@ import "leaflet-contextmenu"; import "leaflet.smooth_marker_bouncing"; import "react-toastify/dist/ReactToastify.css"; import { InformationCircleIcon } from "@heroicons/react/20/solid"; -import PoiUpdateModal from "@/components/pois/PoiUpdateModal.js"; +import PoiUpdateModal from "@/components/pois/poiUpdateModal/PoiUpdateModal.js"; import { ToastContainer, toast } from "react-toastify"; import plusRoundIcon from "../icons/devices/overlapping/PlusRoundIcon.js"; import { restoreMapSettings, checkOverlappingMarkers } from "../../utils/mapUtils.js"; @@ -244,6 +244,8 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { }, [map, locations, poiReadTrigger]); //-------------------------------------------- + const { Points: gisDevices = [] } = useSelector(selectGisStationsStaticDistrict); + // POIs auf die Karte zeichnen useEffect(() => { if (poiData.length === 0) return; @@ -264,7 +266,7 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { toast, setShowPoiUpdateModal, setCurrentPoiData, - deviceName, + gisDevices, dispatch ); }, [ diff --git a/components/pois/AddPOIModal.js b/components/pois/AddPOIModal.js index 9851f3e12..1733df461 100644 --- a/components/pois/AddPOIModal.js +++ b/components/pois/AddPOIModal.js @@ -10,7 +10,7 @@ import { fetchPoiIconsDataThunk } from "../../redux/thunks/database/pois/fetchPo const AddPOIModal = ({ onClose, map, latlng }) => { const dispatch = useDispatch(); - + const [selectedDeviceId, setSelectedDeviceId] = useState(""); const poiTypData = useSelector(state => state.poiTypes.data); const status = useSelector(state => state.addPoi.status); const error = useSelector(state => state.addPoi.error); @@ -49,7 +49,7 @@ const AddPOIModal = ({ onClose, map, latlng }) => { poiTypeId: Number(poiTypeId), latitude, longitude, - idLD: locationDeviceData.find(device => device.LD_Name === deviceName)?.IdLD, + idLD: Number(selectedDeviceId), }; try { @@ -110,14 +110,14 @@ const AddPOIModal = ({ onClose, map, latlng }) => { diff --git a/components/pois/PoiUpdateModal.js b/components/pois/poiUpdateModal/PoiUpdateModal.js similarity index 67% rename from components/pois/PoiUpdateModal.js rename to components/pois/poiUpdateModal/PoiUpdateModal.js index 6913e490e..42cb21798 100644 --- a/components/pois/PoiUpdateModal.js +++ b/components/pois/poiUpdateModal/PoiUpdateModal.js @@ -1,84 +1,41 @@ -// /components/pois/PoiUpdateModal.js +// @/components/pois/PoiUpdateModal.js import React, { useState, useEffect } from "react"; import Select from "react-select"; import { useSelector, useDispatch } from "react-redux"; -import { fetchLocationDevicesThunk } from "../../redux/thunks/database/fetchLocationDevicesThunk"; -import { fetchPoiTypThunk } from "../../redux/thunks/database/pois/fetchPoiTypThunk"; -import { selectMapLayersState } from "../../redux/slices/mapLayersSlice"; -import { selectPoiTypData, selectPoiTypStatus } from "../../redux/slices/database/pois/poiTypSlice"; -import { deletePoiThunk } from "../../redux/thunks/database/pois/deletePoiThunk"; -import { updatePoiThunk } from "../../redux/thunks/database/pois/updatePoiThunk"; +import { fetchLocationDevicesThunk } from "@/redux/thunks/database/fetchLocationDevicesThunk"; +import { fetchPoiTypThunk } from "@/redux/thunks/database/pois/fetchPoiTypThunk"; +import { selectMapLayersState } from "@/redux/slices/mapLayersSlice"; +import { selectPoiTypData, selectPoiTypStatus } from "@/redux/slices/database/pois/poiTypSlice"; +import { deletePoiThunk } from "@/redux/thunks/database/pois/deletePoiThunk"; +import { updatePoiThunk } from "@/redux/thunks/database/pois/updatePoiThunk"; +import { selectSelectedPoi } from "@/redux/slices/database/pois/selectedPoiSlice"; +import { handleSubmit } from "@/components/pois/poiUpdateModal/utils/handlers"; +import { selectCurrentPoi } from "@/redux/slices/database/pois/currentPoiSlice"; +import { selectGisStationsStaticDistrict } from "@/redux/slices/webservice/gisStationsStaticDistrictSlice"; const PoiUpdateModal = ({ onClose, poiData }) => { const dispatch = useDispatch(); + const mapLayersVisibility = useSelector(selectMapLayersState); const poiTypData = useSelector(selectPoiTypData); const poiTypStatus = useSelector(selectPoiTypStatus); - const devices = useSelector(state => state.locationDevicesFromDB.devices); + //const devices = useSelector(state => state.locationDevicesFromDB.devices); + const { Points: availableDevices = [] } = useSelector(selectGisStationsStaticDistrict); - const [poiId, setPoiId] = useState(poiData?.idPoi || ""); - const [name, setName] = useState(poiData?.name || ""); - const [description, setDescription] = useState(poiData?.description || ""); + const poi = useSelector(selectCurrentPoi); + const selectedPoi = poi; + console.log("Selected POI in PoiUpdateModal:", selectedPoi); + + //const poi = poiData || selectedPoi || {}; + + const [poiId, setPoiId] = useState(poi?.idPoi || ""); + const [name, setName] = useState(poi?.name || ""); + const [description, setDescription] = useState(poi?.description || ""); const [deviceName, setDeviceName] = useState(null); const [poiTypeId, setPoiTypeId] = useState(null); const systemNameToIdMap = {}; - useEffect(() => { - dispatch(fetchLocationDevicesThunk()); - if (poiTypStatus === "idle") { - dispatch(fetchPoiTypThunk()); - } - }, [dispatch, poiTypStatus]); - - useEffect(() => { - if (poiData && devices.length > 0) { - const selectedDevice = devices.find(device => device.idLD === poiData.idLD); - if (selectedDevice) { - setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.name }); - } - } - }, [poiData, devices]); - - useEffect(() => { - if (poiData && poiTypData.length > 0) { - const selectedTyp = poiTypData.find(typ => typ.idPoiTyp === poiData.idPoiTyp); - if (selectedTyp) { - setPoiTypeId({ value: selectedTyp.idPoiTyp, label: selectedTyp.name }); - } - } - }, [poiData, poiTypData]); - - const filterDevices = () => { - const activeSystems = Object.keys(mapLayersVisibility).filter( - system => mapLayersVisibility[system] - ); - const activeSystemIds = activeSystems - .map(system => systemNameToIdMap[system]) - .filter(id => id !== undefined); - return devices.filter(device => activeSystemIds.includes(device.idsystem_typ)); - }; - - const handleSubmit = async event => { - event.preventDefault(); - try { - await dispatch( - updatePoiThunk({ - idPoi: poiId, - name, - description, - idPoiTyp: poiTypeId?.value ?? poiData?.idPoiTyp, - idLD: deviceName?.value, - }) - ).unwrap(); - onClose(); - window.location.reload(); - } catch (error) { - console.error("Fehler beim Aktualisieren des POI:", error); - alert("Fehler beim Aktualisieren des POI."); - } - }; - const handleDeletePoi = async () => { if (confirm("Sind Sie sicher, dass Sie diesen POI löschen möchten?")) { try { @@ -92,6 +49,55 @@ const PoiUpdateModal = ({ onClose, poiData }) => { } }; + useEffect(() => { + dispatch(fetchLocationDevicesThunk()); + if (poiTypStatus === "idle") { + dispatch(fetchPoiTypThunk()); + } + }, [dispatch, poiTypStatus]); + + /* useEffect(() => { + console.log("devices in PoiUpdateModal:", devices); + if (poi && devices.length > 0) { + const selectedDevice = devices.find(device => Number(device.idLD) === Number(poi.idLD)); + console.log("Selected Device:", selectedDevice); + if (selectedDevice) { + setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.name }); + } + } + }, [poi, devices]); */ + + useEffect(() => { + console.log("poiTypData in PoiUpdateModal:", poiTypData); + if (poi && poiTypData.length > 0) { + const selectedTyp = poiTypData.find(typ => Number(typ.idPoiTyp) === Number(poi.idPoiTyp)); + console.log("Selected Poi Type:", selectedTyp); + if (selectedTyp) { + setPoiTypeId({ value: selectedTyp.idPoiTyp, label: selectedTyp.name }); + } + } + }, [poi, poiTypData]); + + useEffect(() => { + console.log("availableDevices in PoiUpdateModal:", availableDevices); + if (poiData && availableDevices.length > 0) { + const selectedDevice = availableDevices.find(device => device.idLD === poiData.idLD); + if (selectedDevice) { + setDeviceName({ value: selectedDevice.idLD, label: selectedDevice.LD_Name }); // ✅ auch hier korrigieren + } + } + }, [poiData, availableDevices]); + + const filterDevices = () => { + const activeSystems = Object.keys(mapLayersVisibility).filter( + system => mapLayersVisibility[system] + ); + const activeSystemIds = activeSystems + .map(system => systemNameToIdMap[system]) + .filter(id => id !== undefined); + return devices.filter(device => activeSystemIds.includes(device.idsystem_typ)); + }; + const poiTypeOptions = Array.isArray(poiTypData) ? poiTypData.map(poiTyp => ({ value: poiTyp.idPoiTyp, @@ -99,9 +105,9 @@ const PoiUpdateModal = ({ onClose, poiData }) => { })) : []; - const deviceOptions = filterDevices().map(device => ({ + const deviceOptions = availableDevices.map(device => ({ value: device.idLD, - label: device.name, + label: device.LD_Name, })); const customStyles = { diff --git a/components/pois/poiUpdateModal/utils/handlers.js b/components/pois/poiUpdateModal/utils/handlers.js new file mode 100644 index 000000000..2c09f8003 --- /dev/null +++ b/components/pois/poiUpdateModal/utils/handlers.js @@ -0,0 +1,42 @@ +export const handleSubmit = async ({ + event, + dispatch, + poiId, + name, + description, + poiTypeId, + deviceName, + poi, + onClose, +}) => { + event.preventDefault(); + try { + await dispatch( + updatePoiThunk({ + idPoi: poiId, + name, + description, + idPoiTyp: poiTypeId?.value ?? poi?.idPoiTyp, + idLD: deviceName?.value, + }) + ).unwrap(); + onClose(); + window.location.reload(); + } catch (error) { + console.error("Fehler beim Aktualisieren des POI:", error); + alert("Fehler beim Aktualisieren des POI."); + } +}; + +export const handleDeletePoi = async ({ dispatch, poiId, onClose }) => { + if (confirm("Sind Sie sicher, dass Sie diesen POI löschen möchten?")) { + try { + await dispatch(deletePoiThunk(poiId)).unwrap(); + onClose(); + window.location.reload(); + } catch (error) { + console.error("Fehler beim Löschen des POI:", error); + alert("Fehler beim Löschen des POI."); + } + } +}; diff --git a/config/appVersion.js b/config/appVersion.js index e8dd07dec..79bdf9d9e 100644 --- a/config/appVersion.js +++ b/config/appVersion.js @@ -1,2 +1,2 @@ // /config/appVersion -export const APP_VERSION = "1.1.252"; +export const APP_VERSION = "1.1.253"; diff --git a/package-lock.json b/package-lock.json index 81ea324ac..b6bbfc88b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "06.06.2025 NodeMap at home", + "name": "10.06.2025 NodeMap at home", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/redux/slices/database/pois/selectedPoiSlice.js b/redux/slices/database/pois/selectedPoiSlice.js index 39dd4adf0..bbc6dd0a1 100644 --- a/redux/slices/database/pois/selectedPoiSlice.js +++ b/redux/slices/database/pois/selectedPoiSlice.js @@ -1,4 +1,4 @@ -// redux/slices/database/pois/selectedPoiSlice.js +// @/redux/slices/database/pois/selectedPoiSlice.js import { createSlice } from "@reduxjs/toolkit"; export const selectedPoiSlice = createSlice({ @@ -11,4 +11,5 @@ export const selectedPoiSlice = createSlice({ }); export const { setSelectedPoi, clearSelectedPoi } = selectedPoiSlice.actions; +export const selectSelectedPoi = state => state.selectedPoi; export default selectedPoiSlice.reducer; diff --git a/redux/store.js b/redux/store.js index feef8277b..f8ae97310 100644 --- a/redux/store.js +++ b/redux/store.js @@ -48,14 +48,14 @@ export const store = configureStore({ gisLinesStatusFromWebservice: gisLinesStatusFromWebserviceReducer, gisLinesFromDatabase: gisLinesFromDatabaseReducer, lineVisibility: lineVisibilityReducer, - currentPoi: currentPoiReducer, polylineLayerVisible: polylineLayerVisibleReducer, locationDevicesFromDB: locationDevicesFromDBReducer, poiTypes: poiTypesReducer, addPoiOnPolyline: addPoiOnPolylineReducer, polylineContextMenu: polylineContextMenuReducer, - selectedPoi: selectedPoiReducer, selectedDevice: selectedDeviceReducer, + selectedPoi: selectedPoiReducer, + currentPoi: currentPoiReducer, mapLayers: mapLayersReducer, poiLayerVisible: poiLayerVisibleReducer, poiReadFromDbTrigger: poiReadFromDbTriggerReducer, diff --git a/services/database.zip b/services/database.zip deleted file mode 100644 index f784b33a2..000000000 Binary files a/services/database.zip and /dev/null differ diff --git a/utils/setupPOIs.js b/utils/setupPOIs.js index 2f7395c6b..fd94362c8 100644 --- a/utils/setupPOIs.js +++ b/utils/setupPOIs.js @@ -21,7 +21,7 @@ export const setupPOIs = async ( toast, setShowPoiUpdateModal, setCurrentPoiData, - deviceName, + gisDevices, dispatch ) => { const editMode = localStorage.getItem("editMode") === "true"; @@ -45,9 +45,13 @@ export const setupPOIs = async ( for (const poi of pois) { try { + // console.log("👉 poi an Modal übergeben:", poi); + const { latitude, longitude } = parsePoint(poi.position); const poiTypName = poiTypMap.get(poi.idPoiTyp) || "Unbekannt"; const canDrag = userRights ? userRights.some(r => r.IdRight === 56) : false; + const matchingDevice = gisDevices.find(d => d.IdLD === poi.idLD); + const deviceLabel = matchingDevice?.LD_Name || "unbekannt"; // ✅ Icon korrekt über idPoi auflösen const iconPath = iconMap.get(poi.idPoi); @@ -97,7 +101,7 @@ export const setupPOIs = async ( `
${poi.description || "Unbekannt"}
-
Gerät: ${deviceName || "unbekannt"}
+
Gerät: ${deviceLabel || "unbekannt"}
Typ: ${poiTypName}
`, @@ -111,6 +115,7 @@ export const setupPOIs = async ( marker.on("mouseover", function () { dispatch(setSelectedPoi(poi)); + dispatch(setCurrentPoi(poi)); localStorage.setItem("lastElementType", "marker"); localStorage.setItem("markerLink", this.options.link); });