mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2025-12-13 07:46:10 +00:00
More refactoring
This commit is contained in:
parent
eb054f4d1f
commit
f8e9cca011
@ -1,24 +1,8 @@
|
||||
import { ItemFormPopup } from '#components/Map/Subcomponents/ItemFormPopup'
|
||||
|
||||
import TemplateItemContext from './TemplateItemContext'
|
||||
|
||||
/**
|
||||
* @category Item
|
||||
*/
|
||||
export const PopupForm = ({ children }: { children?: React.ReactNode }) => {
|
||||
|
||||
return (
|
||||
<ItemFormPopup
|
||||
key={setItemFormPopup?.name}
|
||||
position={itemFormPopup.position}
|
||||
layer={itemFormPopup.layer}
|
||||
setItemFormPopup={setItemFormPopup}
|
||||
item={itemFormPopup.item}
|
||||
>
|
||||
<TemplateItemContext.Provider value={itemFormPopup.item}>
|
||||
{children}
|
||||
</TemplateItemContext.Provider>
|
||||
</ItemFormPopup>
|
||||
)
|
||||
)
|
||||
return <ItemFormPopup>{children}</ItemFormPopup>
|
||||
}
|
||||
|
||||
@ -28,8 +28,8 @@ import type { Popup } from 'leaflet'
|
||||
* @category Item
|
||||
*/
|
||||
export const PopupView = ({ children }: { children?: React.ReactNode }) => {
|
||||
const cardViewContext = useContext(LayerContext)
|
||||
const { name, markerDefaultColor, markerDefaultColor2, markerShape, markerIcon } = cardViewContext
|
||||
const layerContext = useContext(LayerContext)
|
||||
const { name, markerDefaultColor, markerDefaultColor2, markerShape, markerIcon } = layerContext
|
||||
|
||||
const filterTags = useFilterTags()
|
||||
|
||||
|
||||
@ -112,6 +112,7 @@ export const Layer = ({
|
||||
markerDefaultColor2,
|
||||
markerShape,
|
||||
markerIcon,
|
||||
menuText,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@ -6,6 +6,7 @@ interface LayerContextType {
|
||||
markerDefaultColor2: string
|
||||
markerShape: string
|
||||
markerIcon: string
|
||||
menuText: string
|
||||
}
|
||||
|
||||
const LayerContext = createContext<LayerContextType>({
|
||||
@ -14,6 +15,7 @@ const LayerContext = createContext<LayerContextType>({
|
||||
markerDefaultColor2: '',
|
||||
markerShape: '',
|
||||
markerIcon: '',
|
||||
menuText: '',
|
||||
})
|
||||
|
||||
export default LayerContext
|
||||
|
||||
@ -5,17 +5,19 @@
|
||||
/* 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, 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'
|
||||
|
||||
@ -26,9 +28,12 @@ interface Props {
|
||||
}
|
||||
|
||||
export function ItemFormPopup(props: Props) {
|
||||
const [spinner, setSpinner] = useState(false)
|
||||
const layerContext = useContext(LayerContext)
|
||||
const { menuText } = layerContext
|
||||
|
||||
const [, setPopupTitle] = useState<string>('')
|
||||
const { popupForm, setPopupForm } = usePopupForm()
|
||||
|
||||
const [spinner, setSpinner] = useState(false)
|
||||
|
||||
const formRef = useRef<HTMLFormElement>(null)
|
||||
|
||||
@ -45,8 +50,6 @@ export function ItemFormPopup(props: Props) {
|
||||
|
||||
const { user } = useAuth()
|
||||
|
||||
const { popupForm, setPopupForm } = usePopupForm()
|
||||
|
||||
const handleSubmit = async (evt: any) => {
|
||||
if (!popupForm) {
|
||||
throw new Error('Popup form is not defined')
|
||||
@ -82,32 +85,34 @@ export function ItemFormPopup(props: Props) {
|
||||
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,
|
||||
@ -118,14 +123,14 @@ export function ItemFormPopup(props: Props) {
|
||||
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,
|
||||
})
|
||||
}
|
||||
@ -146,77 +151,74 @@ export function ItemFormPopup(props: Props) {
|
||||
|
||||
useEffect(() => {
|
||||
resetPopup()
|
||||
}, [props.position])
|
||||
}, [popupForm?.position])
|
||||
|
||||
return (
|
||||
<LeafletPopup
|
||||
minWidth={275}
|
||||
maxWidth={275}
|
||||
autoPanPadding={[20, 80]}
|
||||
eventHandlers={{
|
||||
remove: () => {
|
||||
setTimeout(function () {
|
||||
resetPopup()
|
||||
}, 100)
|
||||
},
|
||||
}}
|
||||
position={props.position}
|
||||
>
|
||||
<form ref={formRef} onReset={resetPopup} autoComplete='off' onSubmit={(e) => handleSubmit(e)}>
|
||||
{props.item ? (
|
||||
<div className='tw:h-3'></div>
|
||||
) : (
|
||||
<div className='tw:flex tw:justify-center'>
|
||||
<b className='tw:text-xl tw:text-center tw:font-bold'>{props.layer.menuText}</b>
|
||||
popupForm && (
|
||||
<LeafletPopup
|
||||
minWidth={275}
|
||||
maxWidth={275}
|
||||
autoPanPadding={[20, 80]}
|
||||
eventHandlers={{
|
||||
remove: () => {
|
||||
setTimeout(function () {
|
||||
resetPopup()
|
||||
}, 100)
|
||||
},
|
||||
}}
|
||||
position={popupForm.position}
|
||||
>
|
||||
<form
|
||||
ref={formRef}
|
||||
onReset={resetPopup}
|
||||
autoComplete='off'
|
||||
onSubmit={(e) => handleSubmit(e)}
|
||||
>
|
||||
{popupForm.item ? (
|
||||
<div className='tw-h-3'></div>
|
||||
) : (
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<b className='tw-text-xl tw-text-center tw-font-bold'>{menuText}</b>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.children ? (
|
||||
<TemplateItemContext.Provider value={popupForm.item}>
|
||||
{props.children}
|
||||
</TemplateItemContext.Provider>
|
||||
) : (
|
||||
<>
|
||||
<TextInput
|
||||
type='text'
|
||||
placeholder='Name'
|
||||
dataField='name'
|
||||
defaultValue={popupForm.item ? popupForm.item.name : ''}
|
||||
inputStyle=''
|
||||
/>
|
||||
<TextAreaInput
|
||||
key={popupForm.position.toString()}
|
||||
placeholder='Text'
|
||||
dataField='text'
|
||||
defaultValue={popupForm.item?.text ?? ''}
|
||||
inputStyle='tw-h-40 tw-mt-5'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className='tw-flex tw-justify-center'>
|
||||
<button
|
||||
className={
|
||||
spinner
|
||||
? 'tw-btn tw-btn-disabled tw-mt-5 tw-place-self-center'
|
||||
: 'tw-btn tw-mt-5 tw-place-self-center'
|
||||
}
|
||||
type='submit'
|
||||
>
|
||||
{spinner ? <span className='tw-loading tw-loading-spinner'></span> : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.children ? (
|
||||
Children.toArray(props.children).map((child) =>
|
||||
isValidElement<{
|
||||
item: Item
|
||||
test: string
|
||||
setPopupTitle: React.Dispatch<React.SetStateAction<string>>
|
||||
}>(child)
|
||||
? cloneElement(child, {
|
||||
item: props.item,
|
||||
key: props.position.toString(),
|
||||
setPopupTitle,
|
||||
})
|
||||
: '',
|
||||
)
|
||||
) : (
|
||||
<>
|
||||
<TextInput
|
||||
type='text'
|
||||
placeholder='Name'
|
||||
dataField='name'
|
||||
defaultValue={props.item ? props.item.name : ''}
|
||||
inputStyle=''
|
||||
/>
|
||||
<TextAreaInput
|
||||
key={props.position.toString()}
|
||||
placeholder='Text'
|
||||
dataField='text'
|
||||
defaultValue={props.item?.text ?? ''}
|
||||
inputStyle='tw:h-40 tw:mt-5'
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className='tw:flex tw:justify-center'>
|
||||
<button
|
||||
className={
|
||||
spinner
|
||||
? 'tw:btn tw:btn-disabled tw:mt-5 tw:place-self-center'
|
||||
: 'tw:btn tw:mt-5 tw:place-self-center'
|
||||
}
|
||||
type='submit'
|
||||
>
|
||||
{spinner ? <span className='tw:loading tw:loading-spinner'></span> : 'Save'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</LeafletPopup>
|
||||
</form>
|
||||
</LeafletPopup>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -44,12 +44,16 @@ export const ItemViewPopup = forwardRef((props: ItemViewPopupProps, ref: any) =>
|
||||
event.stopPropagation()
|
||||
map.closePopup()
|
||||
|
||||
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!,
|
||||
layer: props.item.layer,
|
||||
item: props.item,
|
||||
})
|
||||
}
|
||||
|
||||
@ -63,16 +63,14 @@ export function UtopiaMapInner({
|
||||
const clusterRef = useClusterRef()
|
||||
const setMapClicked = useSetMapClicked()
|
||||
const { setPopupForm } = usePopupForm()
|
||||
|
||||
useTheme(defaultTheme)
|
||||
|
||||
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
|
||||
|
||||
@ -1,19 +1,19 @@
|
||||
import { createContext, useContext, useState } from 'react'
|
||||
|
||||
import type { ItemFormPopupProps } from '#types/ItemFormPopupProps'
|
||||
import type { PopupFormState } from '#types/PopupFormState'
|
||||
|
||||
type UsePopupFormManagerResult = ReturnType<typeof usePopupFormManager>
|
||||
|
||||
const PoupFormContext = createContext<UsePopupFormManagerResult>({
|
||||
popupForm: {} as ItemFormPopupProps | null,
|
||||
popupForm: {} as PopupFormState | null,
|
||||
setPopupForm: () => {},
|
||||
})
|
||||
|
||||
function usePopupFormManager(): {
|
||||
popupForm: ItemFormPopupProps | null
|
||||
setPopupForm: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||
popupForm: PopupFormState | null
|
||||
setPopupForm: React.Dispatch<React.SetStateAction<PopupFormState | null>>
|
||||
} {
|
||||
const [popupForm, setPopupForm] = useState<ItemFormPopupProps | null>(null)
|
||||
const [popupForm, setPopupForm] = useState<PopupFormState | null>(null)
|
||||
|
||||
return { popupForm, setPopupForm }
|
||||
}
|
||||
|
||||
@ -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 { PopupFormState } from '#types/PopupFormState'
|
||||
import type { LayerProps } from '#types/LayerProps'
|
||||
import type { Point } from 'geojson'
|
||||
import type { LatLng } from 'leaflet'
|
||||
|
||||
interface PolygonClickedProps {
|
||||
position: LatLng
|
||||
setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
|
||||
setItemFormPopup: React.Dispatch<React.SetStateAction<PopupFormState | null>>
|
||||
}
|
||||
|
||||
type UseSelectPositionManagerResult = ReturnType<typeof useSelectPositionManager>
|
||||
|
||||
@ -2,9 +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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user