From 4bbe9caf55a182b9f74295b48460e13003335b15 Mon Sep 17 00:00:00 2001 From: seb Date: Mon, 3 Aug 2026 07:22:08 +0200 Subject: [PATCH] Directly patch posterminalIds in Redux instead of reloading the category tree After toggling a POS category, update the category's posterminalIds array in-place rather than re-fetching the entire tree. This keeps the settings cycle open on the same terminal. Also fix off-by-one in terminal cycling and ensure posterminals load on category page mount. --- src/components/tiles/CategoryTile.jsx | 2 +- src/pages/artikel/kategorien.jsx | 20 ++++++++++++++++++-- src/store/categorySlice.js | 12 ++++++++++++ src/store/posterminalSlice.js | 3 ++- 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/components/tiles/CategoryTile.jsx b/src/components/tiles/CategoryTile.jsx index 57ab7dd..20f2002 100644 --- a/src/components/tiles/CategoryTile.jsx +++ b/src/components/tiles/CategoryTile.jsx @@ -283,7 +283,7 @@ export class CategoryEditTile extends Component { const terminalCount = terminals?.length || 0; this.setState((prev) => { const next = prev.settingsTab + 1; - const nextTab = next > terminalCount ? -1 : next; + const nextTab = next >= terminalCount ? -1 : next; console.log('[CategoryEditTile] settings toggle', { terminals: terminals?.length, terminalCount, diff --git a/src/pages/artikel/kategorien.jsx b/src/pages/artikel/kategorien.jsx index 9731fed..871b86d 100644 --- a/src/pages/artikel/kategorien.jsx +++ b/src/pages/artikel/kategorien.jsx @@ -21,7 +21,7 @@ import { import withCategoryRoute from './withCategoryRoute'; import { artikelDetailPath, articleSku } from './articleRoute'; import { selectCompanyId } from '../../store/companySlice'; -import { selectHasPosterminals, selectPosterminals } from '../../store/posterminalSlice'; +import { selectHasPosterminals, selectPosterminals, loadPosterminals } from '../../store/posterminalSlice'; import { buildCategoryPath, defaultCategoryPath, @@ -47,6 +47,7 @@ import { selectCategoryTreeStatus, selectChildCategories, selectRenameMode, + patchCategoryPosterminalIds, } from '../../store/categorySlice'; import { enableTerminalCategory, @@ -72,6 +73,7 @@ class ArtikelKategorienPage extends Component { componentDidMount() { this.ensureTreeLoaded(); + this.ensurePosterminalsLoaded(); this.syncCategoryFromUrl(); this.ensureArticlesLoaded(); this.syncSortable(); @@ -158,6 +160,12 @@ class ArtikelKategorienPage extends Component { this.props.loadCategoryTree(); }; + ensurePosterminalsLoaded = () => { + const { companyId } = this.props; + if (!companyId) return; + this.props.loadPosterminals(); + }; + ensureArticlesLoaded = () => { const { currentCategoryId, articlesStatus, rootCategoryId, treeStatus } = this.props; if (treeStatus !== 'succeeded' || !currentCategoryId || articlesStatus !== 'idle') return; @@ -356,7 +364,13 @@ class ArtikelKategorienPage extends Component { : this.props.disableTerminalCategory; void thunk({ terminalId, categoryId: item.id }) .unwrap() - .then(() => this.props.loadCategoryTree()) + .then(() => { + this.props.patchCategoryPosterminalIds({ + categoryId: item.id, + terminalId, + enabled, + }); + }) .catch(notifyError); }} onOpen={() => this.navigateToCategoryById(item.id)} @@ -456,6 +470,7 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = { loadCategoryTree, loadCategoryArticles, + loadPosterminals, navigateToCategory, renameCategory, deleteCategory, @@ -464,6 +479,7 @@ const mapDispatchToProps = { toggleCategoryPos, enableTerminalCategory, disableTerminalCategory, + patchCategoryPosterminalIds, }; export default withCategoryRoute(connect(mapStateToProps, mapDispatchToProps)(ArtikelKategorienPage)); diff --git a/src/store/categorySlice.js b/src/store/categorySlice.js index 7dd97ea..15d9c80 100644 --- a/src/store/categorySlice.js +++ b/src/store/categorySlice.js @@ -291,6 +291,17 @@ const categorySlice = createSlice({ resetCategoryState() { return initialState; }, + patchCategoryPosterminalIds(state, action) { + const { categoryId, terminalId, enabled } = action.payload; + const cat = state.categories?.[String(categoryId)]; + if (!cat) return; + if (!Array.isArray(cat.posterminalIds)) cat.posterminalIds = []; + if (enabled && !cat.posterminalIds.includes(terminalId)) { + cat.posterminalIds.push(terminalId); + } else if (!enabled) { + cat.posterminalIds = cat.posterminalIds.filter((id) => id !== terminalId); + } + }, setRenameMode(state, action) { state.renameMode = Boolean(action.payload); }, @@ -451,6 +462,7 @@ export const { setRenameMode, removeArticleBySku, patchArticleInLists, + patchCategoryPosterminalIds, } = categorySlice.actions; export const selectRenameMode = (state) => state.category.renameMode; diff --git a/src/store/posterminalSlice.js b/src/store/posterminalSlice.js index 7dc5bda..c6c2d91 100644 --- a/src/store/posterminalSlice.js +++ b/src/store/posterminalSlice.js @@ -253,8 +253,9 @@ export function posterminalLoadListener(listenerMiddleware) { loginWithGoogle.fulfilled.match(action) || selectCompany.fulfilled.match(action) || createCompany.fulfilled.match(action), - effect: async (_action, api) => { + effect: async (action, api) => { const companyId = api.getState().auth.user?.selectedCompanyId; + console.log('[posterminalLoadListener]', action.type, { companyId }); if (companyId) { api.dispatch(loadPosterminals()); }