'use client' import { useState, useEffect, useRef, useCallback } from 'react' import { useTheme } from '@/lib/ThemeContext' import dynamic from 'next/dynamic' // Leaflet Komponente dynamisch laden (nur Client-Side) const CityMapLeaflet = dynamic( () => import('./CityMapLeaflet'), { ssr: false, loading: () => (
) } ) interface CityMapProps { bundesland: string bundeslandName: string selectedCity: string onSelectCity: (city: string, lat?: number, lng?: number) => void className?: string } // Bundesland-Zentren für initiale Kartenposition const bundeslandCenters: Record = { 'SH': { lat: 54.2, lng: 9.9, zoom: 8 }, 'HH': { lat: 53.55, lng: 10.0, zoom: 11 }, 'MV': { lat: 53.9, lng: 12.4, zoom: 8 }, 'HB': { lat: 53.1, lng: 8.8, zoom: 11 }, 'NI': { lat: 52.8, lng: 9.5, zoom: 7 }, 'BE': { lat: 52.52, lng: 13.4, zoom: 11 }, 'BB': { lat: 52.4, lng: 13.2, zoom: 8 }, 'ST': { lat: 51.9, lng: 11.7, zoom: 8 }, 'NW': { lat: 51.5, lng: 7.5, zoom: 8 }, 'HE': { lat: 50.6, lng: 9.0, zoom: 8 }, 'TH': { lat: 50.9, lng: 11.0, zoom: 8 }, 'SN': { lat: 51.1, lng: 13.2, zoom: 8 }, 'RP': { lat: 49.9, lng: 7.5, zoom: 8 }, 'SL': { lat: 49.4, lng: 7.0, zoom: 9 }, 'BW': { lat: 48.7, lng: 9.0, zoom: 8 }, 'BY': { lat: 48.8, lng: 11.5, zoom: 7 }, } export function CityMap({ bundesland, bundeslandName, selectedCity, onSelectCity, className = '' }: CityMapProps) { const { isDark } = useTheme() const [searchQuery, setSearchQuery] = useState(selectedCity || '') const [searchResults, setSearchResults] = useState([]) const [isSearching, setIsSearching] = useState(false) const [markerPosition, setMarkerPosition] = useState<[number, number] | null>(null) const searchTimeoutRef = useRef(null) const center = bundeslandCenters[bundesland] || { lat: 51.2, lng: 10.4, zoom: 6 } // Nominatim-Suche mit Debouncing const searchCity = useCallback(async (query: string) => { if (query.length < 2) { setSearchResults([]) return } setIsSearching(true) try { // Nominatim API für Geocoding (OpenStreetMap) const response = await fetch( `https://nominatim.openstreetmap.org/search?` + `q=${encodeURIComponent(query)}, ${bundeslandName}, Deutschland&` + `format=json&addressdetails=1&limit=8&countrycodes=de`, { headers: { 'Accept-Language': 'de', } } ) const data = await response.json() // Filtere nach relevanten Ergebnissen (Städte, Orte, Gemeinden) const filtered = data.filter((item: any) => item.type === 'city' || item.type === 'town' || item.type === 'village' || item.type === 'municipality' || item.type === 'administrative' || item.class === 'place' ) setSearchResults(filtered.length > 0 ? filtered : data.slice(0, 5)) } catch (error) { console.error('Geocoding error:', error) setSearchResults([]) } finally { setIsSearching(false) } }, [bundeslandName]) // Debounced Search useEffect(() => { if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current) } searchTimeoutRef.current = setTimeout(() => { searchCity(searchQuery) }, 400) return () => { if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current) } } }, [searchQuery, searchCity]) // Reverse Geocoding bei Kartenklick const handleMapClick = async (lat: number, lng: number) => { setMarkerPosition([lat, lng]) try { const response = await fetch( `https://nominatim.openstreetmap.org/reverse?` + `lat=${lat}&lon=${lng}&format=json&addressdetails=1`, { headers: { 'Accept-Language': 'de', } } ) const data = await response.json() // Extrahiere Stadt/Ort aus der Adresse const city = data.address?.city || data.address?.town || data.address?.village || data.address?.municipality || data.address?.county || 'Unbekannter Ort' setSearchQuery(city) onSelectCity(city, lat, lng) } catch (error) { console.error('Reverse geocoding error:', error) } } // Suchergebnis auswählen const handleSelectResult = (result: any) => { const cityName = result.address?.city || result.address?.town || result.address?.village || result.address?.municipality || result.display_name.split(',')[0] setSearchQuery(cityName) setMarkerPosition([parseFloat(result.lat), parseFloat(result.lon)]) onSelectCity(cityName, parseFloat(result.lat), parseFloat(result.lon)) setSearchResults([]) } // Manuelle Eingabe bestätigen const handleManualInput = () => { if (searchQuery.trim()) { onSelectCity(searchQuery.trim()) setSearchResults([]) } } return (
{/* Suchfeld */}
setSearchQuery(e.target.value)} onKeyDown={(e) => { if (e.key === 'Enter') { handleManualInput() } }} placeholder={`Stadt in ${bundeslandName} suchen...`} className={`w-full px-5 py-4 pl-12 text-lg rounded-2xl border transition-all ${ isDark ? 'bg-white/10 border-white/20 text-white placeholder-white/40 focus:border-blue-400' : 'bg-white border-slate-300 text-slate-900 placeholder-slate-400 focus:border-blue-500' } focus:outline-none focus:ring-2 focus:ring-blue-500/30`} /> {isSearching && (
)}
{/* Suchergebnisse Dropdown */} {searchResults.length > 0 && (
{searchResults.map((result, index) => ( ))}
)}
{/* Karte */}
{/* Hinweis */}

Tippen Sie den Namen ein oder klicken Sie auf die Karte

) }