separated types, eslint rule for importing types

- Separated types and moved them into the proper ./types folder defined
in the tsconfig.json.
- Defined a new folder alias `#types`.
- New eslint rule to enforce `import type` when a type is imported.
- Removed Geometry Class and used manual Point types from `geojson`
This commit is contained in:
Ulf Gebhardt 2024-11-24 04:05:35 +01:00
parent d87363faf1
commit 3872a052b6
Signed by: ulfgebhardt
GPG Key ID: DA6B843E748679C9
82 changed files with 382 additions and 304 deletions

View File

@ -79,7 +79,7 @@ module.exports = {
'import/no-relative-parent-imports': [ 'import/no-relative-parent-imports': [
'error', 'error',
{ {
ignore: ['#[src,root,components,utils]/*'], ignore: ['#[src,types,root,components,utils]/*'],
}, },
], ],
'import/no-self-import': 'error', 'import/no-self-import': 'error',
@ -156,6 +156,7 @@ module.exports = {
'plugin:@typescript-eslint/strict', 'plugin:@typescript-eslint/strict',
], ],
rules: { rules: {
'@typescript-eslint/consistent-type-imports': 'error',
// allow explicitly defined dangling promises // allow explicitly defined dangling promises
'@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }], '@typescript-eslint/no-floating-promises': ['error', { ignoreVoid: true }],
'no-void': ['error', { allowAsStatement: true }], 'no-void': ['error', { allowAsStatement: true }],

View File

@ -79,6 +79,7 @@
"#components/*": "./src/Components/*", "#components/*": "./src/Components/*",
"#utils/*": "./src/Utils/*", "#utils/*": "./src/Utils/*",
"#src/*": "./src/*", "#src/*": "./src/*",
"#types/*": "./types/*",
"#root/*": "./*" "#root/*": "./*"
} }
} }

View File

