Merge pull request #642 from kaitranntt/kai/fix/home-route-no-last-restore

fix(ui): keep home route at root without last-route redirect
This commit is contained in:
Kai (Tam Nhu) Tran authored and GitHub committed 2026-02-26 10:00:52 -05:00
commit bf198e4af0
3 files changed
+36 -40

No files matched your search

+2 -12
View File
@@ -1,5 +1,5 @@
import { lazy, Suspense } from 'react';
import { BrowserRouter, Navigate, Routes, Route } from 'react-router-dom';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { QueryClientProvider } from '@tanstack/react-query';
import { Toaster } from 'sonner';
import { queryClient } from '@/lib/query-client';
@@ -8,7 +8,6 @@ import { PrivacyProvider } from '@/contexts/privacy-context';
import { AuthProvider } from '@/contexts/auth-context';
import { RequireAuth } from '@/components/auth/require-auth';
import { Layout } from '@/components/layout/layout';
import { getStoredLastRoute, shouldRestoreRoute } from '@/lib/last-route';
import { Loader2 } from 'lucide-react';
// Eager load: HomePage (initial route) + LoginPage (auth flow)
@@ -48,15 +47,6 @@ function PageLoader() {
);
}
function HomeEntryRoute() {
const lastRoute = getStoredLastRoute();
if (shouldRestoreRoute(lastRoute)) {
return <Navigate to={lastRoute} replace />;
}
return <HomePage />;
}
export default function App() {
return (
<QueryClientProvider client={queryClient}>
@@ -71,7 +61,7 @@ export default function App() {
{/* Protected routes: wrapped with RequireAuth */}
<Route element={<RequireAuth />}>
<Route element={<Layout />}>
<Route path="/" element={<HomeEntryRoute />} />
<Route path="/" element={<HomePage />} />
<Route
path="/analytics"
element={
-28
View File
@@ -1,5 +1,4 @@
const LAST_ROUTE_STORAGE_KEY = 'ccs-dashboard:last-route';
const NON_RESTORABLE_PATHS = new Set(['/login']);
export function storeLastRoute(pathname: string, search = '', hash = ''): void {
try {
@@ -8,30 +7,3 @@ export function storeLastRoute(pathname: string, search = '', hash = ''): void {
// Ignore storage failures (private mode, quota, etc.)
}
}
export function getStoredLastRoute(): string | null {
try {
const route = localStorage.getItem(LAST_ROUTE_STORAGE_KEY);
if (!route || !route.startsWith('/')) {
return null;
}
const pathOnly = route.split(/[?#]/, 1)[0];
if (NON_RESTORABLE_PATHS.has(pathOnly)) {
return null;
}
return route;
} catch {
return null;
}
}
export function shouldRestoreRoute(route: string | null): route is string {
if (!route) {
return false;
}
const pathOnly = route.split(/[?#]/, 1)[0];
return pathOnly !== '/' && !NON_RESTORABLE_PATHS.has(pathOnly);
}
+34
View File
@@ -0,0 +1,34 @@
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { storeLastRoute } from '@/lib/last-route';
const LAST_ROUTE_STORAGE_KEY = 'ccs-dashboard:last-route';
describe('storeLastRoute', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('writes pathname with search and hash', () => {
storeLastRoute('/accounts', '?tab=auth', '#matrix');
expect(localStorage.setItem).toHaveBeenCalledWith(
LAST_ROUTE_STORAGE_KEY,
'/accounts?tab=auth#matrix'
);
});
it('writes pathname when search and hash are omitted', () => {
storeLastRoute('/health');
expect(localStorage.setItem).toHaveBeenCalledWith(LAST_ROUTE_STORAGE_KEY, '/health');
});
it('does not throw when localStorage write fails', () => {
const setItemSpy = vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {
throw new Error('quota exceeded');
});
expect(() => storeLastRoute('/providers')).not.toThrow();
setItemSpy.mockRestore();
});
});