From c130e9a0cca0409a3731569db56768d37178aebf Mon Sep 17 00:00:00 2001 From: Tam Nhu Tran Date: Thu, 26 Feb 2026 21:37:43 +0700 Subject: [PATCH 1/2] fix(ui): keep home route at root without last-route redirect --- ui/src/App.tsx | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 13811346..62ecb304 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -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 ; - } - - return ; -} - export default function App() { return ( @@ -71,7 +61,7 @@ export default function App() { {/* Protected routes: wrapped with RequireAuth */} }> }> - } /> + } /> Date: Thu, 26 Feb 2026 21:48:55 +0700 Subject: [PATCH 2/2] refactor(ui): remove unused last-route restore helpers --- ui/src/lib/last-route.ts | 28 -------------------- ui/tests/unit/ui/lib/last-route.test.ts | 34 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 28 deletions(-) create mode 100644 ui/tests/unit/ui/lib/last-route.test.ts diff --git a/ui/src/lib/last-route.ts b/ui/src/lib/last-route.ts index 26589822..a071f7b7 100644 --- a/ui/src/lib/last-route.ts +++ b/ui/src/lib/last-route.ts @@ -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); -} diff --git a/ui/tests/unit/ui/lib/last-route.test.ts b/ui/tests/unit/ui/lib/last-route.test.ts new file mode 100644 index 00000000..19548c6b --- /dev/null +++ b/ui/tests/unit/ui/lib/last-route.test.ts @@ -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(); + }); +});