import { useContext, useMemo, useState } from 'react' import { Marker, Tooltip } from 'react-leaflet' import { useAppState } from '#components/AppShell/hooks/useAppState' import { useFilterTags, useIsLayerVisible, useIsGroupTypeVisible, useVisibleGroupType, useAllVisibleLayersInitialized, } from '#components/Map/hooks/useFilter' import { useItems } from '#components/Map/hooks/useItems' import { useAddMarker, useAddPopup, useLeafletRefs } from '#components/Map/hooks/useLeafletRefs' import { useSetMarkerClicked, useSelectPosition } from '#components/Map/hooks/useSelectPosition' import { useGetItemTags, useAllTagsLoaded, useTags } from '#components/Map/hooks/useTags' import LayerContext from '#components/Map/LayerContext' import { ItemViewPopup } from '#components/Map/Subcomponents/ItemViewPopup' import { encodeTag } from '#utils/FormatTags' import { hashTagRegex } from '#utils/HashTagRegex' import MarkerIconFactory from '#utils/MarkerIconFactory' import { randomColor } from '#utils/RandomColor' import TemplateItemContext from './TemplateItemContext' import type { Item } from '#types/Item' import type { Tag } from '#types/Tag' import type { Popup } from 'leaflet' /** * @category Item */ export const PopupView = ({ children }: { children?: React.ReactNode }) => { const layerContext = useContext(LayerContext) const { name, markerDefaultColor, markerDefaultColor2, markerShape, markerIcon } = layerContext const filterTags = useFilterTags() const appState = useAppState() const items = useItems() const getItemTags = useGetItemTags() const addMarker = useAddMarker() const addPopup = useAddPopup() const leafletRefs = useLeafletRefs() const allTagsLoaded = useAllTagsLoaded() const allVisibleLayersInitialized = useAllVisibleLayersInitialized() const setMarkerClicked = useSetMarkerClicked() const selectPosition = useSelectPosition() const tags = useTags() const [newTagsToAdd, setNewTagsToAdd] = useState([]) const [tagsReady, setTagsReady] = useState(false) const isLayerVisible = useIsLayerVisible() const isGroupTypeVisible = useIsGroupTypeVisible() const visibleGroupTypes = useVisibleGroupType() const visibleItems = useMemo( () => items .filter((item) => item.layer?.name === name) .filter((item) => filterTags.length === 0 ? item : filterTags.some((tag) => getItemTags(item).some( (filterTag) => filterTag.name.toLocaleLowerCase() === tag.name.toLocaleLowerCase(), ), ), ) .filter((item) => item.layer && isLayerVisible(item.layer)) .filter( (item) => (item.group_type && isGroupTypeVisible(item.group_type)) || visibleGroupTypes.length === 0, ), [ filterTags, getItemTags, isGroupTypeVisible, isLayerVisible, items, name, visibleGroupTypes.length, ], ) return visibleItems.map((item: Item) => { if (!(item.position?.coordinates[0] && item.position.coordinates[1])) return null if (item.tags) { item.text += '\n\n' item.tags.map((tag) => { if (!item.text?.includes(`#${encodeTag(tag)}`)) { item.text += `#${encodeTag(tag)}` } return item.text }) } if (allTagsLoaded && allVisibleLayersInitialized) { item.text?.match(hashTagRegex)?.map((tag) => { if ( !tags.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) && !newTagsToAdd.find((t) => t.name.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()) ) { const newTag = { id: crypto.randomUUID(), name: tag.slice(1), color: randomColor(), } setNewTagsToAdd((current) => [...current, newTag]) } return null }) !tagsReady && setTagsReady(true) } const itemTags = getItemTags(item) const latitude = item.position.coordinates[1] const longitude = item.position.coordinates[0] let color1 = markerDefaultColor let color2 = markerDefaultColor2 if (item.color) { color1 = item.color } else if (itemTags[0]) { color1 = itemTags[0].color } if (itemTags[0] && item.color) { color2 = itemTags[0].color } else if (itemTags[1]) { color2 = itemTags[1].color } return ( { if (!(item.id in leafletRefs && leafletRefs[item.id].marker === r)) { r && addMarker(item, r) } }} eventHandlers={{ click: () => { selectPosition && setMarkerClicked(item) }, }} icon={MarkerIconFactory( markerShape, color1, color2, item.markerIcon ?? markerIcon, appState.assetsApi.url, )} position={[latitude, longitude]} > { if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) { r && addPopup(item, r) } }} item={item} > {children} {item.name} ) }) }