import React, { useState, useMemo, useEffect, useCallback } from 'react'; import { useConfigContext } from '../../contexts/ConfigContext'; import MapView from '../map/MapView'; import FilterPanel from '../users/FilterPanel'; import { calculateDistance } from '../../utils/helpers'; import { getGeocodeByPostalCode } from '../../services/users'; import './PublicUserList.css'; const PublicUserList = ({ users, loading, onRefetch }) => { const { userTypeLabels } = useConfigContext(); // Load saved location from localStorage on mount const savedLocation = localStorage.getItem('userLocation'); const initialCoords = savedLocation ? JSON.parse(savedLocation) : null; const [showMap, setShowMap] = useState(true); const [showFilters, setShowFilters] = useState(false); const [locationStatus, setLocationStatus] = useState(initialCoords ? 'granted' : 'idle'); const [locationError, setLocationError] = useState(''); const [coords, setCoords] = useState(initialCoords); const [radiusKm, setRadiusKm] = useState(100); const [postalCode, setPostalCode] = useState(''); const [postalSearching, setPostalSearching] = useState(false); const [filters, setFilters] = useState({ type: null, sortBy: 'name' }); // Save location to localStorage whenever it changes useEffect(() => { if (coords) { localStorage.setItem('userLocation', JSON.stringify(coords)); } }, [coords]); const handleFilterChange = useCallback((key, value) => { setFilters(prev => ({ ...prev, [key]: value })); }, []); // Re-fetch from backend when type filter changes (server-side filtering) useEffect(() => { if (onRefetch) { onRefetch(filters.type ? { type: filters.type } : {}); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [filters.type]); const requestLocation = () => { if (!navigator.geolocation) { return; } setLocationStatus('requesting'); setLocationError(''); navigator.geolocation.getCurrentPosition( (position) => { setCoords({ lat: position.coords.latitude, lng: position.coords.longitude }); setLocationStatus('granted'); }, () => { setLocationStatus('idle'); }, { enableHighAccuracy: true, timeout: 15000, maximumAge: 0 } ); }; const searchByPostalCode = async () => { if (!postalCode || postalCode.trim().length < 4) { setLocationError('Bitte geben Sie eine gültige Postleitzahl ein'); return; } setPostalSearching(true); setLocationError(''); const result = await getGeocodeByPostalCode(postalCode.trim()); if (result.success) { setCoords({ lat: result.data.lat, lng: result.data.lng }); setLocationStatus('granted'); setLocationError(''); } else { setLocationError(result.message || 'Fehler bei der PLZ-Suche'); } setPostalSearching(false); }; const { list: filteredAndSortedUsers, missingGpsCount, allUsersWithGPS } = useMemo(() => { let filtered = [...users]; const missingGps = filtered.filter(user => !(user.gps && user.gps.lat && user.gps.lng)).length; // Alle Benutzer mit GPS für die Karte (vor Radius-Filterung) const allWithGPS = filtered.filter(user => user.gps && user.gps.lat && user.gps.lng); if (coords) { const withDistance = filtered .filter(user => user.gps && user.gps.lat && user.gps.lng) .map(user => ({ ...user, distanceKm: calculateDistance( coords.lat, coords.lng, user.gps.lat, user.gps.lng ) })) .filter(user => user.distanceKm <= radiusKm) .sort((a, b) => a.distanceKm - b.distanceKm); return { list: withDistance, missingGpsCount: missingGps, allUsersWithGPS: allWithGPS }; } // Sort by name/type when no location filtered.sort((a, b) => { switch (filters.sortBy) { case 'nameDesc': return b.name.localeCompare(a.name); case 'type': return a.type.localeCompare(b.type); case 'name': default: return a.name.localeCompare(b.name); } }); return { list: filtered, missingGpsCount: missingGps, allUsersWithGPS: allWithGPS }; }, [users, filters, coords, radiusKm]); if (loading) { return
Derzeit sind keine Nachsuchenführer verfügbar.
Standort wird nur im Browser genutzt und nicht gespeichert.
Keine Nachsuchenführer im gewählten Radius gefunden.
Nachsuchenführer
{user.distanceKm !== undefined && (