Files
nodeMap/components/pois/PoiUpdateModal.js
ISA c85b0ee0ba Postfix *Slice.js in slices folder
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.
2024-12-18 21:12:53 +01:00

257 lines
9.6 KiB
JavaScript

// /components/pois/PoiUpdateModal.js
import React, { useState, useEffect } from "react";
import Select from "react-select"; // Importiere react-select
import { useRecoilState } from "recoil";
import { selectedPoiState } from "../../redux/slices/selectedPoiSlice";
import { currentPoiState } from "../../redux/slices/currentPoiSlice";
import { mapLayersState } from "../../redux/slices/mapLayersSlice";
const PoiUpdateModal = ({ onClose, poiData, onSubmit }) => {
const currentPoi = useRecoilState(currentPoiState);
const selectedPoi = useRecoilState(selectedPoiState);
const [mapLayersVisibility] = useRecoilState(mapLayersState);
const [poiId, setPoiId] = useState(poiData ? poiData.idPoi : "");
const [name, setName] = useState(poiData ? poiData.name : "");
const [poiTypData, setPoiTypData] = useState([]);
const [poiTypeId, setPoiTypeId] = useState(null); // Verwende null für react-select
const [locationDeviceData, setLocationDeviceData] = useState([]);
const [filteredDevices, setFilteredDevices] = useState([]);
const [deviceName, setDeviceName] = useState(poiData ? poiData.deviceName : null); // Verwende null für react-select
const [idLD, setIdLD] = useState(poiData ? poiData.idLD : "");
const [description, setDescription] = useState(poiData ? poiData.description : "");
// 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,
};
useEffect(() => {
if (poiData) {
setPoiId(poiData.idPoi);
setName(poiData.name);
setPoiTypeId(poiData.idPoiTyp); // Setze den Typ-ID
setIdLD(poiData.idLD);
setDescription(poiData.description);
}
}, [poiData]);
// Fetch POI types and set the current POI type in the react-select dropdown
useEffect(() => {
const fetchPoiTypData = async () => {
try {
const response = await fetch("/api/talas_v5_DB/poiTyp/readPoiTyp");
const data = await response.json();
setPoiTypData(data);
// Prüfe den gespeicherten Typ im localStorage
const storedPoiType = localStorage.getItem("selectedPoiType");
// Finde den passenden Typ in den abgerufenen Daten und setze ihn als ausgewählt
if (storedPoiType) {
const matchingType = data.find((type) => type.name === storedPoiType);
if (matchingType) {
setPoiTypeId({ value: matchingType.idPoiTyp, label: matchingType.name });
}
} else if (poiData && poiData.idPoiTyp) {
// Falls kein Typ im localStorage ist, setze den Typ von poiData
const matchingType = data.find((type) => type.idPoiTyp === poiData.idPoiTyp);
if (matchingType) {
setPoiTypeId({ value: matchingType.idPoiTyp, label: matchingType.name });
}
}
} catch (error) {
console.error("Fehler beim Abrufen der poiTyp Daten:", error);
}
};
fetchPoiTypData();
}, [poiData]);
// Fetch location devices and pre-select the current device
useEffect(() => {
const fetchLocationDevices = async () => {
try {
const response = await fetch("/api/talas5/location_device");
const data = await response.json();
setLocationDeviceData(data);
filterDevices(data);
if (poiData && poiData.idLD) {
const selectedDevice = data.find((device) => device.idLD === poiData.idLD);
setDeviceName(selectedDevice ? { value: selectedDevice.name, label: selectedDevice.name } : null);
}
} catch (error) {
console.error("Fehler beim Abrufen der Standort- und Gerätedaten:", error);
}
};
fetchLocationDevices();
}, [poiData]);
// Funktion zum Filtern der Geräte basierend auf den aktiven Systemen (Layern)
const filterDevices = (devices) => {
const activeSystems = Object.keys(mapLayersVisibility).filter((system) => mapLayersVisibility[system]);
// Mappe aktive Systeme auf ihre ids
const activeSystemIds = activeSystems.map((system) => systemNameToIdMap[system]).filter((id) => id !== undefined);
// Filtere die Geräte nach aktiven Systemen basierend auf idsystem_typ
const filtered = devices.filter((device) => activeSystemIds.includes(device.idsystem_typ));
setFilteredDevices(filtered);
};
const handleSubmit = async (event) => {
event.preventDefault();
const idLDResponse = await fetch(`/api/talas_v5_DB/locationDevice/getDeviceId?deviceName=${encodeURIComponent(deviceName?.value)}`);
const idLDData = await idLDResponse.json();
const idLD = idLDData.idLD;
try {
const response = await fetch("/api/talas_v5_DB/pois/updatePoi", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
idPoi: poiId,
name: name,
description: description,
idPoiTyp: poiTypeId?.value, // Den ausgewählten Typ mitsenden
idLD: idLD,
}),
});
if (response.ok) {
onClose();
window.location.reload();
} else {
const errorResponse = await response.json();
throw new Error(errorResponse.error || "Fehler beim Aktualisieren des POI.");
}
} 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 {
const response = await fetch(`/api/talas_v5_DB/pois/deletePoi?id=${poiId}`, {
method: "DELETE",
});
if (response.ok) {
onClose();
window.location.reload(); // Aktualisiert die Seite nach dem Löschen
} else {
throw new Error("Fehler beim Löschen des POI.");
}
} catch (error) {
console.error("Fehler beim Löschen des POI:", error);
alert("Fehler beim Löschen des POI.");
}
}
};
// 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
}),
};
return (
<div className="fixed inset-0 bg-black bg-opacity-10 flex justify-center items-center z-[1000]" onClick={onClose}>
<div className="relative bg-white p-6 rounded-lg shadow-lg" onClick={(e) => e.stopPropagation()}>
<button onClick={onClose} className="absolute top-0 right-0 mt-2 mr-2 p-1 text-gray-700 hover:text-gray-900 focus:outline-none focus:ring-2 focus:ring-gray-600" aria-label="Close">
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<form onSubmit={handleSubmit} className="m-0 p-2 w-full">
<div className="flex flex-col mb-4">
<label htmlFor="description" className="block mb-2 font-bold text-sm text-gray-700">
Beschreibung:
</label>
<input type="text" id="description" name="description" value={description} onChange={(e) => setDescription(e.target.value)} placeholder="Beschreibung der Station" 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} // Options for filtering
placeholder="Gerät auswählen..."
isClearable={true} // Allow clearing the selection
styles={customStyles} // Apply custom styles
/>
</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} // Options for filtering
placeholder="Typ auswählen..."
isClearable={true}
styles={customStyles} // Apply custom styles
/>
</div>
<button type="button" onClick={handleDeletePoi} className="bg-red-400 hover:bg-red-600 text-white font-bold py-2 px-4 rounded w-full mb-4">
POI löschen
</button>
<button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full">
POI aktualisieren
</button>
</form>
</div>
</div>
);
};
export default PoiUpdateModal;