refactor: move info modal to dedicated /info route

- Move Modal from always-rendered to route-based rendering at /info
- Update Modal component to use MapOverlayPage instead of dialog element
- Update ModalContent to use useNavigate for closing (navigates to /)
- Add automatic redirect to /info when map.info_open is true on first load

This change makes the info modal accessible via URL and improves
the architecture by using the existing routing system.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Anton Tranelis 2026-01-12 16:45:23 +01:00
parent b7f5b0092f
commit ec2bce1ccb
3 changed files with 33 additions and 48 deletions

View File

@ -41,7 +41,7 @@ import {
UserSettings,
} from 'utopia-ui'
import { Route, Routes } from 'react-router-dom'
import { Route, Routes, useNavigate } from 'react-router-dom'
import './App.css'
import { Suspense, useEffect, useState } from 'react'
@ -196,6 +196,14 @@ function App() {
const currentUrl = window.location.href
const bottomRoutes = getBottomRoutes(currentUrl)
const navigate = useNavigate()
// Redirect to /info if map.info_open is true (on first load)
useEffect(() => {
if (map?.info_open && window.location.pathname === '/') {
void navigate('/info')
}
}, [map?.info_open, navigate])
if (map && layers)
return (
@ -210,9 +218,6 @@ function App() {
>
<Permissions api={permissionsApiInstance} adminRole={config.adminRole} />
{tagsApi && <Tags api={tagsApi}></Tags>}
<Modal>
<ModalContent map={map} />
</Modal>
<SideBar routes={[...routes, ...layerPageRoutes]} bottomRoutes={bottomRoutes} />
<Content>
<Quests />
@ -258,6 +263,14 @@ function App() {
</Suspense>
}
/>
<Route
path='info'
element={
<Modal>
<ModalContent map={map} />
</Modal>
}
/>
<Route path='landingpage' element={<Landingpage />} />
<Route path='market' element={<MarketView />} />
<Route path='select-user' element={<SelectUser />} />

View File

@ -4,7 +4,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
import { useEffect, useState } from 'react'
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { TextView } from 'utopia-ui'
import { config } from './config'
@ -61,21 +62,13 @@ export function Welcome1({ clickAction1, map }: ChapterProps) {
)
}
const close = () => {
const myModal = document.getElementById('my_modal_3') as HTMLDialogElement
myModal.close()
}
export const ModalContent = ({ map }: { map: any }) => {
useEffect(() => {
const myModal = document.getElementById('my_modal_3') as HTMLDialogElement
if (map.info_open) {
myModal.showModal()
}
}, [map.info_open])
const navigate = useNavigate()
const [chapter, setChapter] = useState<number>(1)
// const setQuestsOpen = useSetQuestOpen()
const close = () => {
void navigate('/')
}
const ActiveChapter = () => {
switch (chapter) {
@ -86,7 +79,6 @@ export const ModalContent = ({ map }: { map: any }) => {
clickAction1={() => {
close()
setTimeout(() => {
// setQuestsOpen(true);
setChapter(1)
}, 1000)
}}

View File

@ -1,36 +1,16 @@
import { useEffect } from 'react'
import { MapOverlayPage } from '#components/Templates'
/**
* @category Gaming
*/
export function Modal({
children,
showOnStartup,
}: {
children: React.ReactNode
showOnStartup?: boolean
}) {
useEffect(() => {
if (showOnStartup) {
window.my_modal_3.showModal()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
export function Modal({ children }: { children: React.ReactNode }) {
return (
<>
{/* You can open the modal using ID.showModal() method */}
<dialog id='my_modal_3' className='tw:modal tw:transition-all tw:duration-300'>
<form method='dialog' className='tw:modal-box tw:transition-none'>
<button className='tw:btn tw:btn-sm tw:btn-circle tw:btn-ghost tw:absolute tw:right-2 tw:top-2 tw:focus:outline-hidden'>
</button>
{children}
</form>
<form method='dialog' className='tw:modal-backdrop'>
<button>close</button>
</form>
</dialog>
</>
<MapOverlayPage
backdrop
card
className='tw:absolute tw:h-fit tw:max-h-[calc(100%-2.5em)] tw:top-4 tw:bottom-4 tw:left-1/2 tw:transform tw:-translate-x-1/2 tw:overflow-scroll tw:md:w-[calc(50%-32px)] tw:w-[calc(100%-32px)] tw:min-w-80 tw:max-w-[612px] tw:transition-opacity tw:duration-500 tw:opacity-100 tw:pointer-events-auto'
>
{children}
</MapOverlayPage>
)
}