/* eslint-disable @typescript-eslint/no-unnecessary-condition */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ /* eslint-disable import/order */ /* eslint-disable eqeqeq */ /* eslint-disable @typescript-eslint/no-unsafe-argument */ /* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable @typescript-eslint/no-floating-promises */ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable new-cap */ /* eslint-disable @typescript-eslint/prefer-optional-chain */ /* eslint-disable @typescript-eslint/restrict-plus-operands */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ import type { Item, Tag, LayerProps } from 'utopia-ui' import { AppShell, SideBar, Content, AuthProvider, Modal, InvitePage, LoginPage, SignupPage, Quests, RequestPasswordPage, SetNewPasswordPage, OverlayItemsIndexPage, Permissions, Tags, SelectUser, AttestationForm, MarketView, SVG, LoadingMapOverlay, ProfileForm, ProfileView, UserSettings, } from 'utopia-ui' import { Route, Routes } from 'react-router-dom' import './App.css' import { Suspense, useEffect, useState } from 'react' import { assetsApi } from './api/assetsApi' import { itemsApi } from './api/itemsApi' import { layersApi } from './api/layersApi' import { mapApi } from './api/mapApi' import { permissionsApi } from './api/permissionsApi' import { UserApi } from './api/userApi' import { ModalContent } from './ModalContent' import { Landingpage } from './pages/Landingpage' import MapContainer from './pages/MapContainer' import { getBottomRoutes, routes } from './routes/sidebar' import { config } from './config' import { InviteApi } from './api/inviteApi' import { MapPinIcon } from '@heroicons/react/24/solid' const userApi = new UserApi() const inviteApi = new InviteApi(userApi) function App() { const [permissionsApiInstance, setPermissionsApiInstance] = useState() const [tagsApi, setTagsApi] = useState>() const [mapApiInstance, setMapApiInstance] = useState() const [layersApiInstance, setLayersApiInstance] = useState() const [attestationApi, setAttestationApi] = useState>() const [itemsApiInstance, setItemsApiInstance] = useState>() const [map, setMap] = useState() const [layers, setLayers] = useState() const [layerPageRoutes, setLayerPageRoutes] = useState() const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const retryConnection = () => { setError(null) setLoading(true) if (mapApiInstance) { getMap() } } const [embedded, setEmbedded] = useState(true) useEffect(() => { const params = new URLSearchParams(location.search) const embedded = params.get('embedded') embedded !== 'true' && setEmbedded(false) }, [location]) useEffect(() => { setPermissionsApiInstance(new permissionsApi()) // TODO: it should be mapId instead of mapUrl, which then in turn can be an URL const mapUrl = config.mapUrl === 'CURRENT_WINDOW_LOCATION' ? window.location.origin : config.mapUrl setMapApiInstance(new mapApi(mapUrl)) setAttestationApi(new itemsApi('attestations')) }, []) useEffect(() => { mapApiInstance && getMap() }, [mapApiInstance]) const getMap = async () => { try { const map = await mapApiInstance?.getItems() map && setMap(map) map && map != 'null' && setLayersApiInstance(new layersApi(map.id)) map && map != 'null' && map.own_tag_space ? setTagsApi(new itemsApi('tags', undefined, map.id)) : setTagsApi(new itemsApi('tags')) // eslint-disable-next-line no-catch-all/no-catch-all } catch (error: any) { // eslint-disable-next-line no-console console.error('Failed to load map:', error) setError( typeof error === 'string' ? error : (error?.errors?.length > 0 ? error.errors[0]?.message : null) || error?.message || 'Failed to connect to the server. Please check your connection and try again.', ) setLoading(false) // Don't rethrow since we're handling the error by setting error state } } useEffect(() => { layersApiInstance && getLayers() }, [layersApiInstance]) const getLayers = async () => { try { const layers = await layersApiInstance?.getItems() layers && setLayers(layers) setLayerPageRoutes( layers ?.filter((l: LayerProps) => l.listed) .map((l: LayerProps) => ({ path: '/' + l.name, // url icon: l.markerIcon?.image ? ( code.replace(/stroke=".*?"/g, 'stroke="currentColor"') } /> ) : ( ), name: l.name, // name that appear in Sidebar color: l.menuColor, })), ) // eslint-disable-next-line no-catch-all/no-catch-all } catch (error: any) { // eslint-disable-next-line no-console console.error('Failed to load layers:', error) setError( typeof error === 'string' ? error : (error?.errors?.length > 0 ? error.errors[0]?.message : null) || error?.message || 'Failed to load map layers. Please check your permissions and try again.', ) setLoading(false) // Don't rethrow since we're handling the error by setting error state } } useEffect(() => { if (map && map.name) { document.title = map?.name && map.name let link: HTMLLinkElement = document.querySelector("link[rel~='icon']")! if (!link) { link = document.createElement('link') link.rel = 'icon' document.getElementsByTagName('head')[0].appendChild(link) } link.href = map?.logo && config.apiUrl + '/assets/' + map.logo // Specify the path to your favicon } // Only set loading to false when both map and layers are successfully loaded if (map && layers) { setLoading(false) } }, [map, layers]) useEffect(() => { if (!map) return setItemsApiInstance(new itemsApi('items', undefined, map.id)) }, [map]) const currentUrl = window.location.href const bottomRoutes = getBottomRoutes(currentUrl) if (map && layers && itemsApiInstance) return (
{tagsApi && } }> } /> } /> } /> } /> } /> }> } /> }> } /> }> } /> } /> } /> } /> {/* } /> */} } /> {layers.map((l: LayerProps) => ( } /> ))}
) else if (map == 'null' && !loading) return (

This map does not exist

) else if (error) return (

Connection Error

{error}

) else return (

) } export default App