diff --git a/components/MapComponent.js b/components/MapComponent.js index 70ec7a862..d9c7daaa0 100644 --- a/components/MapComponent.js +++ b/components/MapComponent.js @@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState, useCallback } from "react"; import L from "leaflet"; import "leaflet/dist/leaflet.css"; import "leaflet-contextmenu/dist/leaflet.contextmenu.css"; + import "leaflet-contextmenu"; import * as config from "../config/config.js"; import "leaflet.smooth_marker_bouncing"; @@ -736,18 +737,95 @@ const MapComponent = ({ locations, onLocationUpdate, lineCoordinates }) => { ref.current = new L.LayerGroup().addTo(map); } }); - - // Fügt das Suchfeld (Geocoder) zur Karte hinzu + //-------------------------------------------- + // Benutzerdefiniertes Icon erstellen für den Geocoder + const customIcon = L.icon({ + iconUrl: "/img/marker-icon.png", // Pfad zum Icon + iconSize: [32, 32], // Größe des Icons + iconAnchor: [16, 32], // Ankerpunkt (Mitte unten) + popupAnchor: [0, -32], // Popup-Ankerpunkt + }); + // Geocoder mit benutzerdefiniertem Icon verwenden const geocoder = L.Control.geocoder({ - position: "topleft", // Position des Suchfeldes - defaultMarkGeocode: false, // Deaktiviert den automatischen Marker + position: "topleft", + defaultMarkGeocode: false, + geocoder: new L.Control.Geocoder.Nominatim({ + serviceUrl: "https://nominatim.openstreetmap.org/", + geocodingQueryParams: { + "accept-language": "de", // Sprache auf Deutsch setzen + countrycodes: "DE", // Nur Ergebnisse aus Deutschland + }, + }), }) .on("markgeocode", function (e) { const latlng = e.geocode.center; - map.setView(latlng, 15); // Zoom zur Position - L.marker(latlng).addTo(map).bindPopup(e.geocode.name).openPopup(); // Marker hinzufügen + map.setView(latlng, 15); + + // Marker hinzufügen + L.marker(latlng, { icon: customIcon }).addTo(map).bindPopup(e.geocode.name).openPopup(); }) - .addTo(map); // Suchfeld zur Karte hinzufügen + .addTo(map); + + // Tailwind-Klassen dynamisch hinzufügen + setTimeout(() => { + // Geocoder-Container stylen + const geocoderContainer = document.querySelector(".leaflet-control-geocoder"); + if (geocoderContainer) { + // Nur minimale Klassen für Volle Breite und abgerundetes Design + geocoderContainer.classList.add( + "shadow-md", + "border", + "border-gray-300", + "rounded-full", + "bg-white", + "p-2", + "w-96" // Breite des gesamten Suchfeldes + ); + + // Alle anderen Elemente im Container entfernen außer Eingabefeld + Array.from(geocoderContainer.children).forEach((child) => { + if (!child.querySelector("input")) { + child.remove(); // Löscht alle Elemente außer dem Eingabefeld + } + }); + } + + // Eingabefeld stylen und Platzhaltertext setzen + const geocoderInput = document.querySelector(".leaflet-control-geocoder input"); + if (geocoderInput) { + geocoderInput.classList.add( + "border-none", + "outline-none", + "w-full", // Volle Breite nutzen + "text-sm", + "text-gray-700", + "pl-3" + ); + geocoderInput.placeholder = "Ort oder Adresse suchen..."; // Platzhalter auf Deutsch + } + + // Meldung "Nothing found." ausblenden + const noResultsMessage = document.querySelector(".leaflet-control-geocoder-form-no-error"); + if (noResultsMessage) { + noResultsMessage.style.display = "none"; // Verstecke die Meldung + } + + // Alternativen (falls leer) ebenfalls ausblenden + const observer = new MutationObserver(() => { + const alternatives = document.querySelector(".leaflet-control-geocoder-alternatives"); + if (alternatives && alternatives.children.length === 0) { + alternatives.style.display = "none"; // Verstecke die Liste, wenn keine Vorschläge vorhanden sind + } + }); + + // Beobachte Änderungen im Geocoder-Container + const targetNode = document.querySelector(".leaflet-control-geocoder"); + if (targetNode) { + observer.observe(targetNode, { childList: true, subtree: true }); + } + }, 100); + + //-------------------------------------------- const updateMarkers = ({ ref, id, setState }) => { if (ref.current) { diff --git a/pages/_app.js b/pages/_app.js index 1a2213940..6102bc0e5 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -4,6 +4,7 @@ import { RecoilRoot } from "recoil"; import { Provider } from "react-redux"; import store from "../redux/store"; import "../styles/global.css"; +//import "../public/css/geocoder.css"; function MyApp({ Component, pageProps }) { return ( diff --git a/public/css/geocoder.css b/public/css/geocoder.css new file mode 100644 index 000000000..f20fc1ad2 --- /dev/null +++ b/public/css/geocoder.css @@ -0,0 +1,42 @@ +.leaflet-control-geocoder { + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Weicher Schatten */ + border: 1px solid #d9d9d9; /* Heller Rand */ + border-radius: 20px; /* Abgerundete Ecken für Google Maps Look */ + padding: 5px 10px; /* Innenabstand */ + font-size: 14px; /* Schriftgröße */ + font-family: Arial, sans-serif; /* Schriftart */ + width: 300px; /* Breite des Suchfeldes */ + background-color: #fff; /* Hintergrundfarbe */ + display: flex; /* Flexbox für Icon-Ausrichtung */ + align-items: center; /* Zentrierte Inhalte */ +} + +.leaflet-control-geocoder input { + border: none; /* Kein Rand für das Eingabefeld */ + outline: none; /* Kein Fokus-Rahmen */ + width: 100%; /* Volle Breite */ + font-size: 14px; /* Schriftgröße */ + color: #333; /* Textfarbe */ + padding-left: 10px; /* Abstand vom Rand */ +} + +.leaflet-control-geocoder input::placeholder { + color: #757575; /* Platzhalter-Farbe */ +} + +.leaflet-control-geocoder-icon { + background-color: transparent; /* Kein Hintergrund */ + border: none; /* Kein Rand */ + cursor: pointer; /* Zeiger beim Überfahren */ + margin-right: 5px; /* Abstand zum Textfeld */ +} + +.leaflet-control-geocoder-icon img { + width: 20px; /* Icon-Größe */ + height: 20px; +} + +/* Alternative Ergebnisse verbergen */ +.leaflet-control-geocoder-alternatives { + display: none; +}