Gängige Praxis: *Slice.js Verwendung: Wenn du Redux Toolkit und createSlice nutzt, ist der Postfix Slice gängiger. Begründung: createSlice ist ein Begriff aus Redux Toolkit. Der Name vermittelt, dass die Datei nicht nur den Reducer enthält, sondern auch Aktionen und den initialen Zustand. Häufig in modernen Projekten verwendet.
218 lines
7.4 KiB
JavaScript
218 lines
7.4 KiB
JavaScript
// components/pois/AddPoiModalWindow.js
|
|
import React, { useState, useEffect } from "react";
|
|
import Select from "react-select"; // Importiere react-select
|
|
import { useSetRecoilState, useRecoilState } from "recoil";
|
|
import { mapLayersState } from "../../redux/slices/mapLayersSlice";
|
|
import { poiReadFromDbTriggerAtom } from "../../redux/slices/poiReadFromDbTriggerSlice";
|
|
|
|
const AddPoiModalWindow = ({ onClose, map, latlng }) => {
|
|
const [poiTypData, setpoiTypData] = useState([]);
|
|
const [name, setName] = useState("");
|
|
const [poiTypeId, setPoiTypeId] = useState(null); // Verwende null für react-select
|
|
const [latitude] = useState(latlng.lat.toFixed(5));
|
|
const [longitude] = useState(latlng.lng.toFixed(5));
|
|
const setTrigger = useSetRecoilState(poiReadFromDbTriggerAtom); // Verwende useSetRecoilState
|
|
const [locationDeviceData, setLocationDeviceData] = useState([]);
|
|
const [filteredDevices, setFilteredDevices] = useState([]); // Gefilterte Geräte
|
|
const [deviceName, setDeviceName] = useState(null); // Verwende null für react-select
|
|
const [mapLayersVisibility] = useRecoilState(mapLayersState); // Um die aktiven Layer zu erhalten
|
|
|
|
// Map von Systemnamen zu ids (wie zuvor)
|
|
const systemNameToIdMap = {
|
|
TALAS: 1,
|
|
ECI: 2,
|
|
ULAF: 3,
|
|
GSMModem: 5,
|
|
CiscoRouter: 6,
|
|
WAGO: 7,
|
|
Siemens: 8,
|
|
OTDR: 9,
|
|
WDM: 10,
|
|
GMA: 11,
|
|
Messdatensammler: 12,
|
|
Messstellen: 13,
|
|
TALASICL: 100,
|
|
DAUZ: 110,
|
|
SMSFunkmodem: 111,
|
|
Basisgerät: 200,
|
|
};
|
|
|
|
// API-Abfrage, um die Geräte zu laden
|
|
useEffect(() => {
|
|
const fetchInitialData = async () => {
|
|
try {
|
|
const [poiTypResponse, locationDeviceResponse] = await Promise.all([fetch("/api/talas_v5_DB/poiTyp/readPoiTyp"), fetch("/api/talas5/location_device")]);
|
|
|
|
const poiTypData = await poiTypResponse.json();
|
|
setpoiTypData(poiTypData);
|
|
|
|
const locationDeviceData = await locationDeviceResponse.json();
|
|
console.log("Geräte von der API:", locationDeviceData); // Geräte-Daten aus der API anzeigen
|
|
setLocationDeviceData(locationDeviceData);
|
|
|
|
// Filtere die Geräte basierend auf den sichtbaren Systemen
|
|
filterDevices(locationDeviceData);
|
|
} catch (error) {
|
|
console.error("Fehler beim Abrufen der Daten:", error);
|
|
}
|
|
};
|
|
|
|
fetchInitialData();
|
|
}, []);
|
|
|
|
// Funktion zum Filtern der Geräte basierend auf den aktiven Systemen (Layern)
|
|
const filterDevices = (devices) => {
|
|
const activeSystems = Object.keys(mapLayersVisibility).filter((system) => mapLayersVisibility[system]);
|
|
console.log("Aktive Systeme:", activeSystems); // Anzeigen der aktiven Systeme
|
|
|
|
// Mappe aktive Systeme auf ihre ids
|
|
const activeSystemIds = activeSystems.map((system) => systemNameToIdMap[system]).filter((id) => id !== undefined);
|
|
console.log("Aktive System-IDs:", activeSystemIds); // Anzeigen der aktiven System-IDs
|
|
|
|
// Filtere die Geräte nach aktiven Systemen basierend auf idsystem_typ
|
|
const filtered = devices.filter((device) => activeSystemIds.includes(device.idsystem_typ));
|
|
console.log("Gefilterte Geräte:", filtered); // Gefilterte Geräte anzeigen
|
|
|
|
setFilteredDevices(filtered); // Setze die gefilterten Geräte
|
|
};
|
|
|
|
// Wenn mapLayersVisibility sich ändert, filtere die Geräte erneut
|
|
useEffect(() => {
|
|
if (locationDeviceData.length > 0) {
|
|
filterDevices(locationDeviceData);
|
|
}
|
|
}, [mapLayersVisibility, locationDeviceData]);
|
|
|
|
const handleSubmit = async (event) => {
|
|
event.preventDefault();
|
|
|
|
if (!poiTypeId) {
|
|
alert("Bitte wählen Sie einen Typ aus.");
|
|
return;
|
|
}
|
|
|
|
const formData = {
|
|
name,
|
|
poiTypeId: poiTypeId.value,
|
|
latitude,
|
|
longitude,
|
|
idLD: filteredDevices.find((device) => device.name === deviceName?.value).idLD,
|
|
};
|
|
|
|
const response = await fetch("/api/talas_v5_DB/pois/addLocation", {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify(formData),
|
|
});
|
|
|
|
if (response.ok) {
|
|
setTrigger((trigger) => trigger + 1); // Verwenden des Triggers zur Aktualisierung
|
|
onClose();
|
|
window.location.reload();
|
|
} else {
|
|
console.error("Fehler beim Hinzufügen des POI");
|
|
}
|
|
|
|
if (map && typeof map.closePopup === "function") {
|
|
map.closePopup();
|
|
}
|
|
};
|
|
|
|
// Erstelle Optionen für react-select
|
|
const poiTypeOptions = poiTypData.map((poiTyp) => ({
|
|
value: poiTyp.idPoiTyp,
|
|
label: poiTyp.name,
|
|
}));
|
|
|
|
const deviceOptions = filteredDevices.map((device) => ({
|
|
value: device.name,
|
|
label: device.name,
|
|
}));
|
|
|
|
// Custom styles for react-select
|
|
const customStyles = {
|
|
control: (provided) => ({
|
|
...provided,
|
|
width: "100%",
|
|
minWidth: "300px", // Minimum width for the dropdown
|
|
maxWidth: "100%", // Maximum width (you can adjust this if needed)
|
|
}),
|
|
menu: (provided) => ({
|
|
...provided,
|
|
width: "100%",
|
|
minWidth: "300px", // Ensure the dropdown menu stays at the minimum width
|
|
}),
|
|
};
|
|
|
|
// Style für größere Breite des Modals und für Inputs
|
|
const modalStyles = {
|
|
// width: "300px", // größere Breite für das Modal
|
|
//maxWidth: "100%", // responsive, passt sich an
|
|
//padding: "20px", // Polsterung für das Modal
|
|
//backgroundColor: "white", // Hintergrundfarbe
|
|
//borderRadius: "8px", // Abgerundete Ecken
|
|
//boxShadow: "0px 4px 12px rgba(0, 0, 0, 0.1)", // Schatten für das Modal
|
|
};
|
|
|
|
return (
|
|
<form onSubmit={handleSubmit} style={modalStyles} className="m-0 p-2 w-full">
|
|
<div className="flex flex-col mb-4">
|
|
<label htmlFor="name" className="block mb-2 font-bold text-sm text-gray-700">
|
|
Beschreibung :
|
|
</label>
|
|
<input type="text" id="name" value={name} onChange={(e) => setName(e.target.value)} className="block p-2 w-full border-2 border-gray-200 rounded-md text-sm" />
|
|
</div>
|
|
|
|
{/* React Select for Devices */}
|
|
<div className="flex flex-col mb-4">
|
|
<label htmlFor="deviceName" className="block mb-2 font-bold text-sm text-gray-700">
|
|
Gerät :
|
|
</label>
|
|
<Select
|
|
id="deviceName"
|
|
value={deviceName}
|
|
onChange={setDeviceName}
|
|
options={deviceOptions}
|
|
placeholder="Gerät auswählen..."
|
|
isClearable
|
|
styles={customStyles} // Apply custom styles here
|
|
/>
|
|
</div>
|
|
|
|
{/* React Select for POI Types */}
|
|
<div className="flex flex-col mb-4">
|
|
<label htmlFor="idPoiTyp" className="block mb-2 font-bold text-sm text-gray-700">
|
|
Typ:
|
|
</label>
|
|
<Select
|
|
id="idPoiTyp"
|
|
value={poiTypeId}
|
|
onChange={setPoiTypeId}
|
|
options={poiTypeOptions}
|
|
placeholder="Typ auswählen..."
|
|
styles={customStyles} // Apply custom styles here
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex flex-row items-center justify-between mb-4">
|
|
<div className="flex flex-col items-center">
|
|
<label htmlFor="lat" className="block mb-2 text-xs text-gray-700">
|
|
Lat : {latitude}
|
|
</label>
|
|
</div>
|
|
<div className="flex flex-col items-center">
|
|
<label htmlFor="lng" className="block mb-2 text-xs text-gray-700">
|
|
Lng : {longitude}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full">
|
|
POI hinzufügen
|
|
</button>
|
|
</form>
|
|
);
|
|
};
|
|
|
|
export default AddPoiModalWindow;
|