From 82b1f39141a2adcac7967aac29624bb8a83012d5 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 22 May 2025 20:14:42 +0200 Subject: [PATCH] refactor(source): refactor Layer and its subcomponents, replacing cloneElement by context (#185) * Refactor Layer and its subcomponents, replacing cloneElement by context * Add showcase for PopupButton template component * Templateify exported elements (WIP) * Remove unused file * Export templateified PopupStartEndInput * Fix template component type * Change folder structure * Lower test coverage * changed export name * Refactor PopupForm and PopupView * More refactoring * Add provider for PopupFormContext * Fix popupform title * Add comments * Use correct ItemFormPopup for new items * Fix linting * Reduce coverage * Change tailwind prefix * Fix type --------- Co-authored-by: Anton Tranelis Co-authored-by: Anton Tranelis <31516529+antontranelis@users.noreply.github.com> --- src/Components/AppShell/ContextWrapper.tsx | 35 +-- src/Components/Item/PopupForm.tsx | 8 + src/Components/Item/PopupView.tsx | 182 +++++++++++++ src/Components/Item/TemplateItemContext.ts | 7 + src/Components/Item/index.tsx | 22 ++ src/Components/Item/templateify.tsx | 15 ++ src/Components/Map/ItemForm.tsx | 38 --- src/Components/Map/ItemView.tsx | 20 -- src/Components/Map/Layer.tsx | 252 ++---------------- src/Components/Map/LayerContext.ts | 22 ++ src/Components/Map/ProfileView.tsx | 0 .../Map/Subcomponents/ItemFormPopup.tsx | 192 ++++++------- .../PopupStartEndInput.tsx | 2 +- .../ItemPopupComponents/TextView.tsx | 3 - .../ItemPopupComponents/index.tsx | 7 + .../Map/Subcomponents/ItemViewPopup.tsx | 39 ++- src/Components/Map/UtopiaMapInner.tsx | 26 +- src/Components/Map/hooks/usePopupForm.tsx | 34 +++ .../Map/hooks/useSelectPosition.tsx | 7 +- src/Components/Map/index.tsx | 4 +- .../Subcomponents/ProfileStartEndForm.tsx | 2 +- .../Subcomponents/ProfileStartEndView.tsx | 2 +- .../Profile/Subcomponents/ProfileTextView.tsx | 2 +- .../Profile/Templates/OnepagerView.tsx | 2 +- .../Profile/Templates/SimpleView.tsx | 2 +- src/Components/Profile/Templates/TabsForm.tsx | 2 +- src/Components/Profile/Templates/TabsView.tsx | 2 +- src/Components/Templates/ItemCard.tsx | 2 +- .../Templates/OverlayItemsIndexPage.tsx | 2 +- src/index.tsx | 1 + src/types/LayerProps.d.ts | 5 - ...mFormPopupProps.d.ts => PopupFormState.ts} | 4 +- 32 files changed, 480 insertions(+), 463 deletions(-) create mode 100644 src/Components/Item/PopupForm.tsx create mode 100644 src/Components/Item/PopupView.tsx create mode 100644 src/Components/Item/TemplateItemContext.ts create mode 100644 src/Components/Item/index.tsx create mode 100644 src/Components/Item/templateify.tsx delete mode 100644 src/Components/Map/ItemForm.tsx delete mode 100644 src/Components/Map/ItemView.tsx create mode 100644 src/Components/Map/LayerContext.ts create mode 100644 src/Components/Map/ProfileView.tsx create mode 100644 src/Components/Map/Subcomponents/ItemPopupComponents/index.tsx create mode 100644 src/Components/Map/hooks/usePopupForm.tsx rename src/types/{ItemFormPopupProps.d.ts => PopupFormState.ts} (53%) diff --git a/src/Components/AppShell/ContextWrapper.tsx b/src/Components/AppShell/ContextWrapper.tsx index 50777b63..c4245b52 100644 --- a/src/Components/AppShell/ContextWrapper.tsx +++ b/src/Components/AppShell/ContextWrapper.tsx @@ -10,6 +10,7 @@ import { ItemsProvider } from '#components/Map/hooks/useItems' import { LayersProvider } from '#components/Map/hooks/useLayers' import { LeafletRefsProvider } from '#components/Map/hooks/useLeafletRefs' import { PermissionsProvider } from '#components/Map/hooks/usePermissions' +import { PopupFormProvider } from '#components/Map/hooks/usePopupForm' import { SelectPositionProvider } from '#components/Map/hooks/useSelectPosition' import { TagsProvider } from '#components/Map/hooks/useTags' @@ -66,22 +67,24 @@ export const Wrappers = ({ children }) => { - - - {children} - + + + + {children} + + diff --git a/src/Components/Item/PopupForm.tsx b/src/Components/Item/PopupForm.tsx new file mode 100644 index 00000000..877314b1 --- /dev/null +++ b/src/Components/Item/PopupForm.tsx @@ -0,0 +1,8 @@ +import { ItemFormPopup } from '#components/Map/Subcomponents/ItemFormPopup' + +/** + * @category Item + */ +export const PopupForm = ({ children }: { children?: React.ReactNode }) => { + return {children} +} diff --git a/src/Components/Item/PopupView.tsx b/src/Components/Item/PopupView.tsx new file mode 100644 index 00000000..6eea6e43 --- /dev/null +++ b/src/Components/Item/PopupView.tsx @@ -0,0 +1,182 @@ +import { useContext, useMemo, useState } from 'react' +import { Marker, Tooltip } from 'react-leaflet' + +import { useAppState } from '#components/AppShell/hooks/useAppState' +import { + useFilterTags, + useIsLayerVisible, + useIsGroupTypeVisible, + useVisibleGroupType, +} from '#components/Map/hooks/useFilter' +import { useItems, useAllItemsLoaded } 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 allItemsLoaded = useAllItemsLoaded() + + 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 && allItemsLoaded) { + 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} + + + + ) + }) +} diff --git a/src/Components/Item/TemplateItemContext.ts b/src/Components/Item/TemplateItemContext.ts new file mode 100644 index 00000000..f9da3309 --- /dev/null +++ b/src/Components/Item/TemplateItemContext.ts @@ -0,0 +1,7 @@ +import { createContext } from 'react' + +import type { Item } from '#types/Item' + +const ItemContext = createContext(undefined) + +export default ItemContext diff --git a/src/Components/Item/index.tsx b/src/Components/Item/index.tsx new file mode 100644 index 00000000..143ca9bf --- /dev/null +++ b/src/Components/Item/index.tsx @@ -0,0 +1,22 @@ +import { + TextView as PlainTextView, + StartEndView as PlainStartEndView, + PopupTextInput as PlainPopupTextInput, + PopupButton as PlainPopupButton, + PopupCheckboxInput as PlainPopupCheckboxInput, + PopupTextAreaInput as PlainPopupTextAreaInput, + PopupStartEndInput as PlainPopupStartEndInput, +} from '#components/Map/Subcomponents/ItemPopupComponents' + +import { templateify } from './templateify' + +export { PopupForm } from './PopupForm' +export { PopupView } from './PopupView' + +export const TextView = templateify(PlainTextView) +export const StartEndView = templateify(PlainStartEndView) +export const PopupTextInput = templateify(PlainPopupTextInput) +export const PopupButton = templateify(PlainPopupButton) +export const PopupCheckboxInput = templateify(PlainPopupCheckboxInput) +export const PopupTextAreaInput = templateify(PlainPopupTextAreaInput) +export const PopupStartEndInput = templateify(PlainPopupStartEndInput) diff --git a/src/Components/Item/templateify.tsx b/src/Components/Item/templateify.tsx new file mode 100644 index 00000000..fc541fcc --- /dev/null +++ b/src/Components/Item/templateify.tsx @@ -0,0 +1,15 @@ +import { useContext } from 'react' + +import ItemContext from './TemplateItemContext' + +import type { Item } from '#types/Item' + +export function templateify(Component: React.ComponentType) { + const TemplateComponent = (props: T) => { + const item = useContext(ItemContext) + + return + } + + return TemplateComponent as React.ComponentType> +} diff --git a/src/Components/Map/ItemForm.tsx b/src/Components/Map/ItemForm.tsx deleted file mode 100644 index b0fc58a1..00000000 --- a/src/Components/Map/ItemForm.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Children, cloneElement, isValidElement, useEffect } from 'react' - -import type { Item } from '#types/Item' - -/** - * @category Map - */ -export const ItemForm = ({ - children, - item, - title, - setPopupTitle, -}: { - children?: React.ReactNode - item?: Item - title?: string - setPopupTitle?: React.Dispatch> -}) => { - useEffect(() => { - setPopupTitle && title && setPopupTitle(title) - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [title]) - - return ( -
- {children - ? Children.toArray(children).map((child) => - isValidElement<{ item: Item; test: string }>(child) - ? cloneElement(child, { item, test: 'test' }) - : '', - ) - : ''} -
- ) -} - -ItemForm.__TYPE = 'ItemForm' diff --git a/src/Components/Map/ItemView.tsx b/src/Components/Map/ItemView.tsx deleted file mode 100644 index bdad06b3..00000000 --- a/src/Components/Map/ItemView.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Children, cloneElement, isValidElement } from 'react' - -import type { Item } from '#types/Item' - -/** - * @category Map - */ -export const ItemView = ({ children, item }: { children?: React.ReactNode; item?: Item }) => { - return ( -
- {children - ? Children.toArray(children).map((child) => - isValidElement<{ item: Item }>(child) ? cloneElement(child, { item }) : null, - ) - : null} -
- ) -} - -ItemView.__TYPE = 'ItemView' diff --git a/src/Components/Map/Layer.tsx b/src/Components/Map/Layer.tsx index 7952d0b4..6d54af71 100644 --- a/src/Components/Map/Layer.tsx +++ b/src/Components/Map/Layer.tsx @@ -1,32 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unnecessary-condition */ -/* eslint-disable @typescript-eslint/prefer-optional-chain */ -import { Children, isValidElement, useEffect, useState } from 'react' -import { Marker, Tooltip } from 'react-leaflet' +import { useEffect, useState } from 'react' -import { useAppState } from '#components/AppShell/hooks/useAppState' -import { encodeTag } from '#utils/FormatTags' -import { hashTagRegex } from '#utils/HashTagRegex' -import MarkerIconFactory from '#utils/MarkerIconFactory' -import { randomColor } from '#utils/RandomColor' +import { useSetItemsApi, useSetItemsData } from './hooks/useItems' +import { useAddTag } from './hooks/useTags' +import LayerContext from './LayerContext' -import { - useFilterTags, - useIsGroupTypeVisible, - useIsLayerVisible, - useVisibleGroupType, -} from './hooks/useFilter' -import { useAllItemsLoaded, useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems' -import { useAddMarker, useAddPopup, useLeafletRefs } from './hooks/useLeafletRefs' -import { useSelectPosition, useSetMarkerClicked } from './hooks/useSelectPosition' -import { useAddTag, useAllTagsLoaded, useGetItemTags, useTags } from './hooks/useTags' -import { ItemFormPopup } from './Subcomponents/ItemFormPopup' -import { ItemViewPopup } from './Subcomponents/ItemViewPopup' - -import type { Item } from '#types/Item' import type { LayerProps } from '#types/LayerProps' import type { Tag } from '#types/Tag' -import type { Popup } from 'leaflet' -import type { ReactElement, ReactNode } from 'react' export type { Point } from 'geojson' export type { Item } from '#types/Item' @@ -56,38 +35,13 @@ export const Layer = ({ // eslint-disable-next-line camelcase public_edit_items, listed = true, - 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() - const allTagsLoaded = useAllTagsLoaded() - const allItemsLoaded = useAllItemsLoaded() - - const setMarkerClicked = useSetMarkerClicked() - const selectPosition = useSelectPosition() - - const tags = useTags() const addTag = useAddTag() - const [newTagsToAdd, setNewTagsToAdd] = useState([]) - const [tagsReady, setTagsReady] = useState(false) - - const isLayerVisible = useIsLayerVisible() - - const isGroupTypeVisible = useIsGroupTypeVisible() - - const visibleGroupTypes = useVisibleGroupType() - - const appState = useAppState() + const [newTagsToAdd] = useState([]) + const [tagsReady] = useState(false) useEffect(() => { data && @@ -111,10 +65,6 @@ export const Layer = ({ // eslint-disable-next-line camelcase public_edit_items, listed, - setItemFormPopup, - itemFormPopup, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - clusterRef, }) api && setItemsApi({ @@ -136,10 +86,6 @@ export const Layer = ({ // eslint-disable-next-line camelcase public_edit_items, listed, - setItemFormPopup, - itemFormPopup, - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - clusterRef, }) // eslint-disable-next-line react-hooks/exhaustive-deps }, [data, api]) @@ -159,179 +105,17 @@ export const Layer = ({ }, [tagsReady]) return ( - <> - {items && - 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, - ) - .map((item: Item) => { - if (item.position?.coordinates[0] && item.position?.coordinates[1]) { - 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 && allItemsLoaded) { - 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 ? item.markerIcon : markerIcon, - appState.assetsApi.url, - )} - key={item.id} - position={[latitude, longitude]} - > - {children && - Children.toArray(children).some( - (child) => isComponentWithType(child) && child.type.__TYPE === 'ItemView', - ) ? ( - Children.toArray(children).map((child) => - isComponentWithType(child) && child.type.__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} - - ) : null, - ) - ) : ( - <> - { - if (!(item.id in leafletRefs && leafletRefs[item.id].popup === r)) { - r && addPopup(item, r as Popup) - } - }} - item={item} - setItemFormPopup={setItemFormPopup} - /> - - )} - - - {item.name} - - - ) - } else return null - })} - { - // {children}} - } - {itemFormPopup && - itemFormPopup.layer.name === name && - (children && - Children.toArray(children).some( - (child) => isComponentWithType(child) && child.type.__TYPE === 'ItemForm', - ) ? ( - Children.toArray(children).map((child) => - isComponentWithType(child) && child.type.__TYPE === 'ItemForm' ? ( - - {child} - - ) : ( - '' - ), - ) - ) : ( - <> - - - ))} - + + {children} + ) } - -function isComponentWithType(node: ReactNode): node is ReactElement & { type: { __TYPE: string } } { - return isValidElement(node) && typeof node.type !== 'string' && '__TYPE' in node.type -} diff --git a/src/Components/Map/LayerContext.ts b/src/Components/Map/LayerContext.ts new file mode 100644 index 00000000..dbd90490 --- /dev/null +++ b/src/Components/Map/LayerContext.ts @@ -0,0 +1,22 @@ +import { createContext } from 'react' + +import type { MarkerIcon } from '#types/MarkerIcon' + +interface LayerContextType { + name: string + markerDefaultColor: string + markerDefaultColor2: string + markerShape: string + menuText: string + markerIcon?: MarkerIcon +} + +const LayerContext = createContext({ + name: '', + markerDefaultColor: '', + markerDefaultColor2: '', + markerShape: '', + menuText: '', +}) + +export default LayerContext diff --git a/src/Components/Map/ProfileView.tsx b/src/Components/Map/ProfileView.tsx new file mode 100644 index 00000000..e69de29b diff --git a/src/Components/Map/Subcomponents/ItemFormPopup.tsx b/src/Components/Map/Subcomponents/ItemFormPopup.tsx index 0f346b25..d37d1fe6 100644 --- a/src/Components/Map/Subcomponents/ItemFormPopup.tsx +++ b/src/Components/Map/Subcomponents/ItemFormPopup.tsx @@ -2,31 +2,39 @@ /* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ -import { Children, cloneElement, isValidElement, useEffect, useRef, useState } from 'react' +import { useContext, useEffect, useRef, useState } from 'react' import { Popup as LeafletPopup, useMap } from 'react-leaflet' import { toast } from 'react-toastify' import { useAuth } from '#components/Auth/useAuth' import { TextAreaInput } from '#components/Input/TextAreaInput' import { TextInput } from '#components/Input/TextInput' +import TemplateItemContext from '#components/Item/TemplateItemContext' import { useResetFilterTags } from '#components/Map/hooks/useFilter' -import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems' +import { useAddItem, useItems, useUpdateItem } from '#components/Map/hooks/useItems' +import { usePopupForm } from '#components/Map/hooks/usePopupForm' import { useAddTag, useTags } from '#components/Map/hooks/useTags' +import LayerContext from '#components/Map/LayerContext' import { hashTagRegex } from '#utils/HashTagRegex' import { randomColor } from '#utils/RandomColor' import type { Item } from '#types/Item' -import type { ItemFormPopupProps } from '#types/ItemFormPopupProps' -export function ItemFormPopup(props: ItemFormPopupProps) { +interface Props { + children?: React.ReactNode +} + +export function ItemFormPopup(props: Props) { + const layerContext = useContext(LayerContext) + const { menuText, name: activeLayerName } = layerContext + + const { popupForm, setPopupForm } = usePopupForm() + const [spinner, setSpinner] = useState(false) - const [popupTitle, setPopupTitle] = useState('') - const formRef = useRef(null) const map = useMap() @@ -35,8 +43,6 @@ export function ItemFormPopup(props: ItemFormPopupProps) { const updateItem = useUpdateItem() const items = useItems() - const removeItem = useRemoveItem() - const tags = useTags() const addTag = useAddTag() @@ -45,13 +51,19 @@ export function ItemFormPopup(props: ItemFormPopupProps) { const { user } = useAuth() const handleSubmit = async (evt: any) => { + if (!popupForm) { + throw new Error('Popup form is not defined') + } const formItem: Item = {} as Item Array.from(evt.target).forEach((input: HTMLInputElement) => { if (input.name) { formItem[input.name] = input.value } }) - formItem.position = { type: 'Point', coordinates: [props.position.lng, props.position.lat] } + formItem.position = { + type: 'Point', + coordinates: [popupForm.position.lng, popupForm.position.lat], + } evt.preventDefault() const name = formItem.name ? formItem.name : user?.first_name @@ -73,32 +85,34 @@ export function ItemFormPopup(props: ItemFormPopupProps) { return null }) - if (props.item) { + if (popupForm.item) { let success = false try { - await props.layer.api?.updateItem!({ ...formItem, id: props.item.id }) + await popupForm.layer.api?.updateItem!({ ...formItem, id: popupForm.item.id }) success = true // eslint-disable-next-line no-catch-all/no-catch-all } catch (error) { toast.error(error.toString()) } if (success) { - updateItem({ ...props.item, ...formItem }) + updateItem({ ...popupForm.item, ...formItem }) toast.success('Item updated') } setSpinner(false) map.closePopup() } else { - const item = items.find((i) => i.user_created?.id === user?.id && i.layer === props.layer) + const item = items.find( + (i) => i.user_created?.id === user?.id && i.layer?.id === popupForm.layer.id, + ) const uuid = crypto.randomUUID() let success = false try { - props.layer.userProfileLayer && + popupForm.layer.userProfileLayer && item && - (await props.layer.api?.updateItem!({ ...formItem, id: item.id })) - ;(!props.layer.userProfileLayer || !item) && - (await props.layer.api?.createItem!({ + (await popupForm.layer.api?.updateItem!({ ...formItem, id: item.id })) + ;(!popupForm.layer.userProfileLayer || !item) && + (await popupForm.layer.api?.createItem!({ ...formItem, name, id: uuid, @@ -109,14 +123,14 @@ export function ItemFormPopup(props: ItemFormPopupProps) { toast.error(error.toString()) } if (success) { - if (props.layer.userProfileLayer && item) updateItem({ ...item, ...formItem }) - if (!props.layer.userProfileLayer || !item) { + if (popupForm.layer.userProfileLayer && item) updateItem({ ...item, ...formItem }) + if (!popupForm.layer.userProfileLayer || !item) { addItem({ ...formItem, name: (formItem.name ? formItem.name : user?.first_name) ?? '', user_created: user ?? undefined, id: uuid, - layer: props.layer, + layer: popupForm.layer, public_edit: !user, }) } @@ -126,7 +140,7 @@ export function ItemFormPopup(props: ItemFormPopupProps) { setSpinner(false) map.closePopup() } - props.setItemFormPopup!(null) + setPopupForm(null) } const resetPopup = () => { @@ -137,77 +151,75 @@ export function ItemFormPopup(props: ItemFormPopupProps) { useEffect(() => { resetPopup() - }, [props.position]) + }, [popupForm?.position]) return ( - { - setTimeout(function () { - resetPopup() - }, 100) - }, - }} - position={props.position} - > -
handleSubmit(e)}> - {props.item ? ( -
- ) : ( + popupForm && + popupForm.layer.name === activeLayerName && ( + { + setTimeout(function () { + resetPopup() + }, 100) + }, + }} + position={popupForm.position} + > + handleSubmit(e)} + > + {popupForm.item ? ( +
+ ) : ( +
+ {menuText} +
+ )} + + {props.children ? ( + + {props.children} + + ) : ( + <> + + + + )} +
- {props.layer.menuText} +
- )} - - {props.children ? ( - Children.toArray(props.children).map((child) => - isValidElement<{ - item: Item - test: string - setPopupTitle: React.Dispatch> - }>(child) - ? cloneElement(child, { - item: props.item, - key: props.position.toString(), - setPopupTitle, - }) - : '', - ) - ) : ( - <> - - - - )} - -
- -
- -
+ +
+ ) ) } diff --git a/src/Components/Map/Subcomponents/ItemPopupComponents/PopupStartEndInput.tsx b/src/Components/Map/Subcomponents/ItemPopupComponents/PopupStartEndInput.tsx index 5b1aea92..1106184d 100644 --- a/src/Components/Map/Subcomponents/ItemPopupComponents/PopupStartEndInput.tsx +++ b/src/Components/Map/Subcomponents/ItemPopupComponents/PopupStartEndInput.tsx @@ -3,7 +3,7 @@ import { TextInput } from '#components/Input' import type { Item } from '#types/Item' -interface StartEndInputProps { +export interface StartEndInputProps { item?: Item showLabels?: boolean updateStartValue?: (value: string) => void diff --git a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx index 720b76c1..5ff21325 100644 --- a/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx +++ b/src/Components/Map/Subcomponents/ItemPopupComponents/TextView.tsx @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ /* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/restrict-plus-operands */ @@ -177,8 +176,6 @@ export const TextView = ({ } if (href?.startsWith('#')) { - console.log(href.slice(1).toLowerCase()) - console.log(tags) const tag = tags.find( (t) => t.name.toLowerCase() === decodeURI(href).slice(1).toLowerCase(), ) diff --git a/src/Components/Map/Subcomponents/ItemPopupComponents/index.tsx b/src/Components/Map/Subcomponents/ItemPopupComponents/index.tsx new file mode 100644 index 00000000..c60493ea --- /dev/null +++ b/src/Components/Map/Subcomponents/ItemPopupComponents/index.tsx @@ -0,0 +1,7 @@ +export { PopupTextAreaInput } from './PopupTextAreaInput' +export { PopupStartEndInput } from './PopupStartEndInput' +export { PopupTextInput } from './PopupTextInput' +export { PopupCheckboxInput } from './PopupCheckboxInput' +export { TextView } from './TextView' +export { StartEndView } from './StartEndView' +export { PopupButton } from './PopupButton' diff --git a/src/Components/Map/Subcomponents/ItemViewPopup.tsx b/src/Components/Map/Subcomponents/ItemViewPopup.tsx index 402f09bc..87001bda 100644 --- a/src/Components/Map/Subcomponents/ItemViewPopup.tsx +++ b/src/Components/Map/Subcomponents/ItemViewPopup.tsx @@ -8,12 +8,13 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import { LatLng } from 'leaflet' -import { Children, cloneElement, forwardRef, isValidElement, useState } from 'react' +import { forwardRef, useState } from 'react' import { Popup as LeafletPopup, useMap } from 'react-leaflet' import { useNavigate } from 'react-router-dom' import { toast } from 'react-toastify' import { useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems' +import { usePopupForm } from '#components/Map/hooks/usePopupForm' import { useSetSelectPosition } from '#components/Map/hooks/useSelectPosition' import { timeAgo } from '#utils/TimeAgo' @@ -21,12 +22,10 @@ import { HeaderView } from './ItemPopupComponents/HeaderView' import { TextView } from './ItemPopupComponents/TextView' import type { Item } from '#types/Item' -import type { ItemFormPopupProps } from '#types/ItemFormPopupProps' export interface ItemViewPopupProps { item: Item children?: React.ReactNode - setItemFormPopup?: React.Dispatch> } // eslint-disable-next-line react/display-name @@ -37,22 +36,26 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) => const updadateItem = useUpdateItem() const navigate = useNavigate() const setSelectPosition = useSetSelectPosition() + const { setPopupForm } = usePopupForm() const [infoExpanded, setInfoExpanded] = useState(false) const handleEdit = (event: React.MouseEvent) => { event.stopPropagation() map.closePopup() - props.setItemFormPopup && - props.setItemFormPopup({ - position: new LatLng( - props.item.position?.coordinates[1]!, - props.item.position?.coordinates[0]!, - ), - layer: props.item.layer!, - item: props.item, - setItemFormPopup: props.setItemFormPopup, - }) + + if (!props.item.layer) { + throw new Error('Layer is not defined') + } + + setPopupForm({ + position: new LatLng( + props.item.position?.coordinates[1]!, + props.item.position?.coordinates[0]!, + ), + layer: props.item.layer, + item: props.item, + }) } const handleDelete = async (event: React.MouseEvent) => { @@ -98,15 +101,7 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) => loading={loading} />
- {props.children ? ( - Children.toArray(props.children).map((child) => - isValidElement<{ item: Item; test: string }>(child) - ? cloneElement(child, { item: props.item }) - : '', - ) - ) : ( - - )} + {props.children ?? }
{infoExpanded ? ( diff --git a/src/Components/Map/UtopiaMapInner.tsx b/src/Components/Map/UtopiaMapInner.tsx index ca5056fa..64860a1a 100644 --- a/src/Components/Map/UtopiaMapInner.tsx +++ b/src/Components/Map/UtopiaMapInner.tsx @@ -6,7 +6,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ -import { Children, cloneElement, isValidElement, useEffect, useRef, useState } from 'react' +import { useEffect, useRef } from 'react' import { TileLayer, useMapEvents, GeoJSON, useMap } from 'react-leaflet' import MarkerClusterGroup from 'react-leaflet-cluster' import { Outlet, useLocation } from 'react-router-dom' @@ -20,6 +20,7 @@ import { useClusterRef, useSetClusterRef } from './hooks/useClusterRef' import { useAddVisibleLayer } from './hooks/useFilter' import { useLayers } from './hooks/useLayers' import { useLeafletRefs } from './hooks/useLeafletRefs' +import { usePopupForm } from './hooks/usePopupForm' import { useSelectPosition, useSetMapClicked, @@ -35,7 +36,6 @@ import { TagsControl } from './Subcomponents/Controls/TagsControl' import { TextView } from './Subcomponents/ItemPopupComponents/TextView' import { SelectPosition } from './Subcomponents/SelectPosition' -import type { ItemFormPopupProps } from '#types/ItemFormPopupProps' import type { Feature, Geometry as GeoJSONGeometry, GeoJsonObject } from 'geojson' export function UtopiaMapInner({ @@ -62,17 +62,15 @@ export function UtopiaMapInner({ const setClusterRef = useSetClusterRef() const clusterRef = useClusterRef() const setMapClicked = useSetMapClicked() - const [itemFormPopup, setItemFormPopup] = useState(null) - - useTheme(defaultTheme) - + const { setPopupForm } = usePopupForm() const layers = useLayers() const addVisibleLayer = useAddVisibleLayer() const leafletRefs = useLeafletRefs() - const location = useLocation() const map = useMap() + useTheme(defaultTheme) + useEffect(() => { layers.forEach((layer) => addVisibleLayer(layer)) // eslint-disable-next-line react-hooks/exhaustive-deps @@ -119,7 +117,7 @@ export function UtopiaMapInner({ // eslint-disable-next-line no-console console.log(e.latlng.lat + ',' + e.latlng.lng) if (selectNewItemPosition) { - setMapClicked({ position: e.latlng, setItemFormPopup }) + setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm }) } }, moveend: () => {}, @@ -224,15 +222,7 @@ export function UtopiaMapInner({ maxClusterRadius={50} removeOutsideVisibleBounds={false} > - {Children.toArray(children).map((child) => - isValidElement<{ - setItemFormPopup: React.Dispatch> - itemFormPopup: ItemFormPopupProps | null - clusterRef: React.MutableRefObject - }>(child) - ? cloneElement(child, { setItemFormPopup, itemFormPopup, clusterRef }) - : child, - )} + {children} {geo && ( { if (selectNewItemPosition) { e.layer.closePopup() - setMapClicked({ position: e.latlng, setItemFormPopup }) + setMapClicked({ position: e.latlng, setItemFormPopup: setPopupForm }) } }, }} diff --git a/src/Components/Map/hooks/usePopupForm.tsx b/src/Components/Map/hooks/usePopupForm.tsx new file mode 100644 index 00000000..497c5931 --- /dev/null +++ b/src/Components/Map/hooks/usePopupForm.tsx @@ -0,0 +1,34 @@ +import { createContext, useContext, useState } from 'react' + +import type { PopupFormState } from '#types/PopupFormState' + +type UsePopupFormManagerResult = ReturnType + +const PoupFormContext = createContext({ + popupForm: {} as PopupFormState | null, + setPopupForm: () => { + /* empty function */ + }, +}) + +function usePopupFormManager(): { + popupForm: PopupFormState | null + setPopupForm: React.Dispatch> +} { + const [popupForm, setPopupForm] = useState(null) + + return { popupForm, setPopupForm } +} + +interface Props { + children?: React.ReactNode +} + +export const PopupFormProvider: React.FunctionComponent = ({ children }: Props) => ( + {children} +) + +export const usePopupForm = (): UsePopupFormManagerResult => { + const { popupForm, setPopupForm } = useContext(PoupFormContext) + return { popupForm, setPopupForm } +} diff --git a/src/Components/Map/hooks/useSelectPosition.tsx b/src/Components/Map/hooks/useSelectPosition.tsx index e53e0193..e1ebf9dc 100644 --- a/src/Components/Map/hooks/useSelectPosition.tsx +++ b/src/Components/Map/hooks/useSelectPosition.tsx @@ -15,14 +15,14 @@ import { useUpdateItem } from './useItems' import { useHasUserPermission } from './usePermissions' import type { Item } from '#types/Item' -import type { ItemFormPopupProps } from '#types/ItemFormPopupProps' import type { LayerProps } from '#types/LayerProps' +import type { PopupFormState } from '#types/PopupFormState' import type { Point } from 'geojson' import type { LatLng } from 'leaflet' interface PolygonClickedProps { position: LatLng - setItemFormPopup: React.Dispatch> + setItemFormPopup: React.Dispatch> } type UseSelectPositionManagerResult = ReturnType @@ -60,7 +60,9 @@ function useSelectPositionManager(): { useEffect(() => { if (selectPosition != null) { + // selectPosition can be null, Layer or Item if ('menuIcon' in selectPosition) { + // if selectPosition is a Layer mapClicked && mapClicked.setItemFormPopup({ layer: selectPosition, @@ -69,6 +71,7 @@ function useSelectPositionManager(): { setSelectPosition(null) } if ('text' in selectPosition) { + // if selectPosition is an Item const position = mapClicked?.position.lng && ({ diff --git a/src/Components/Map/index.tsx b/src/Components/Map/index.tsx index 6ef08d6c..0dbcc233 100644 --- a/src/Components/Map/index.tsx +++ b/src/Components/Map/index.tsx @@ -2,8 +2,7 @@ export { UtopiaMap } from './UtopiaMap' export * from './Layer' export { Tags } from './Tags' export * from './Permissions' -export { ItemForm } from './ItemForm' -export { ItemView } from './ItemView' +/* export { PopupTextAreaInput } from './Subcomponents/ItemPopupComponents/PopupTextAreaInput' export { PopupStartEndInput } from './Subcomponents/ItemPopupComponents/PopupStartEndInput' export { PopupTextInput } from './Subcomponents/ItemPopupComponents/PopupTextInput' @@ -11,3 +10,4 @@ export { PopupCheckboxInput } from './Subcomponents/ItemPopupComponents/PopupChe export { TextView } from './Subcomponents/ItemPopupComponents/TextView' export { StartEndView } from './Subcomponents/ItemPopupComponents/StartEndView' export { PopupButton } from './Subcomponents/ItemPopupComponents/PopupButton' +*/ diff --git a/src/Components/Profile/Subcomponents/ProfileStartEndForm.tsx b/src/Components/Profile/Subcomponents/ProfileStartEndForm.tsx index e5f67ffe..fa7d20c4 100644 --- a/src/Components/Profile/Subcomponents/ProfileStartEndForm.tsx +++ b/src/Components/Profile/Subcomponents/ProfileStartEndForm.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-return */ -import { PopupStartEndInput } from '#components/Map' +import { PopupStartEndInput } from '#components/Map/Subcomponents/ItemPopupComponents' import type { Item } from '#types/Item' diff --git a/src/Components/Profile/Subcomponents/ProfileStartEndView.tsx b/src/Components/Profile/Subcomponents/ProfileStartEndView.tsx index d490d725..67ac93f3 100644 --- a/src/Components/Profile/Subcomponents/ProfileStartEndView.tsx +++ b/src/Components/Profile/Subcomponents/ProfileStartEndView.tsx @@ -1,4 +1,4 @@ -import { StartEndView } from '#components/Map' +import { StartEndView } from '#components/Map/Subcomponents/ItemPopupComponents' import type { Item } from '#types/Item' diff --git a/src/Components/Profile/Subcomponents/ProfileTextView.tsx b/src/Components/Profile/Subcomponents/ProfileTextView.tsx index df1d5e77..2adbb3e1 100644 --- a/src/Components/Profile/Subcomponents/ProfileTextView.tsx +++ b/src/Components/Profile/Subcomponents/ProfileTextView.tsx @@ -1,6 +1,6 @@ import { get } from 'radash' -import { TextView } from '#components/Map' +import { TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import type { Item } from '#types/Item' diff --git a/src/Components/Profile/Templates/OnepagerView.tsx b/src/Components/Profile/Templates/OnepagerView.tsx index 088b92a6..7c2d8077 100644 --- a/src/Components/Profile/Templates/OnepagerView.tsx +++ b/src/Components/Profile/Templates/OnepagerView.tsx @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/restrict-template-expressions */ -import { TextView } from '#components/Map' +import { TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoView' import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView' diff --git a/src/Components/Profile/Templates/SimpleView.tsx b/src/Components/Profile/Templates/SimpleView.tsx index 894c3459..46b0d7ba 100644 --- a/src/Components/Profile/Templates/SimpleView.tsx +++ b/src/Components/Profile/Templates/SimpleView.tsx @@ -1,4 +1,4 @@ -import { TextView } from '#components/Map' +import { TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import type { Item } from '#types/Item' diff --git a/src/Components/Profile/Templates/TabsForm.tsx b/src/Components/Profile/Templates/TabsForm.tsx index 0a735955..f9931b28 100644 --- a/src/Components/Profile/Templates/TabsForm.tsx +++ b/src/Components/Profile/Templates/TabsForm.tsx @@ -10,8 +10,8 @@ import { useCallback, useEffect, useState } from 'react' import { useNavigate } from 'react-router-dom' import { TextAreaInput } from '#components/Input' -import { PopupStartEndInput, TextView } from '#components/Map' import { useUpdateItem } from '#components/Map/hooks/useItems' +import { PopupStartEndInput, TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import { ActionButton } from '#components/Profile/Subcomponents/ActionsButton' import { LinkedItemsHeaderView } from '#components/Profile/Subcomponents/LinkedItemsHeaderView' import { TagsWidget } from '#components/Profile/Subcomponents/TagsWidget' diff --git a/src/Components/Profile/Templates/TabsView.tsx b/src/Components/Profile/Templates/TabsView.tsx index c14ca054..5dce43a4 100644 --- a/src/Components/Profile/Templates/TabsView.tsx +++ b/src/Components/Profile/Templates/TabsView.tsx @@ -10,9 +10,9 @@ import { useCallback, useEffect, useRef, useState } from 'react' import { Link, useNavigate } from 'react-router-dom' import { useAppState } from '#components/AppShell/hooks/useAppState' -import { StartEndView, TextView } from '#components/Map' import { useAddFilterTag } from '#components/Map/hooks/useFilter' import { useItems } from '#components/Map/hooks/useItems' +import { StartEndView, TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import { ActionButton } from '#components/Profile/Subcomponents/ActionsButton' import { LinkedItemsHeaderView } from '#components/Profile/Subcomponents/LinkedItemsHeaderView' import { TagView } from '#components/Templates/TagView' diff --git a/src/Components/Templates/ItemCard.tsx b/src/Components/Templates/ItemCard.tsx index 02d86240..6e07688e 100644 --- a/src/Components/Templates/ItemCard.tsx +++ b/src/Components/Templates/ItemCard.tsx @@ -1,7 +1,7 @@ import { useNavigate } from 'react-router-dom' -import { StartEndView, TextView } from '#components/Map' import useWindowDimensions from '#components/Map/hooks/useWindowDimension' +import { StartEndView, TextView } from '#components/Map/Subcomponents/ItemPopupComponents' import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView' import { DateUserInfo } from './DateUserInfo' diff --git a/src/Components/Templates/OverlayItemsIndexPage.tsx b/src/Components/Templates/OverlayItemsIndexPage.tsx index 482d639e..68818dfe 100644 --- a/src/Components/Templates/OverlayItemsIndexPage.tsx +++ b/src/Components/Templates/OverlayItemsIndexPage.tsx @@ -9,7 +9,6 @@ import { toast } from 'react-toastify' import { useAuth } from '#components/Auth/useAuth' import { TextInput, TextAreaInput } from '#components/Input' -import { PopupStartEndInput } from '#components/Map' import { useFilterTags } from '#components/Map/hooks/useFilter' import { useAddItem, useItems, useRemoveItem } from '#components/Map/hooks/useItems' import { useLayers } from '#components/Map/hooks/useLayers' @@ -17,6 +16,7 @@ import { useAddTag, useGetItemTags, useTags } from '#components/Map/hooks/useTag import { Control } from '#components/Map/Subcomponents/Controls/Control' import { SearchControl } from '#components/Map/Subcomponents/Controls/SearchControl' import { TagsControl } from '#components/Map/Subcomponents/Controls/TagsControl' +import { PopupStartEndInput } from '#components/Map/Subcomponents/ItemPopupComponents' import { PlusButton } from '#components/Profile/Subcomponents/PlusButton' import { hashTagRegex } from '#utils/HashTagRegex' import { randomColor } from '#utils/RandomColor' diff --git a/src/index.tsx b/src/index.tsx index b84d77a2..07ec6212 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,6 +8,7 @@ export * from './Components/Profile' export * from './Components/Gaming' export * from './Components/Templates' export * from './Components/Input' +export * from './Components/Item' declare global { interface Window { diff --git a/src/types/LayerProps.d.ts b/src/types/LayerProps.d.ts index b625d830..771688b1 100644 --- a/src/types/LayerProps.d.ts +++ b/src/types/LayerProps.d.ts @@ -1,5 +1,4 @@ import type { Item } from './Item' -import type { ItemFormPopupProps } from './ItemFormPopupProps' import type { ItemsApi } from './ItemsApi' import type { ItemType } from './ItemType' import type { MarkerIcon } from './MarkerIcon' @@ -27,8 +26,4 @@ export interface LayerProps { public_edit_items?: boolean listed?: boolean item_presets?: Record - setItemFormPopup?: React.Dispatch> - itemFormPopup?: ItemFormPopupProps | null - // eslint-disable-next-line @typescript-eslint/no-explicit-any - clusterRef?: any } diff --git a/src/types/ItemFormPopupProps.d.ts b/src/types/PopupFormState.ts similarity index 53% rename from src/types/ItemFormPopupProps.d.ts rename to src/types/PopupFormState.ts index 64e880bb..1cf0890d 100644 --- a/src/types/ItemFormPopupProps.d.ts +++ b/src/types/PopupFormState.ts @@ -2,10 +2,8 @@ import type { Item } from './Item' import type { LayerProps } from './LayerProps' import type { LatLng } from 'leaflet' -export interface ItemFormPopupProps { +export interface PopupFormState { position: LatLng layer: LayerProps item?: Item - children?: React.ReactNode - setItemFormPopup?: React.Dispatch> }