import * as React from 'react' import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet' import { Item, LayerProps, Tag } from '../../types' import MarkerIconFactory from '../../Utils/MarkerIconFactory' import { ItemViewPopup } from './Subcomponents/ItemViewPopup' import { useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems' import { useEffect, useState } from 'react' import { ItemFormPopup } from './Subcomponents/ItemFormPopup' import { useFilterTags, useIsLayerVisible } from './hooks/useFilter' import { useAddTag, useAllTagsLoaded, useGetItemTags, useTags } from './hooks/useTags' import { useAddMarker, useAddPopup, useLeafletRefs } from './hooks/useLeafletRefs' import { Popup } from 'leaflet' import { useLocation } from 'react-router-dom'; import { getValue } from '../../Utils/GetValue' import { hashTagRegex } from '../../Utils/HashTagRegex' import { randomColor } from '../../Utils/RandomColor' export const Layer = ({ data, children, name = 'places', menuIcon = 'MapPinIcon', menuText = 'add new place', menuColor = '#2E7D32', markerIcon = 'circle-solid', markerShape = 'circle', markerDefaultColor = '#777', api, itemNameField = 'name', itemTextField = 'text', itemAvatarField, itemColorField, itemOwnerField, itemLatitudeField = 'position.coordinates.1', itemLongitudeField = 'position.coordinates.0', onlyOnePerOwner = false, setItemFormPopup, itemFormPopup, clusterRef }: LayerProps) => { const filterTags = useFilterTags(); const items = useItems(); const setItemsApi = useSetItemsApi(); const setItemsData = useSetItemsData(); const getItemTags = useGetItemTags(); const addMarker = useAddMarker(); const addPopup = useAddPopup(); const leafletRefs = useLeafletRefs(); let location = useLocation(); const allTagsLoaded = useAllTagsLoaded(); const tags = useTags(); const addTag = useAddTag(); const [newTagsToAdd, setNewTagsToAdd] = useState([]); const [tagsReady, setTagsReady] = useState(false); const map = useMap(); const isLayerVisible = useIsLayerVisible(); useEffect(() => { data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef }); api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef }); }, [data, api]) useMapEvents({ popupopen: (e) => { const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item; if (item?.layer?.name == name && window.location.pathname.split("/")[2] != item.id) { window.history.pushState({}, "", `/${name}/${item.id}`) let title = ""; if (item.name) title = item.name; else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField); document.title = `${document.title.split("-")[0]} - ${title}`; } }, }) const openPopup = () => { if (window.location.pathname.split("/").length <= 2 || window.location.pathname.split("/")[2] === "") { map.closePopup(); } else { if (window.location.pathname.split("/")[1] == name) { if (window.location.pathname.split("/")[2]) { const id = window.location.pathname.split("/")[2] const marker = leafletRefs[id]?.marker; if (marker && marker != null) { marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => { marker.openPopup(); }); const item = leafletRefs[id]?.item; let title = ""; if (item.name) title = item.name; else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField); document.title = `${document.title.split("-")[0]} - ${title}`; document.querySelector('meta[property="og:title"]')?.setAttribute("content", item.name); document.querySelector('meta[property="og:description"]')?.setAttribute("content", item.text); } } } } } useEffect(() => { openPopup(); }, [leafletRefs, location]) useEffect(() => { }, [allTagsLoaded]) useEffect(() => { if(tagsReady){ newTagsToAdd.map(newtag => { addTag(newtag); setNewTagsToAdd(current => current.filter(tag => { return tag.id !== newtag.id; }), ) }) } }, [tagsReady]) return ( <> {items && items. filter(item => item.layer?.name === name)?. filter(item => filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.id.toLocaleLowerCase() === tag.id.toLocaleLowerCase())))?. filter(item => item.layer && isLayerVisible(item.layer)). map((item: Item) => { if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) { item[itemTextField] = getValue(item, itemTextField); if (item?.tags) { item[itemTextField] = item[itemTextField] + '\n\n'; item.tags.map(tag => { if(!item[itemTextField].includes(`#${tag}`)) return (item[itemTextField] = item[itemTextField] + `#${tag} `) return item[itemTextField] }); } if(allTagsLoaded) { item[itemTextField].toLocaleLowerCase().match(hashTagRegex)?.map(tag=> { if ((!tags.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()))&& !newTagsToAdd.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) { const newTag = {id: tag.slice(1).toLocaleLowerCase(), color: randomColor()}; setNewTagsToAdd(current => [...current, newTag]); } }); !tagsReady && setTagsReady(true); } const itemTtags = getItemTags(item); const latitude = itemLatitudeField && item ? getValue(item, itemLatitudeField) : undefined; const longitude = itemLongitudeField && item ? getValue(item, itemLongitudeField) : undefined; let color1 = markerDefaultColor; let color2 = "RGBA(35, 31, 32, 0.2)"; if (itemColorField) color1 = getValue(item, itemColorField); else if (itemTtags && itemTtags[0]) { color1 = itemTtags[0].color; } if (itemTtags && itemTtags[0] && itemColorField) color2 = itemTtags[0].color; else if (itemTtags && itemTtags[1]) { color2 = itemTtags[1].color; } return ( { if (!(item.id in leafletRefs && leafletRefs[item.id].marker == r)) r && addMarker(item, r); }} icon={MarkerIconFactory(markerShape, color1, color2, markerIcon)} key={item.id} position={[latitude, longitude]}> { (children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ? React.Children.toArray(children).map((child) => React.isValidElement(child) && child.props.__TYPE === "ItemView" ? { if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r)) r && addPopup(item, r as Popup); }} key={item.id + item.name} item={item} setItemFormPopup={setItemFormPopup}> {child} : "" ) : <> { if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r)) r && addPopup(item, r as Popup); }} item={item} setItemFormPopup={setItemFormPopup} /> ) } {item.name ? item.name : getValue(item, itemNameField)} ); } else return null; }) } {//{children}} } {itemFormPopup && itemFormPopup.layer!.name == name && (children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ? React.Children.toArray(children).map((child) => React.isValidElement(child) && child.props.__TYPE === "ItemForm" ? {child} : "" ) : <> ) } ) }