From 3d2e40518b33441691812a802cfe981fd622df4d Mon Sep 17 00:00:00 2001 From: rstubryan Date: Tue, 3 Mar 2026 10:33:03 +0700 Subject: [PATCH] refactor(FE): Add table state management with path grouping logic --- src/stores/ui/slices/table.slice.ts | 55 ++++++++++++++++++++++++++--- src/stores/ui/ui.store.ts | 5 ++- src/types/stores.d.ts | 8 +++++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/stores/ui/slices/table.slice.ts b/src/stores/ui/slices/table.slice.ts index eb6e7cc2..bf9a8686 100644 --- a/src/stores/ui/slices/table.slice.ts +++ b/src/stores/ui/slices/table.slice.ts @@ -1,13 +1,34 @@ import { StateCreator } from 'zustand'; +import { TableUISlice } from '@/types/stores'; export interface TableState { + key: string; + path: string; searchValue: string; } -export interface TableUISlice { - searchValue: string; - setSearchValue: (value: string) => void; - resetSearchValue: () => void; +function getPathGroup(path: string): string { + const segments = path.split('/').filter(Boolean); + const subPaths = ['add', 'detail', 'edit']; + const lastSegment = segments[segments.length - 1]; + + // If last segment is a sub-path or numeric ID, remove it + if ( + lastSegment && + (subPaths.includes(lastSegment) || /^\d+$/.test(lastSegment)) + ) { + segments.pop(); + } + + return segments.length > 0 ? '/' + segments.join('/') : path; +} + +function isSamePathGroup( + currentPath: string, + previousPath: string | null +): boolean { + if (!previousPath) return false; + return getPathGroup(currentPath) === getPathGroup(previousPath); } export const createTableUISlice: StateCreator< @@ -17,7 +38,10 @@ export const createTableUISlice: StateCreator< TableUISlice > = (set) => ({ // Initial state + key: '', + path: '', searchValue: '', + previousPath: null, // Actions setSearchValue: (value) => set({ searchValue: value }), @@ -25,4 +49,27 @@ export const createTableUISlice: StateCreator< resetSearchValue: () => { return set({ searchValue: '' }); }, + + setTableState: (key, path, searchValue = '') => { + set((state) => { + const isSameGroup = isSamePathGroup(path, state.path); + + return { + key, + path, + previousPath: state.path, + // Reset search if path group changed, otherwise keep existing search + searchValue: isSameGroup ? state.searchValue : searchValue, + }; + }); + }, + + resetTableState: () => { + set({ + key: '', + path: '', + searchValue: '', + previousPath: null, + }); + }, }); diff --git a/src/stores/ui/ui.store.ts b/src/stores/ui/ui.store.ts index 46c70283..4b8379db 100644 --- a/src/stores/ui/ui.store.ts +++ b/src/stores/ui/ui.store.ts @@ -19,9 +19,12 @@ export const useUiStore = create()( ...createNavbarActionsSlice(...args), }), { - name: 'ui-cache', + name: 'search-store', partialize: (state) => ({ + key: state.key, + path: state.path, searchValue: state.searchValue, + previousPath: state.previousPath, }), } ), diff --git a/src/types/stores.d.ts b/src/types/stores.d.ts index c358e2a1..331bbb82 100644 --- a/src/types/stores.d.ts +++ b/src/types/stores.d.ts @@ -28,9 +28,17 @@ type DrawerUISlice = { }; type TableUISlice = { + // State + key: string; + path: string; searchValue: string; + previousPath: string | null; + + // Actions setSearchValue: (value: string) => void; resetSearchValue: () => void; + setTableState: (key: string, path: string, searchValue?: string) => void; + resetTableState: () => void; }; // Navbar Actions Slice