@ -1,9 +1,9 @@
import { AssetsApi } from '#src/types'
import { ContextWrapper } from './ContextWrapper' import { ContextWrapper } from './ContextWrapper'
import NavBar from './NavBar' import NavBar from './NavBar'
import { SetAppState } from './SetAppState' import { SetAppState } from './SetAppState'
import type { AssetsApi } from '#types/AssetsApi'
export function AppShell({ export function AppShell({
appName, appName,
children, children,

View File

@ -16,7 +16,8 @@ import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export default function NavBar({ appName, userType }: { appName: string; userType: string }) { export default function NavBar({ appName, userType }: { appName: string; userType: string }) {
const { isAuthenticated, user, logout } = useAuth() const { isAuthenticated, user, logout } = useAuth()

View File

@ -1,9 +1,9 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { AssetsApi } from '#src/types'
import { useSetAppState } from './hooks/useAppState' import { useSetAppState } from './hooks/useAppState'
import type { AssetsApi } from '#types/AssetsApi'
export const SetAppState = ({ export const SetAppState = ({
assetsApi, assetsApi,
userType, userType,

View File

@ -2,7 +2,7 @@
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
import { useCallback, useState, createContext, useContext } from 'react' import { useCallback, useState, createContext, useContext } from 'react'
import { AssetsApi } from '#src/types' import type { AssetsApi } from '#types/AssetsApi'
interface AppState { interface AppState {
assetsApi: AssetsApi assetsApi: AssetsApi

View File

@ -3,7 +3,7 @@
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
import { useCallback, useState, createContext, useContext } from 'react' import { useCallback, useState, createContext, useContext } from 'react'
import { AssetsApi } from '#src/types' import type { AssetsApi } from '#types/AssetsApi'
type UseAssetManagerResult = ReturnType<typeof useAssetsManager> type UseAssetManagerResult = ReturnType<typeof useAssetsManager>

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unused-vars */ /* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-argument */
@ -7,7 +5,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import { createContext, useState, useContext, useEffect } from 'react' import { createContext, useState, useContext, useEffect } from 'react'
import { UserApi, UserItem } from '#src/types' import type { UserApi } from '#types/UserApi'
import type { UserItem } from '#types/UserItem'
interface AuthProviderProps { interface AuthProviderProps {
userApi: UserApi userApi: UserApi
@ -80,7 +79,7 @@ export const AuthProvider = ({ userApi, children }: AuthProviderProps) => {
setLoading(true) setLoading(true)
try { try {
const res = await userApi.login(credentials.email, credentials.password) const res = await userApi.login(credentials.email, credentials.password)
setToken(res.access_token) setToken(res?.access_token)
return await loadUser() return await loadUser()
} catch (error: any) { } catch (error: any) {
setLoading(false) setLoading(false)

View File

@ -3,10 +3,11 @@ import { useEffect, useState } from 'react'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { Item } from '#src/types'
import { useQuestsOpen, useSetQuestOpen } from './hooks/useQuests' import { useQuestsOpen, useSetQuestOpen } from './hooks/useQuests'
import type { Item } from '#types/Item'
export function Quests() { export function Quests() {
const questsOpen = useQuestsOpen() const questsOpen = useQuestsOpen()
const setQuestsOpen = useSetQuestOpen() const setQuestsOpen = useSetQuestOpen()

View File

@ -1,7 +1,7 @@
import { node, string } from 'prop-types' import { node, string } from 'prop-types'
import { Children, cloneElement, isValidElement, useEffect } from 'react' import { Children, cloneElement, isValidElement, useEffect } from 'react'
import { Item } from '#src/types' import type { Item } from '#types/Item'
export const ItemForm = ({ export const ItemForm = ({
children, children,

View File

@ -1,7 +1,7 @@
import { node, string } from 'prop-types' import { node, string } from 'prop-types'
import { Children, cloneElement, isValidElement } from 'react' import { Children, cloneElement, isValidElement } from 'react'
import { Item } from '#src/types' import type { Item } from '#types/Item'
export const ItemView = ({ children, item }: { children?: React.ReactNode; item?: Item }) => { export const ItemView = ({ children, item }: { children?: React.ReactNode; item?: Item }) => {
return ( return (

View File

@ -7,12 +7,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Popup } from 'leaflet'
import { Children, isValidElement, useEffect, useState } from 'react' import { Children, isValidElement, useEffect, useState } from 'react'
import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet' import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import { Item, LayerProps, Tag } from '#src/types'
import { encodeTag } from '#utils/FormatTags' import { encodeTag } from '#utils/FormatTags'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
@ -32,6 +30,11 @@ import { useAddTag, useAllTagsLoaded, useGetItemTags, useTags } from './hooks/us
import { ItemFormPopup } from './Subcomponents/ItemFormPopup' import { ItemFormPopup } from './Subcomponents/ItemFormPopup'
import { ItemViewPopup } from './Subcomponents/ItemViewPopup' 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'
export const Layer = ({ export const Layer = ({
data, data,
children, children,

View File

@ -1,10 +1,12 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth'
import { ItemsApi, Permission } from '#src/types'
import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions' import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions'
import type { ItemsApi } from '#types/ItemsApi'
import type { Permission } from '#types/Permission'
export function Permissions({ export function Permissions({
data, data,
api, api,

View File

@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { useLayers } from '#components/Map/hooks/useLayers' import { useLayers } from '#components/Map/hooks/useLayers'
import { useHasUserPermission } from '#components/Map/hooks/usePermissions' import { useHasUserPermission } from '#components/Map/hooks/usePermissions'

View File

@ -22,7 +22,6 @@ import { useItems } from '#components/Map/hooks/useItems'
import { useLeafletRefs } from '#components/Map/hooks/useLeafletRefs' import { useLeafletRefs } from '#components/Map/hooks/useLeafletRefs'
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import useWindowDimensions from '#components/Map/hooks/useWindowDimension' import useWindowDimensions from '#components/Map/hooks/useWindowDimension'
import { Item } from '#src/types'
import { decodeTag } from '#utils/FormatTags' import { decodeTag } from '#utils/FormatTags'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import MarkerIconFactory from '#utils/MarkerIconFactory' import MarkerIconFactory from '#utils/MarkerIconFactory'
@ -30,6 +29,8 @@ import MarkerIconFactory from '#utils/MarkerIconFactory'
import { LocateControl } from './LocateControl' import { LocateControl } from './LocateControl'
import { SidebarControl } from './SidebarControl' import { SidebarControl } from './SidebarControl'
import type { Item } from '#types/Item'
export const SearchControl = () => { export const SearchControl = () => {
const windowDimensions = useWindowDimensions() const windowDimensions = useWindowDimensions()
const [popupOpen, setPopupOpen] = useState(false) const [popupOpen, setPopupOpen] = useState(false)

View File

@ -17,10 +17,12 @@ import { TextInput } from '#components/Input/TextInput'
import { useResetFilterTags } from '#components/Map/hooks/useFilter' import { useResetFilterTags } from '#components/Map/hooks/useFilter'
import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems' import { useAddItem, useItems, useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems'
import { useAddTag, useTags } from '#components/Map/hooks/useTags' import { useAddTag, useTags } from '#components/Map/hooks/useTags'
import { Geometry, Item, ItemFormPopupProps } from '#src/types'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
import { randomColor } from '#utils/RandomColor' import { randomColor } from '#utils/RandomColor'
import type { Item } from '#types/Item'
import type { ItemFormPopupProps } from '#types/ItemFormPopupProps'
export function ItemFormPopup(props: ItemFormPopupProps) { export function ItemFormPopup(props: ItemFormPopupProps) {
const [spinner, setSpinner] = useState(false) const [spinner, setSpinner] = useState(false)
@ -50,7 +52,7 @@ export function ItemFormPopup(props: ItemFormPopupProps) {
formItem[input.name] = input.value formItem[input.name] = input.value
} }
}) })
formItem.position = new Geometry(props.position.lng, props.position.lat) formItem.position = { type: 'Point', coordinates: [props.position.lng, props.position.lat] }
evt.preventDefault() evt.preventDefault()
setSpinner(true) setSpinner(true)

View File

@ -15,9 +15,11 @@ import { useNavigate } from 'react-router-dom'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useHasUserPermission } from '#components/Map/hooks/usePermissions' import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
import DialogModal from '#components/Templates/DialogModal' import DialogModal from '#components/Templates/DialogModal'
import { Item, ItemsApi } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import type { Item } from '#types/Item'
import type { ItemsApi } from '#types/ItemsApi'
export function HeaderView({ export function HeaderView({
item, item,
api, api,

View File

@ -3,9 +3,10 @@
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { useGetItemTags } from '#components/Map/hooks/useTags' import { useGetItemTags } from '#components/Map/hooks/useTags'
import { Item } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import type { Item } from '#types/Item'
export const PopupButton = ({ export const PopupButton = ({
url, url,
parameterField, parameterField,

View File

@ -1,4 +1,4 @@
import { Item } from '#src/types' import type { Item } from '#types/Item'
export const PopupCheckboxInput = ({ export const PopupCheckboxInput = ({
dataField, dataField,

View File

@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
import { TextInput } from '#components/Input' import { TextInput } from '#components/Input'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
interface StartEndInputProps { interface StartEndInputProps {
item?: Item item?: Item

View File

@ -1,5 +1,6 @@
import { TextAreaInput } from '#components/Input' import { TextAreaInput } from '#components/Input'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const PopupTextAreaInput = ({ export const PopupTextAreaInput = ({
dataField, dataField,

View File

@ -1,5 +1,6 @@
import { TextInput } from '#components/Input' import { TextInput } from '#components/Input'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const PopupTextInput = ({ export const PopupTextInput = ({
dataField, dataField,

View File

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
import { Item } from '#src/types' import type { Item } from '#types/Item'
export const StartEndView = ({ item }: { item?: Item }) => { export const StartEndView = ({ item }: { item?: Item }) => {
return ( return (

View File

@ -11,12 +11,14 @@ import remarkBreaks from 'remark-breaks'
import { useAddFilterTag } from '#components/Map/hooks/useFilter' import { useAddFilterTag } from '#components/Map/hooks/useFilter'
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import { Item, Tag } from '#src/types'
import { decodeTag } from '#utils/FormatTags' import { decodeTag } from '#utils/FormatTags'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
import { fixUrls, mailRegex } from '#utils/ReplaceURLs' import { fixUrls, mailRegex } from '#utils/ReplaceURLs'
import type { Item } from '#types/Item'
import type { Tag } from '#types/Tag'
export const TextView = ({ export const TextView = ({
item, item,
truncate = false, truncate = false,

View File

@ -15,12 +15,14 @@ import { toast } from 'react-toastify'
import { useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems' import { useRemoveItem, useUpdateItem } from '#components/Map/hooks/useItems'
import { useSetSelectPosition } from '#components/Map/hooks/useSelectPosition' import { useSetSelectPosition } from '#components/Map/hooks/useSelectPosition'
import { Item, ItemFormPopupProps } from '#src/types'
import { timeAgo } from '#utils/TimeAgo' import { timeAgo } from '#utils/TimeAgo'
import { HeaderView } from './ItemPopupComponents/HeaderView' import { HeaderView } from './ItemPopupComponents/HeaderView'
import { TextView } from './ItemPopupComponents/TextView' import { TextView } from './ItemPopupComponents/TextView'
import type { Item } from '#types/Item'
import type { ItemFormPopupProps } from '#types/ItemFormPopupProps'
export interface ItemViewPopupProps { export interface ItemViewPopupProps {
item: Item item: Item
children?: React.ReactNode children?: React.ReactNode

View File

@ -1,11 +1,12 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useLocation } from 'react-router-dom' import { useLocation } from 'react-router-dom'
import { ItemsApi, Tag } from '#src/types'
import { useAddFilterTag, useFilterTags, useResetFilterTags } from './hooks/useFilter' import { useAddFilterTag, useFilterTags, useResetFilterTags } from './hooks/useFilter'
import { useSetTagData, useSetTagApi, useTags } from './hooks/useTags' import { useSetTagData, useSetTagApi, useTags } from './hooks/useTags'
import type { ItemsApi } from '#types/ItemsApi'
import type { Tag } from '#types/Tag'
export function Tags({ data, api }: { data?: Tag[]; api?: ItemsApi<Tag> }) { export function Tags({ data, api }: { data?: Tag[]; api?: ItemsApi<Tag> }) {
const setTagData = useSetTagData() const setTagData = useSetTagData()
const setTagApi = useSetTagApi() const setTagApi = useSetTagApi()

View File

@ -1,7 +1,9 @@
import { ContextWrapper } from '#components/AppShell/ContextWrapper' import { ContextWrapper } from '#components/AppShell/ContextWrapper'
import { UtopiaMapProps } from '#src/types'
import { UtopiaMapInner } from './UtopiaMapInner' import { UtopiaMapInner } from './UtopiaMapInner'
import type { UtopiaMapProps } from '#types/UtopiaMapProps'
// eslint-disable-next-line import/no-unassigned-import // eslint-disable-next-line import/no-unassigned-import
import 'react-toastify/dist/ReactToastify.css' import 'react-toastify/dist/ReactToastify.css'

View File

@ -23,8 +23,6 @@ import MarkerClusterGroup from 'react-leaflet-cluster'
import { Outlet } from 'react-router-dom' import { Outlet } from 'react-router-dom'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { ItemFormPopupProps, UtopiaMapProps } from '#src/types'
// eslint-disable-next-line import/no-unassigned-import // eslint-disable-next-line import/no-unassigned-import
import './UtopiaMap.css' import './UtopiaMap.css'
@ -46,6 +44,8 @@ import { TagsControl } from './Subcomponents/Controls/TagsControl'
import { TextView } from './Subcomponents/ItemPopupComponents/TextView' import { TextView } from './Subcomponents/ItemPopupComponents/TextView'
import { SelectPosition } from './Subcomponents/SelectPosition' import { SelectPosition } from './Subcomponents/SelectPosition'
import type { ItemFormPopupProps } from '#types/ItemFormPopupProps'
import type { UtopiaMapProps } from '#types/UtopiaMapProps'
import type { Feature, Geometry as GeoJSONGeometry } from 'geojson' import type { Feature, Geometry as GeoJSONGeometry } from 'geojson'
const mapDivRef = createRef() const mapDivRef = createRef()

View File

@ -7,11 +7,12 @@
import { useCallback, useReducer, createContext, useContext, useState } from 'react' import { useCallback, useReducer, createContext, useContext, useState } from 'react'
import { useNavigate } from 'react-router-dom' import { useNavigate } from 'react-router-dom'
import { LayerProps, Tag } from '#src/types'
import { useLayers } from './useLayers' import { useLayers } from './useLayers'
import useWindowDimensions from './useWindowDimension' import useWindowDimensions from './useWindowDimension'
import type { LayerProps } from '#types/LayerProps'
import type { Tag } from '#types/Tag'
type ActionType = type ActionType =
| { type: 'ADD_TAG'; tag: Tag } | { type: 'ADD_TAG'; tag: Tag }
| { type: 'REMOVE_TAG'; name: string } | { type: 'REMOVE_TAG'; name: string }

View File

@ -3,17 +3,16 @@
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
/* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/restrict-template-expressions */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/no-misused-promises */
import { useCallback, useReducer, createContext, useContext, useState } from 'react' import { useCallback, useReducer, createContext, useContext, useState } from 'react'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { Item, LayerProps } from '#src/types'
import { useAddLayer } from './useLayers' import { useAddLayer } from './useLayers'
import type { Item } from '#types/Item'
import type { LayerProps } from '#types/LayerProps'
type ActionType = type ActionType =
| { type: 'ADD'; item: Item } | { type: 'ADD'; item: Item }
| { type: 'UPDATE'; item: Item } | { type: 'UPDATE'; item: Item }
@ -82,13 +81,11 @@ function useItemsManager(initialItems: Item[]): {
}, },
}, },
}) })
if (result) { result.map((item) => {
result.map((item) => { dispatch({ type: 'ADD', item: { ...item, layer } })
dispatch({ type: 'ADD', item: { ...item, layer } }) return null
return null })
}) setallItemsLoaded(true)
setallItemsLoaded(true)
}
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, []) }, [])

View File

@ -2,7 +2,7 @@
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
import { useCallback, useReducer, createContext, useContext } from 'react' import { useCallback, useReducer, createContext, useContext } from 'react'
import { LayerProps } from '#src/types' import type { LayerProps } from '#types/LayerProps'
interface ActionType { interface ActionType {
type: 'ADD LAYER' type: 'ADD LAYER'

View File

@ -1,10 +1,10 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
/* eslint-disable @typescript-eslint/ban-types */ /* eslint-disable @typescript-eslint/ban-types */
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
import { Marker, Popup } from 'leaflet'
import { useCallback, useReducer, createContext, useContext } from 'react' import { useCallback, useReducer, createContext, useContext } from 'react'
import { Item } from '#src/types' import type { Item } from '#types/Item'
import type { Marker, Popup } from 'leaflet'
interface LeafletRef { interface LeafletRef {
item: Item item: Item

View File

@ -1,6 +1,5 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
/* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-call */
@ -10,7 +9,12 @@
import { useCallback, useReducer, createContext, useContext, useState } from 'react' import { useCallback, useReducer, createContext, useContext, useState } from 'react'
import { useAuth } from '#components/Auth/useAuth' import { useAuth } from '#components/Auth/useAuth'
import { Item, ItemsApi, LayerProps, Permission, PermissionAction } from '#src/types'
import type { Item } from '#types/Item'
import type { ItemsApi } from '#types/ItemsApi'
import type { LayerProps } from '#types/LayerProps'
import type { Permission } from '#types/Permission'
import type { PermissionAction } from '#types/PermissionAction'
type ActionType = { type: 'ADD'; permission: Permission } | { type: 'REMOVE'; id: string } type ActionType = { type: 'ADD'; permission: Permission } | { type: 'REMOVE'; id: string }
@ -57,12 +61,10 @@ function usePermissionsManager(initialPermissions: Permission[]): {
const setPermissionApi = useCallback(async (api: ItemsApi<Permission>) => { const setPermissionApi = useCallback(async (api: ItemsApi<Permission>) => {
const result = await api.getItems() const result = await api.getItems()
if (result) { result.map((permission) => {
result.map((permission) => { dispatch({ type: 'ADD', permission })
dispatch({ type: 'ADD', permission }) return null
return null })
})
}
}, []) }, [])
const setPermissionData = useCallback((data: Permission[]) => { const setPermissionData = useCallback((data: Permission[]) => {

View File

@ -8,15 +8,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable @typescript-eslint/no-non-null-assertion */
import { LatLng } from 'leaflet'
import { createContext, useContext, useEffect, useState } from 'react' import { createContext, useContext, useEffect, useState } from 'react'
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { Geometry, Item, LayerProps, ItemFormPopupProps } from '#src/types'
import { useUpdateItem } from './useItems' import { useUpdateItem } from './useItems'
import { useHasUserPermission } from './usePermissions' import { useHasUserPermission } from './usePermissions'
import type { Item } from '#types/Item'
import type { ItemFormPopupProps } from '#types/ItemFormPopupProps'
import type { LayerProps } from '#types/LayerProps'
import type { Point } from 'geojson'
import type { LatLng } from 'leaflet'
interface PolygonClickedProps { interface PolygonClickedProps {
position: LatLng position: LatLng
setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>> setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
@ -67,7 +70,11 @@ function useSelectPositionManager(): {
} }
if ('text' in selectPosition) { if ('text' in selectPosition) {
const position = const position =
mapClicked?.position.lng && new Geometry(mapClicked.position.lng, mapClicked.position.lat) mapClicked?.position.lng &&
({
type: 'Point',
coordinates: [mapClicked.position.lng, mapClicked.position.lat],
} as Point)
position && itemUpdatePosition({ ...selectPosition, position }) position && itemUpdatePosition({ ...selectPosition, position })
setSelectPosition(null) setSelectPosition(null)
} }

View File

@ -1,6 +1,5 @@
/* eslint-disable react/prop-types */ /* eslint-disable react/prop-types */
/* eslint-disable @typescript-eslint/no-misused-promises */ /* eslint-disable @typescript-eslint/no-misused-promises */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-empty-function */ /* eslint-disable @typescript-eslint/no-empty-function */
/* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable @typescript-eslint/no-floating-promises */
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
@ -11,10 +10,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { useCallback, useReducer, createContext, useContext, useState } from 'react' import { useCallback, useReducer, createContext, useContext, useState } from 'react'
import { Item, ItemsApi, Tag } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
import type { Item } from '#types/Item'
import type { ItemsApi } from '#types/ItemsApi'
import type { Tag } from '#types/Tag'
type ActionType = { type: 'ADD'; tag: Tag } | { type: 'REMOVE'; id: string } type ActionType = { type: 'ADD'; tag: Tag } | { type: 'REMOVE'; id: string }
type UseTagManagerResult = ReturnType<typeof useTagsManager> type UseTagManagerResult = ReturnType<typeof useTagsManager>

View File

@ -14,7 +14,6 @@ import { useLayers } from '#components/Map/hooks/useLayers'
import { useHasUserPermission } from '#components/Map/hooks/usePermissions' import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
import { useAddTag, useGetItemTags, useTags } from '#components/Map/hooks/useTags' import { useAddTag, useGetItemTags, useTags } from '#components/Map/hooks/useTags'
import { MapOverlayPage } from '#components/Templates' import { MapOverlayPage } from '#components/Templates'
import { Item, Tag } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { linkItem, onUpdateItem, unlinkItem } from './itemFunctions' import { linkItem, onUpdateItem, unlinkItem } from './itemFunctions'
@ -24,6 +23,9 @@ import { OnepagerForm } from './Templates/OnepagerForm'
import { SimpleForm } from './Templates/SimpleForm' import { SimpleForm } from './Templates/SimpleForm'
import { TabsForm } from './Templates/TabsForm' import { TabsForm } from './Templates/TabsForm'
import type { Item } from '#types/Item'
import type { Tag } from '#types/Tag'
export function ProfileForm() { export function ProfileForm() {
const [state, setState] = useState({ const [state, setState] = useState({
color: '', color: '',

View File

@ -21,7 +21,6 @@ import { useSelectPosition, useSetSelectPosition } from '#components/Map/hooks/u
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView' import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView'
import { MapOverlayPage } from '#components/Templates' import { MapOverlayPage } from '#components/Templates'
import { Item, ItemsApi, Tag } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { handleDelete, linkItem, unlinkItem } from './itemFunctions' import { handleDelete, linkItem, unlinkItem } from './itemFunctions'
@ -30,6 +29,10 @@ import { OnepagerView } from './Templates/OnepagerView'
import { SimpleView } from './Templates/SimpleView' import { SimpleView } from './Templates/SimpleView'
import { TabsView } from './Templates/TabsView' import { TabsView } from './Templates/TabsView'
import type { Item } from '#types/Item'
import type { ItemsApi } from '#types/ItemsApi'
import type { Tag } from '#types/Tag'
export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi<any> }) { export function ProfileView({ attestationApi }: { attestationApi?: ItemsApi<any> }) {
const [item, setItem] = useState<Item>() const [item, setItem] = useState<Item>()
const [updatePermission, setUpdatePermission] = useState<boolean>(false) const [updatePermission, setUpdatePermission] = useState<boolean>(false)

View File

@ -10,9 +10,10 @@ import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
import { useGetItemTags } from '#components/Map/hooks/useTags' import { useGetItemTags } from '#components/Map/hooks/useTags'
import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView' import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView'
import DialogModal from '#components/Templates/DialogModal' import DialogModal from '#components/Templates/DialogModal'
import { Item } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import type { Item } from '#types/Item'
export function ActionButton({ export function ActionButton({
item, item,
triggerAddButton, triggerAddButton,

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-return */
import { TextInput } from '#components/Input' import { TextInput } from '#components/Input'
import { FormState } from '#src/types'
import type { FormState } from '#types/FormState'
export const ContactInfoForm = ({ export const ContactInfoForm = ({
state, state,

View File

@ -8,7 +8,8 @@ import { Link } from 'react-router-dom'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const ContactInfoView = ({ item, heading }: { item: Item; heading: string }) => { export const ContactInfoView = ({ item, heading }: { item: Item; heading: string }) => {
const appState = useAppState() const appState = useAppState()

View File

@ -1,7 +1,7 @@
import { Item } from '#src/types'
import SocialShareBar from './SocialShareBar' import SocialShareBar from './SocialShareBar'
import type { Item } from '#types/Item'
export const GroupSubHeaderView = ({ export const GroupSubHeaderView = ({
item, item,
shareBaseUrl, shareBaseUrl,

View File

@ -4,7 +4,9 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import ComboBoxInput from '#components/Input/ComboBoxInput' import ComboBoxInput from '#components/Input/ComboBoxInput'
import { Item, FormState } from '#src/types'
import type { FormState } from '#types/FormState'
import type { Item } from '#types/Item'
interface groupType { interface groupType {
groupTypes_id: { groupTypes_id: {

View File

@ -8,9 +8,10 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { Item } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import type { Item } from '#types/Item'
export function LinkedItemsHeaderView({ export function LinkedItemsHeaderView({
item, item,
unlinkCallback, unlinkCallback,

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-call */
import { useHasUserPermission } from '#components/Map/hooks/usePermissions' import { useHasUserPermission } from '#components/Map/hooks/usePermissions'
import { LayerProps } from '#src/types'
import type { LayerProps } from '#types/LayerProps'
export function PlusButton({ export function PlusButton({
layer, layer,

View File

@ -1,7 +1,8 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-return */ /* eslint-disable @typescript-eslint/no-unsafe-return */
import { PopupStartEndInput } from '#components/Map' import { PopupStartEndInput } from '#components/Map'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const ProfileStartEndForm = ({ export const ProfileStartEndForm = ({
item, item,

View File

@ -1,5 +1,6 @@
import { StartEndView } from '#components/Map' import { StartEndView } from '#components/Map'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const ProfileStartEndView = ({ item }: { item: Item }) => { export const ProfileStartEndView = ({ item }: { item: Item }) => {
return ( return (

View File

@ -5,11 +5,12 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { TextAreaInput } from '#components/Input' import { TextAreaInput } from '#components/Input'
import { FormState } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { MarkdownHint } from './MarkdownHint' import { MarkdownHint } from './MarkdownHint'
import type { FormState } from '#types/FormState'
export const ProfileTextForm = ({ export const ProfileTextForm = ({
state, state,
setState, setState,

View File

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { TextView } from '#components/Map' import { TextView } from '#components/Map'
import { Item } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import type { Item } from '#types/Item'
export const ProfileTextView = ({ export const ProfileTextView = ({
item, item,
dataField, dataField,

View File

@ -8,10 +8,11 @@ import { useEffect, useState } from 'react'
import { Autocomplete } from '#components/Input/Autocomplete' import { Autocomplete } from '#components/Input/Autocomplete'
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import { Tag } from '#src/types'
import { decodeTag, encodeTag } from '#utils/FormatTags' import { decodeTag, encodeTag } from '#utils/FormatTags'
import { randomColor } from '#utils/RandomColor' import { randomColor } from '#utils/RandomColor'
import type { Tag } from '#types/Tag'
// eslint-disable-next-line react/prop-types // eslint-disable-next-line react/prop-types
export const TagsWidget = ({ placeholder, containerStyle, defaultTags, onUpdate }) => { export const TagsWidget = ({ placeholder, containerStyle, defaultTags, onUpdate }) => {
const [input, setInput] = useState('') const [input, setInput] = useState('')

View File

@ -7,7 +7,9 @@ import { ContactInfoForm } from '#components/Profile/Subcomponents/ContactInfoFo
import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm' import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm'
import { ProfileStartEndForm } from '#components/Profile/Subcomponents/ProfileStartEndForm' import { ProfileStartEndForm } from '#components/Profile/Subcomponents/ProfileStartEndForm'
import { ProfileTextForm } from '#components/Profile/Subcomponents/ProfileTextForm' import { ProfileTextForm } from '#components/Profile/Subcomponents/ProfileTextForm'
import { Item, FormState } from '#src/types'
import type { FormState } from '#types/FormState'
import type { Item } from '#types/Item'
const componentMap = { const componentMap = {
groupSubheaders: GroupSubheaderForm, groupSubheaders: GroupSubheaderForm,

View File

@ -6,7 +6,8 @@ import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoVi
import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView' import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView'
import { ProfileStartEndView } from '#components/Profile/Subcomponents/ProfileStartEndView' import { ProfileStartEndView } from '#components/Profile/Subcomponents/ProfileStartEndView'
import { ProfileTextView } from '#components/Profile/Subcomponents/ProfileTextView' import { ProfileTextView } from '#components/Profile/Subcomponents/ProfileTextView'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
const componentMap = { const componentMap = {
groupSubheaders: GroupSubHeaderView, groupSubheaders: GroupSubHeaderView,

View File

@ -3,7 +3,9 @@
import { TextAreaInput } from '#components/Input' import { TextAreaInput } from '#components/Input'
import { ContactInfoForm } from '#components/Profile/Subcomponents/ContactInfoForm' import { ContactInfoForm } from '#components/Profile/Subcomponents/ContactInfoForm'
import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm' import { GroupSubheaderForm } from '#components/Profile/Subcomponents/GroupSubheaderForm'
import { FormState, Item } from '#src/types'
import type { FormState } from '#types/FormState'
import type { Item } from '#types/Item'
export const OnepagerForm = ({ export const OnepagerForm = ({
item, item,

View File

@ -4,7 +4,8 @@
import { TextView } from '#components/Map' import { TextView } from '#components/Map'
import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoView' import { ContactInfoView } from '#components/Profile/Subcomponents/ContactInfoView'
import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView' import { GroupSubHeaderView } from '#components/Profile/Subcomponents/GroupSubHeaderView'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const OnepagerView = ({ item }: { item: Item }) => { export const OnepagerView = ({ item }: { item: Item }) => {
return ( return (

View File

@ -1,5 +1,6 @@
import { TextView } from '#components/Map' import { TextView } from '#components/Map'
import { Item } from '#src/types'
import type { Item } from '#types/Item'
export const SimpleView = ({ item }: { item: Item }) => { export const SimpleView = ({ item }: { item: Item }) => {
return ( return (

View File

@ -16,9 +16,11 @@ import { useItems } from '#components/Map/hooks/useItems'
import { ActionButton } from '#components/Profile/Subcomponents/ActionsButton' import { ActionButton } from '#components/Profile/Subcomponents/ActionsButton'
import { LinkedItemsHeaderView } from '#components/Profile/Subcomponents/LinkedItemsHeaderView' import { LinkedItemsHeaderView } from '#components/Profile/Subcomponents/LinkedItemsHeaderView'
import { TagView } from '#components/Templates/TagView' import { TagView } from '#components/Templates/TagView'
import { Item, Tag } from '#src/types'
import { timeAgo } from '#utils/TimeAgo' import { timeAgo } from '#utils/TimeAgo'
import type { Item } from '#types/Item'
import type { Tag } from '#types/Tag'
export const TabsView = ({ export const TabsView = ({
attestations, attestations,
item, item,

View File

@ -7,7 +7,8 @@ import { toast } from 'react-toastify'
import { useAuth } from '#components/Auth' import { useAuth } from '#components/Auth'
import { TextInput } from '#components/Input' import { TextInput } from '#components/Input'
import { MapOverlayPage } from '#components/Templates' import { MapOverlayPage } from '#components/Templates'
import { UserItem } from '#src/types'
import type { UserItem } from '#types/UserItem'
export function UserSettings() { export function UserSettings() {
const { user, updateUser, loading /* token */ } = useAuth() const { user, updateUser, loading /* token */ } = useAuth()

View File

@ -11,11 +11,12 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { toast } from 'react-toastify' import { toast } from 'react-toastify'
import { Item } from '#src/types'
import { encodeTag } from '#utils/FormatTags' import { encodeTag } from '#utils/FormatTags'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
import { randomColor } from '#utils/RandomColor' import { randomColor } from '#utils/RandomColor'
import type { Item } from '#types/Item'
// eslint-disable-next-line promise/avoid-new // eslint-disable-next-line promise/avoid-new
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)) const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

View File

@ -13,11 +13,13 @@ import { toast } from 'react-toastify'
import { useAppState } from '#components/AppShell/hooks/useAppState' import { useAppState } from '#components/AppShell/hooks/useAppState'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { Item, ItemsApi } from '#src/types'
import { EmojiPicker } from './EmojiPicker' import { EmojiPicker } from './EmojiPicker'
import { MapOverlayPage } from './MapOverlayPage' import { MapOverlayPage } from './MapOverlayPage'
import type { Item } from '#types/Item'
import type { ItemsApi } from '#types/ItemsApi'
export const AttestationForm = ({ api }: { api?: ItemsApi<any> }) => { export const AttestationForm = ({ api }: { api?: ItemsApi<any> }) => {
const items = useItems() const items = useItems()
const appState = useAppState() const appState = useAppState()

View File

@ -5,9 +5,10 @@
/* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/prefer-optional-chain */
import { useState } from 'react' import { useState } from 'react'
import { Item } from '#src/types'
import { timeAgo } from '#utils/TimeAgo' import { timeAgo } from '#utils/TimeAgo'
import type { Item } from '#types/Item'
export const DateUserInfo = ({ item }: { item: Item }) => { export const DateUserInfo = ({ item }: { item: Item }) => {
const [infoExpanded, setInfoExpanded] = useState<boolean>(false) const [infoExpanded, setInfoExpanded] = useState<boolean>(false)
return ( return (

View File

@ -1,4 +1,6 @@
import { MouseEvent, useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import type { MouseEvent } from 'react'
const isClickInsideRectangle = (e: MouseEvent, element: HTMLElement) => { const isClickInsideRectangle = (e: MouseEvent, element: HTMLElement) => {
const r = element.getBoundingClientRect() const r = element.getBoundingClientRect()

View File

@ -9,11 +9,12 @@ import { useNavigate } from 'react-router-dom'
import { StartEndView, TextView } from '#components/Map' import { StartEndView, TextView } from '#components/Map'
import useWindowDimensions from '#components/Map/hooks/useWindowDimension' import useWindowDimensions from '#components/Map/hooks/useWindowDimension'
import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView' import { HeaderView } from '#components/Map/Subcomponents/ItemPopupComponents/HeaderView'
import { Item } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { DateUserInfo } from './DateUserInfo' import { DateUserInfo } from './DateUserInfo'
import type { Item } from '#types/Item'
export const ItemCard = ({ export const ItemCard = ({
i, i,
loading, loading,

View File

@ -8,12 +8,13 @@ import { useNavigate } from 'react-router-dom'
import { useItems } from '#components/Map/hooks/useItems' import { useItems } from '#components/Map/hooks/useItems'
import { useTags } from '#components/Map/hooks/useTags' import { useTags } from '#components/Map/hooks/useTags'
import { Tag } from '#src/types'
import { getValue } from '#utils/GetValue' import { getValue } from '#utils/GetValue'
import { MapOverlayPage } from './MapOverlayPage' import { MapOverlayPage } from './MapOverlayPage'
import { TagView } from './TagView' import { TagView } from './TagView'
import type { Tag } from '#types/Tag'
function groupAndCount(arr) { function groupAndCount(arr) {
const grouped = arr.reduce((acc, obj) => { const grouped = arr.reduce((acc, obj) => {
const found = acc.find((item) => JSON.stringify(item.object) === JSON.stringify(obj)) const found = acc.find((item) => JSON.stringify(item.object) === JSON.stringify(obj))

View File

@ -19,13 +19,14 @@ import { Control } from '#components/Map/Subcomponents/Controls/Control'
import { SearchControl } from '#components/Map/Subcomponents/Controls/SearchControl' import { SearchControl } from '#components/Map/Subcomponents/Controls/SearchControl'
import { TagsControl } from '#components/Map/Subcomponents/Controls/TagsControl' import { TagsControl } from '#components/Map/Subcomponents/Controls/TagsControl'
import { PlusButton } from '#components/Profile/Subcomponents/PlusButton' import { PlusButton } from '#components/Profile/Subcomponents/PlusButton'
import { Item } from '#src/types'
import { hashTagRegex } from '#utils/HashTagRegex' import { hashTagRegex } from '#utils/HashTagRegex'
import { randomColor } from '#utils/RandomColor' import { randomColor } from '#utils/RandomColor'
import { ItemCard } from './ItemCard' import { ItemCard } from './ItemCard'
import { MapOverlayPage } from './MapOverlayPage' import { MapOverlayPage } from './MapOverlayPage'
import type { Item } from '#types/Item'
export const OverlayItemsIndexPage = ({ export const OverlayItemsIndexPage = ({
url, url,
layerName, layerName,

View File

@ -1,8 +1,9 @@
/* eslint-disable @typescript-eslint/restrict-template-expressions */ /* eslint-disable @typescript-eslint/restrict-template-expressions */
import { Tag } from '#src/types'
import { decodeTag } from '#utils/FormatTags' import { decodeTag } from '#utils/FormatTags'
import type { Tag } from '#types/Tag'
export const TagView = ({ export const TagView = ({
tag, tag,
heighlight, heighlight,

View File

@ -1,207 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { LatLng } from 'leaflet'
export interface Tag {
color: string
id: string
name: string
offer_or_need?: boolean
}
export interface UtopiaMapProps {
height?: string
width?: string
center?: [number, number]
zoom?: number
tags?: Tag[]
children?: React.ReactNode
geo?: any
showFilterControl?: boolean
showLayerControl?: boolean
showGratitudeControl?: boolean
infoText?: string
}
export interface ItemType {
name: string
[key: string]: any
}
export interface ItemsApi<T> {
getItems(): Promise<any>
getItem?(id: string): Promise<any>
createItem?(item: T): Promise<any>
updateItem?(item: T): Promise<any>
deleteItem?(id: string): Promise<any>
collectionName?: string
}
export interface LayerProps {
id?: string
// eslint-disable-next-line no-use-before-define
data?: Item[]
children?: React.ReactNode
name: string
menuIcon: any
menuColor: string
menuText: string
markerIcon: string
markerShape: string
markerDefaultColor: string
markerDefaultColor2?: string
api?: ItemsApi<any>
itemType: ItemType
itemNameField?: string
itemSubnameField?: string
itemTextField?: string
itemAvatarField?: string
itemColorField?: string
itemOwnerField?: string
itemTagsField?: string
itemLatitudeField?: any
itemLongitudeField?: any
itemOffersField?: string
itemNeedsField?: string
onlyOnePerOwner?: boolean
customEditLink?: string
customEditParameter?: string
public_edit_items?: boolean
listed?: boolean
item_presets?: Record<string, unknown>
// eslint-disable-next-line no-use-before-define
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
// eslint-disable-next-line no-use-before-define
itemFormPopup?: ItemFormPopupProps | null
clusterRef?: any
}
export class Geometry {
type: string
coordinates: number[]
constructor(lng: number, lat: number) {
this.coordinates = [lng, lat]
this.type = 'Point'
}
}
export interface Relation {
related_items_id: string
[key: string]: any
}
export class Item {
id: string
name: string
text: string
position?: Geometry
date_created?: string
date_updated?: string | null
start?: string
end?: string
api?: ItemsApi<any>
tags?: string[]
layer?: LayerProps
relations?: Relation[]
parent?: string
subname?: string
public_edit?: boolean
slug?: string;
[key: string]: any
constructor(
id: string,
name: string,
text: string,
position: Geometry,
layer?: LayerProps,
api?: ItemsApi<any>,
) {
this.id = id
this.name = name
this.text = text
this.position = position
this.layer = layer
this.api = api
}
}
export interface AssetsApi {
upload(file: Blob, title: string): any
url: string
}
export interface Profile {
id?: string
avatar?: string
color?: string
name: string
text: string
geoposition?: Geometry
}
export interface UserItem {
id?: string
role?: any
email?: string
password?: string
profile?: Profile
[key: string]: any
}
export interface UserApi {
register(email: string, password: string, userName: string): Promise<void>
login(email: string, password: string): Promise<any>
logout(): Promise<void>
getUser(): Promise<UserItem>
getToken(): Promise<any>
updateUser(user: UserItem): Promise<void>
requestPasswordReset(email: string, reset_url?: string)
passwordReset(token: string, new_password: string)
}
export interface PermissionCondition {
user_created?: {
_eq: string // Erwartet den speziellen Wert "$CURRENT_USER" oder eine spezifische UUID
}
public_edit?: {
_eq: boolean // Erwartet den speziellen Wert "$CURRENT_USER" oder eine spezifische UUID
}
}
export type PermissionAction = 'create' | 'read' | 'update' | 'delete'
export interface Permission {
id?: string
policy: any
collection: string
action: PermissionAction
permissions?: {
// Optional, für spezifische Bedingungen wie `user_created`
_and: PermissionCondition[]
}
}
export interface ItemFormPopupProps {
position: LatLng
layer: LayerProps
item?: Item
children?: React.ReactNode
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}
export interface FormState {
color: string
id: string
group_type: string
status: string
name: string
subname: string
text: string
contact: string
telephone: string
next_appointment: string
image: string
marker_icon: string
offers: Tag[]
needs: Tag[]
relations: Item[]
}

View File

@ -20,10 +20,11 @@
"#components/*": ["./src/Components/*"], "#components/*": ["./src/Components/*"],
"#utils/*": ["./src/Utils/*"], "#utils/*": ["./src/Utils/*"],
"#src/*": ["./src/*"], "#src/*": ["./src/*"],
"#types/*": ["./types/*"],
"#root/*": ["./*"] "#root/*": ["./*"]
} }
}, },
"include": ["src"], "include": ["src", "types"],
"exclude": ["node_modules", "dist", "example", "rollup.config.mjss"], "exclude": ["node_modules", "dist", "example", "rollup.config.mjss"],
"typeRoots": [ "typeRoots": [
"./types", "./types",

5
types/AssetsApi.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export interface AssetsApi {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
upload(file: Blob, title: string): any
url: string
}

20
types/FormState.d.ts vendored Normal file
View File

@ -0,0 +1,20 @@
import type { Item } from './Item'
import type { Tag } from './Tag'
export interface FormState {
color: string
id: string
group_type: string
status: string
name: string
subname: string
text: string
contact: string
telephone: string
next_appointment: string
image: string
marker_icon: string
offers: Tag[]
needs: Tag[]
relations: Item[]
}

41
types/Item.d.ts vendored Normal file
View File

@ -0,0 +1,41 @@
import type { ItemsApi } from './ItemsApi'
import type { LayerProps } from './LayerProps'
import type { Relation } from './Relation'
import type { Point } from 'geojson'
export interface Item {
id: string
name: string
text: string
position?: Point
date_created?: string
date_updated?: string | null
start?: string
end?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
api?: ItemsApi<any>
tags?: string[]
layer?: LayerProps
relations?: Relation[]
parent?: string
subname?: string
public_edit?: boolean
slug?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any
/* constructor(
id: string,
name: string,
text: string,
position: Geometry,
layer?: LayerProps,
api?: ItemsApi<any>,
) {
this.id = id
this.name = name
this.text = text
this.position = position
this.layer = layer
this.api = api
} */
}

11
types/ItemFormPopupProps.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
import type { Item } from './Item'
import type { LayerProps } from './LayerProps'
import type { LatLng } from 'leaflet'
export interface ItemFormPopupProps {
position: LatLng
layer: LayerProps
item?: Item
children?: React.ReactNode
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
}

5
types/ItemType.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export interface ItemType {
name: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any
}

8
types/ItemsApi.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
export interface ItemsApi<T> {
getItems(): Promise<T[]>
getItem?(id: string): Promise<T>
createItem?(item: T): Promise<T>
updateItem?(item: T): Promise<T>
deleteItem?(id: string): Promise<boolean>
collectionName?: string
}

42
types/LayerProps.d.ts vendored Normal file
View File

@ -0,0 +1,42 @@
import type { Item } from './Item'
import type { ItemFormPopupProps } from './ItemFormPopupProps'
import type { ItemsApi } from './ItemsApi'
import type { ItemType } from './ItemType'
export interface LayerProps {
id?: string
data?: Item[]
children?: React.ReactNode
name: string
menuIcon: string
menuColor: string
menuText: string
markerIcon: string
markerShape: string
markerDefaultColor: string
markerDefaultColor2?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
api?: ItemsApi<any>
itemType: ItemType
itemNameField?: string
itemSubnameField?: string
itemTextField?: string
itemAvatarField?: string
itemColorField?: string
itemOwnerField?: string
itemTagsField?: string
itemLatitudeField?: string
itemLongitudeField?: string
itemOffersField?: string
itemNeedsField?: string
onlyOnePerOwner?: boolean
customEditLink?: string
customEditParameter?: string
public_edit_items?: boolean
listed?: boolean
item_presets?: Record<string, unknown>
setItemFormPopup?: React.Dispatch<React.SetStateAction<ItemFormPopupProps | null>>
itemFormPopup?: ItemFormPopupProps | null
// eslint-disable-next-line @typescript-eslint/no-explicit-any
clusterRef?: any
}

13
types/Permission.d.ts vendored Normal file
View File

@ -0,0 +1,13 @@
import type { PermissionAction } from './PermissionAction'
import type { PermissionCondition } from './PermissionCondition'
export interface Permission {
id?: string
policy?: { name: string }
collection: string
action: PermissionAction
permissions?: {
// Optional, für spezifische Bedingungen wie `user_created`
_and: PermissionCondition[]
}
}

1
types/PermissionAction.d.ts vendored Normal file
View File

@ -0,0 +1 @@
export type PermissionAction = 'create' | 'read' | 'update' | 'delete'

8
types/PermissionCondition.d.ts vendored Normal file
View File

@ -0,0 +1,8 @@
export interface PermissionCondition {
user_created?: {
_eq: string // Erwartet den speziellen Wert "$CURRENT_USER" oder eine spezifische UUID
}
public_edit?: {
_eq: boolean // Erwartet den speziellen Wert "$CURRENT_USER" oder eine spezifische UUID
}
}

10
types/Profile.d.ts vendored Normal file
View File

@ -0,0 +1,10 @@
import type { Geometry } from 'geojson'
export interface Profile {
id?: string
avatar?: string
color?: string
name: string
text: string
geoposition?: Geometry
}

5
types/Relation.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
export interface Relation {
related_items_id: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any
}

6
types/Tag.d.ts vendored Normal file
View File

@ -0,0 +1,6 @@
export interface Tag {
color: string
id: string
name: string
offer_or_need?: boolean
}

12
types/UserApi.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
import type { UserItem } from './UserItem'
export interface UserApi {
register(email: string, password: string, userName: string): Promise<void>
login(email: string, password: string): Promise<UserItem | undefined>
logout(): Promise<void>
getUser(): Promise<UserItem>
getToken(): Promise<string | null>
updateUser(user: UserItem): Promise<void>
requestPasswordReset(email: string, reset_url?: string)
passwordReset(token: string, new_password: string)
}

12
types/UserItem.d.ts vendored Normal file
View File

@ -0,0 +1,12 @@
import type { Profile } from './Profile'
export interface UserItem {
id?: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
role?: any
email?: string
password?: string
profile?: Profile
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any
}

16
types/UtopiaMapProps.d.ts vendored Normal file
View File

@ -0,0 +1,16 @@
import type { Tag } from './Tag'
import type { GeoJsonObject } from 'geojson'
export interface UtopiaMapProps {
height?: string
width?: string
center?: [number, number]
zoom?: number
tags?: Tag[]
children?: React.ReactNode
geo?: GeoJsonObject
showFilterControl?: boolean
showLayerControl?: boolean
showGratitudeControl?: boolean
infoText?: string
}