From a7d763a54225ec24af07b851469c903347670fe1 Mon Sep 17 00:00:00 2001 From: MHSanaei Date: Sun, 31 May 2026 01:00:00 +0200 Subject: [PATCH] fix(clients): persist sort selection across navigation The clients page saved searchKey and filters to localStorage but not the sort selection, so leaving the page and returning reset sort to the default (Oldest). Persist the chosen sort alongside the existing filter state and restore it on mount, matching the filter-persistence pattern. --- frontend/.gitignore | 1 + frontend/src/pages/clients/ClientsPage.tsx | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/.gitignore b/frontend/.gitignore index 4e97a76e..e5dc0854 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,3 +1,4 @@ node_modules/ .vite/ *.log +*.tsbuildinfo diff --git a/frontend/src/pages/clients/ClientsPage.tsx b/frontend/src/pages/clients/ClientsPage.tsx index 44ca73e7..5ceefa06 100644 --- a/frontend/src/pages/clients/ClientsPage.tsx +++ b/frontend/src/pages/clients/ClientsPage.tsx @@ -115,6 +115,7 @@ type Bucket = 'active' | 'deactive' | 'depleted' | 'expiring'; interface PersistedFilterState { searchKey: string; filters: ClientFilters; + sort: string; } const INBOUND_PROTOCOL_COLORS: Record = { @@ -145,9 +146,10 @@ function readFilterState(): PersistedFilterState { inboundIds: Array.isArray(fromRaw.inboundIds) ? fromRaw.inboundIds : [], groups: Array.isArray(fromRaw.groups) ? fromRaw.groups : [], }, + sort: typeof raw.sort === 'string' ? raw.sort : '', }; } catch { - return { searchKey: '', filters: emptyFilters() }; + return { searchKey: '', filters: emptyFilters(), sort: '' }; } } @@ -224,8 +226,9 @@ export default function ClientsPage() { const [filters, setFilters] = useState(initial.filters); const [filterDrawerOpen, setFilterDrawerOpen] = useState(false); - const [sortColumn, setSortColumn] = useState(DEFAULT_SORT.column); - const [sortOrder, setSortOrder] = useState<'ascend' | 'descend' | null>(DEFAULT_SORT.order); + const initialSort = SORT_OPTIONS.find((o) => o.value === initial.sort) ?? DEFAULT_SORT; + const [sortColumn, setSortColumn] = useState(initialSort.column); + const [sortOrder, setSortOrder] = useState<'ascend' | 'descend' | null>(initialSort.order); const [currentPage, setCurrentPage] = useState(1); const [tablePageSize, setTablePageSize] = useState(25); // debouncedSearch lags behind the input so we don't spam the server on every @@ -233,8 +236,8 @@ export default function ClientsPage() { const [debouncedSearch, setDebouncedSearch] = useState(searchKey); useEffect(() => { - localStorage.setItem(FILTER_STATE_KEY, JSON.stringify({ searchKey, filters })); - }, [searchKey, filters]); + localStorage.setItem(FILTER_STATE_KEY, JSON.stringify({ searchKey, filters, sort: sortValueFor(sortColumn, sortOrder) })); + }, [searchKey, filters, sortColumn, sortOrder]); useEffect(() => { const handle = window.setTimeout(() => setDebouncedSearch(searchKey), 300);