From cf4b338cd44c331a7fa06844463a81aa8f3e446e Mon Sep 17 00:00:00 2001 From: Forgotten Date: Mon, 23 Feb 2026 14:47:54 -0600 Subject: [PATCH] feat(ui): remember last visited page per company on company switch When switching companies via the sidebar rail, dropdown, or keyboard shortcuts, the app now navigates to the last page visited for that company instead of staying on the current (now irrelevant) page. Falls back to /dashboard if no previous page exists. Co-Authored-By: Claude Opus 4.6 --- ui/src/components/Layout.tsx | 3 ++ ui/src/hooks/useCompanyPageMemory.ts | 58 ++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 ui/src/hooks/useCompanyPageMemory.ts diff --git a/ui/src/components/Layout.tsx b/ui/src/components/Layout.tsx index 19e7e5cb..9bad4a0b 100644 --- a/ui/src/components/Layout.tsx +++ b/ui/src/components/Layout.tsx @@ -19,6 +19,7 @@ import { usePanel } from "../context/PanelContext"; import { useCompany } from "../context/CompanyContext"; import { useSidebar } from "../context/SidebarContext"; import { useKeyboardShortcuts } from "../hooks/useKeyboardShortcuts"; +import { useCompanyPageMemory } from "../hooks/useCompanyPageMemory"; import { healthApi } from "../api/health"; import { queryKeys } from "../lib/queryKeys"; import { cn } from "../lib/utils"; @@ -58,6 +59,8 @@ export function Layout() { [companies, setSelectedCompanyId], ); + useCompanyPageMemory(); + useKeyboardShortcuts({ onNewIssue: () => openNewIssue(), onToggleSidebar: toggleSidebar, diff --git a/ui/src/hooks/useCompanyPageMemory.ts b/ui/src/hooks/useCompanyPageMemory.ts new file mode 100644 index 00000000..e28a636f --- /dev/null +++ b/ui/src/hooks/useCompanyPageMemory.ts @@ -0,0 +1,58 @@ +import { useEffect, useRef } from "react"; +import { useLocation, useNavigate } from "react-router-dom"; +import { useCompany } from "../context/CompanyContext"; + +const STORAGE_KEY = "paperclip.companyPaths"; + +function getCompanyPaths(): Record { + try { + const raw = localStorage.getItem(STORAGE_KEY); + if (raw) return JSON.parse(raw); + } catch { + /* ignore */ + } + return {}; +} + +function saveCompanyPath(companyId: string, path: string) { + const paths = getCompanyPaths(); + paths[companyId] = path; + localStorage.setItem(STORAGE_KEY, JSON.stringify(paths)); +} + +/** + * Remembers the last visited page per company and navigates to it on company switch. + * Falls back to /dashboard if no page was previously visited for a company. + */ +export function useCompanyPageMemory() { + const { selectedCompanyId } = useCompany(); + const location = useLocation(); + const navigate = useNavigate(); + const prevCompanyId = useRef(selectedCompanyId); + + // Save current path for current company on every location change. + // Uses prevCompanyId ref so we save under the correct company even + // during the render where selectedCompanyId has already changed. + const fullPath = location.pathname + location.search; + useEffect(() => { + const companyId = prevCompanyId.current; + if (companyId) { + saveCompanyPath(companyId, fullPath); + } + }, [fullPath]); + + // Navigate to saved path when company changes + useEffect(() => { + if (!selectedCompanyId) return; + + if ( + prevCompanyId.current !== null && + selectedCompanyId !== prevCompanyId.current + ) { + const paths = getCompanyPaths(); + const savedPath = paths[selectedCompanyId]; + navigate(savedPath || "/dashboard", { replace: true }); + } + prevCompanyId.current = selectedCompanyId; + }, [selectedCompanyId, navigate]); +}