import * as React from 'react' import { useAddFilterTag } from '../../hooks/useFilter' import useWindowDimensions from '../../hooks/useWindowDimension'; import axios from 'axios'; import { useEffect, useRef, useState } from 'react'; import { useMap, useMapEvents } from 'react-leaflet'; import { LatLng, LatLngBounds } from 'leaflet'; import { useDebounce } from '../../hooks/useDebounce'; import { useTags } from '../../hooks/useTags'; import { useItems } from '../../hooks/useItems'; import { useLeafletRefs } from '../../hooks/useLeafletRefs'; import { getValue } from '../../../../Utils/GetValue'; import { LocateControl } from './LocateControl'; import * as L from 'leaflet'; import MarkerIconFactory from '../../../../Utils/MarkerIconFactory'; import { decodeTag } from '../../../../Utils/FormatTags'; import { useLocation, useNavigate } from 'react-router-dom'; import { Item } from '../../../../types'; import { SidebarControl } from './SidebarControl'; export const SearchControl = () => { const windowDimensions = useWindowDimensions(); const [popupOpen, setPopupOpen] = useState(false); const [value, setValue] = useState(''); const [geoResults, setGeoResults] = useState>([]); const [tagsResults, setTagsResults] = useState>([]); const [itemsResults, setItemsResults] = useState>([]); const [hideSuggestions, setHideSuggestions] = useState(true); const map = useMap(); const tags = useTags(); const items = useItems(); const leafletRefs = useLeafletRefs(); const addFilterTag = useAddFilterTag(); useMapEvents({ popupopen: () => { setPopupOpen(true); }, popupclose: () => { setPopupOpen(false); } }) const navigate = useNavigate(); useDebounce(() => { const searchGeo = async () => { try { const { data } = await axios.get( `https://photon.komoot.io/api/?q=${value}&limit=5` ); setGeoResults(data.features); } catch (error) { console.log(error); } }; searchGeo(); setItemsResults(items.filter(item => { if (item.layer?.itemNameField) item.name = getValue(item, item.layer.itemNameField) if (item.layer?.itemTextField) item.text = getValue(item, item.layer.itemTextField) return value.length > 2 && ((item.layer?.listed && item.name?.toLowerCase().includes(value.toLowerCase()) || item.text?.toLowerCase().includes(value.toLowerCase()))) })) let phrase = value; if (value.startsWith("#")) phrase = value.substring(1); setTagsResults(tags.filter(tag => tag.name?.toLowerCase().includes(phrase.toLowerCase()))) }, 500, [value]); const hide = async () => { setTimeout(() => { setHideSuggestions(true); }, 200); } const searchInput = useRef(null); const [embedded, setEmbedded] = useState(true) const location = useLocation(); useEffect(() => { const params = new URLSearchParams(location.search); const embedded = params.get("embedded"); embedded != "true" && setEmbedded(false) }, [location]); return (<> {!(windowDimensions.height < 500 && popupOpen && hideSuggestions) &&
{embedded && }
setValue(e.target.value)} onFocus={() => { setHideSuggestions(false); if (windowDimensions.width < 500) map.closePopup(); }} onBlur={() => hide()} /> {value.length > 0 && }
{hideSuggestions || Array.from(geoResults).length == 0 && itemsResults.length == 0 && tagsResults.length == 0 && !isGeoCoordinate(value) || value.length == 0 ? "" :
{tagsResults.length > 0 &&
{tagsResults.slice(0, 3).map(tag => (
{ addFilterTag(tag) }}> #{decodeTag(tag.name)}
))}
} {itemsResults.length > 0 && tagsResults.length > 0 &&
} {itemsResults.slice(0, 5).map(item => (
{ const marker = Object.entries(leafletRefs).find(r => r[1].item == item)?.[1].marker; if (marker) { navigate(`/${item.id}?${new URLSearchParams(window.location.search)}`) } else { navigate("item/" + item.id + "?" + new URLSearchParams(window.location.search)) } } }>
{item.name}
{item.text}
))} {Array.from(geoResults).length > 0 && (itemsResults.length > 0 || tagsResults.length > 0) &&
} {Array.from(geoResults).map((geo) => (
{ searchInput.current?.blur(); L.marker(new LatLng(geo.geometry.coordinates[1], geo.geometry.coordinates[0]), { icon: MarkerIconFactory("circle", "#777", "RGBA(35, 31, 32, 0.2)", "point") }).addTo(map).bindPopup(`

${geo?.properties.name ? geo?.properties.name : value}

${capitalizeFirstLetter(geo?.properties?.osm_value)}`).openPopup().addEventListener("popupclose", (e) => { console.log(e.target.remove()) }); if (geo.properties.extent) map.fitBounds(new LatLngBounds(new LatLng(geo.properties.extent[1], geo.properties.extent[0]), new LatLng(geo.properties.extent[3], geo.properties.extent[2]))); else map.setView(new LatLng(geo.geometry.coordinates[1], geo.geometry.coordinates[0]), 15, { duration: 1 }); hide(); }}>
{geo?.properties.name ? geo?.properties.name : value}
{geo?.properties?.city && `${capitalizeFirstLetter(geo?.properties?.city)}, `} {geo?.properties?.osm_value && geo?.properties?.osm_value !== "yes" && geo?.properties?.osm_value !== "primary" && geo?.properties?.osm_value !== "path" && geo?.properties?.osm_value !== "secondary" && geo?.properties?.osm_value !== "residential" && geo?.properties?.osm_value !== "unclassified" && `${capitalizeFirstLetter(geo?.properties?.osm_value)}, `} {geo.properties.state && `${geo.properties.state}, `} {geo.properties.country && geo.properties.country}

))} {isGeoCoordinate(value) &&
{ L.marker(new LatLng(extractCoordinates(value)![0], extractCoordinates(value)![1]), { icon: MarkerIconFactory("circle", "#777", "RGBA(35, 31, 32, 0.2)", "point") }).addTo(map).bindPopup(`

${extractCoordinates(value)![0]}, ${extractCoordinates(value)![1]}

`).openPopup().addEventListener("popupclose", (e) => { console.log(e.target.remove()) }); map.setView(new LatLng(extractCoordinates(value)![0], extractCoordinates(value)![1]), 15, { duration: 1 }) }}>
{value}
{"Coordiante"}
}
}
} ) } function isGeoCoordinate(input) { const geokoordinatenRegex = /^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/; return geokoordinatenRegex.test(input); } function extractCoordinates(input): number[] | null { const result = input.split(",") if (result) { const latitude = parseFloat(result[0]); const longitude = parseFloat(result[1]); if (!isNaN(latitude) && !isNaN(longitude)) { return [latitude, longitude]; } } return null; // Invalid input or error } function capitalizeFirstLetter(string) { return string.charAt(0).toUpperCase() + string.slice(1); }