Small fixes
Some checks failed
CI / Python (lint + test) (push) Failing after 1m42s
CI / Frontend (lint + typecheck) (push) Failing after 1m45s
CI / Rust (lint + test) (push) Successful in 4m45s
Build and publish Docker image / build-and-push (push) Failing after 6m21s

This commit is contained in:
Andras Schmelczer 2026-03-26 07:55:13 +00:00
parent d56b5dedff
commit d93beb9201
7 changed files with 95 additions and 42 deletions

View file

@ -1,4 +1,4 @@
import { useState, useEffect, useCallback, useMemo } from 'react';
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
import MapPage, { type ExportState } from './components/map/MapPage';
import PricingPage from './components/pricing/PricingPage';
import HomePage from './components/home/HomePage';
@ -67,9 +67,14 @@ function pathToPage(pathname: string): { page: Page; inviteCode?: string } | nul
export default function App() {
const urlState = useMemo(() => parseUrlState(), []);
const [mapUrlState, setMapUrlState] = useState(urlState);
const dashboardSearchRef = useRef(
window.location.pathname === '/dashboard' ? window.location.search : ''
);
const activePageRef = useRef<Page>('home');
const initialViewState = useMemo(
() => urlState.viewState || INITIAL_VIEW_STATE,
[urlState.viewState]
() => mapUrlState.viewState || INITIAL_VIEW_STATE,
[mapUrlState.viewState]
);
const isScreenshotMode = useMemo(() => {
@ -179,17 +184,30 @@ export default function App() {
const navigateTo = useCallback(
(page: Page, hash?: string, infoFeature?: string) => {
// Save dashboard search params before navigating away
if (activePageRef.current === 'dashboard') {
dashboardSearchRef.current = window.location.search;
}
if (infoFeature) {
window.history.replaceState({ ...window.history.state, infoFeature }, '');
}
const path = pageToPath(page, inviteCode ?? undefined);
const url = hash ? `${path}#${hash}` : path;
// Restore dashboard search params when navigating back
const search = page === 'dashboard' ? dashboardSearchRef.current : '';
const url = hash ? `${path}${search}#${hash}` : `${path}${search}`;
window.history.pushState({ page }, '', url);
if (page === 'dashboard') {
setMapUrlState(parseUrlState());
}
setActivePage(page);
},
[inviteCode]
);
useEffect(() => {
activePageRef.current = activePage;
}, [activePage]);
useEffect(() => {
if (!window.history.state?.page) {
window.history.replaceState(
@ -199,17 +217,24 @@ export default function App() {
);
}
const handlePopState = (e: PopStateEvent) => {
let page: Page;
if (e.state?.page) {
setActivePage(e.state.page);
page = e.state.page;
setActivePage(page);
if (e.state.infoFeature) {
setPendingInfoFeature(e.state.infoFeature);
}
} else {
// Fall back to deriving page from pathname
const parsed = pathToPage(window.location.pathname);
setActivePage(parsed?.page || 'home');
page = parsed?.page || 'home';
setActivePage(page);
if (parsed?.inviteCode) setInviteCode(parsed.inviteCode);
}
// Re-parse URL state when returning to dashboard via back/forward
if (page === 'dashboard') {
setMapUrlState(parseUrlState());
}
};
window.addEventListener('popstate', handlePopState);
return () => window.removeEventListener('popstate', handlePopState);
@ -367,10 +392,10 @@ export default function App() {
<MapPage
features={features}
poiCategoryGroups={poiCategoryGroups}
initialFilters={urlState.filters || { 'Listing status': ['Historical sale'] }}
initialFilters={mapUrlState.filters || { 'Listing status': ['Historical sale'] }}
initialViewState={initialViewState}
initialPOICategories={urlState.poiCategories || new Set()}
initialTab={urlState.tab || 'area'}
initialPOICategories={mapUrlState.poiCategories || new Set()}
initialTab={mapUrlState.tab || 'area'}
initialLoading={initialLoading}
theme={theme}
pendingInfoFeature={pendingInfoFeature}
@ -378,8 +403,8 @@ export default function App() {
onNavigateTo={navigateTo}
onExportStateChange={setExportState}
isMobile={isMobile}
initialTravelTime={urlState.travelTime}
initialPostcode={urlState.postcode}
initialTravelTime={mapUrlState.travelTime}
initialPostcode={mapUrlState.postcode}
user={user}
onLoginClick={() => {
setAuthModalTab('login');