This commit is contained in:
Andras Schmelczer 2026-05-31 20:20:41 +01:00
parent 8688b7475e
commit e8345cbdc1
40 changed files with 1980 additions and 904 deletions

View file

@ -81,6 +81,15 @@ function isProtectedPage(page: Page): boolean {
return page === 'account' || page === 'saved';
}
function isSharedDashboardUrl(): boolean {
const share = new URLSearchParams(window.location.search).get('share');
return !!share && /^[a-z0-9]{1,20}$/i.test(share);
}
function isAuthRequiredRoute(page: Page): boolean {
return isProtectedPage(page) || (page === 'dashboard' && !isSharedDashboardUrl());
}
function buildPageUrl(page: Page, inviteCode?: string, search = '', hash = ''): string {
const normalizedHash = normalizeHash(hash);
return `${pageToPath(page, inviteCode)}${search}${normalizedHash ? `#${normalizedHash}` : ''}`;
@ -235,6 +244,7 @@ export default function App() {
const postAuthCheckoutReturnPathRef = useRef<string | null>(null);
const authCompletedRef = useRef(false);
const [licenseSuccessStatus, setLicenseSuccessStatus] = useState<LicenseSuccessStatus>('hidden');
const [dashboardReady, setDashboardReady] = useState(false);
// Keep a ref to the latest refreshAuth so the mount-only startup effect always
// calls the current implementation without re-running when the callback identity changes.
@ -266,7 +276,7 @@ export default function App() {
if (!completed) {
setPostAuthIntent(null);
postAuthCheckoutReturnPathRef.current = null;
if (isProtectedPage(activePageRef.current)) {
if (isAuthRequiredRoute(activePageRef.current)) {
window.history.replaceState({ page: 'home', hash: '' }, '', '/');
setRouteHash('');
setActivePage('home');
@ -517,7 +527,10 @@ export default function App() {
}
}, [activePage, fetchSearches]);
const isAuthRequiredPage = activePage === 'account' || activePage === 'saved';
const isAuthRequiredPage =
activePage === 'account' ||
activePage === 'saved' ||
(activePage === 'dashboard' && !mapUrlState.share);
useEffect(() => {
if (authLoading) return;
if (isAuthRequiredPage && !user) {
@ -530,6 +543,13 @@ export default function App() {
const [exportState, setExportState] = useState<ExportState | null>(null);
useEffect(() => {
if (activePage !== 'dashboard' || !user) {
setDashboardReady(false);
setExportState(null);
}
}, [activePage, user]);
if ((isScreenshotMode || isOgMode) && inviteCode) {
return (
<Suspense fallback={<PageFallback />}>
@ -584,8 +604,9 @@ export default function App() {
onPageChange={navigateTo}
theme={theme}
onToggleTheme={toggleTheme}
exportState={activePage === 'dashboard' ? exportState : null}
exportState={activePage === 'dashboard' && user ? exportState : null}
dashboardParams={activePage === 'dashboard' ? dashboardParams : ''}
dashboardActionsDisabled={activePage === 'dashboard' && !dashboardReady}
onSaveSearch={
activePage === 'dashboard' && user
? editingSearch
@ -675,6 +696,7 @@ export default function App() {
onNavigateTo={navigateTo}
onExportStateChange={setExportState}
onDashboardParamsChange={setDashboardParams}
onDashboardReadyChange={setDashboardReady}
isMobile={isMobile}
initialTravelTime={mapUrlState.travelTime}
initialPostcode={mapUrlState.postcode}