fix: properly sync category lists when article categories change
- Update patchArticleInLists reducer to add/remove articles from category lists - Articles are now correctly added to rootArticles and current category's articles - Articles are correctly removed when no longer in a category - Remove unnecessary loadCategoryTree dispatch (reducer handles sync now)
This commit is contained in:
@@ -12,6 +12,8 @@ import {
|
|||||||
patchArticleInLists,
|
patchArticleInLists,
|
||||||
removeArticleBySku,
|
removeArticleBySku,
|
||||||
selectCategoryRootId,
|
selectCategoryRootId,
|
||||||
|
loadCategoryArticles,
|
||||||
|
selectCurrentCategoryId,
|
||||||
} from '../../store/categorySlice';
|
} from '../../store/categorySlice';
|
||||||
|
|
||||||
import ArticleTileTab from './ArticleTileTab';
|
import ArticleTileTab from './ArticleTileTab';
|
||||||
@@ -33,6 +35,7 @@ export default function ArticleView({
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const categories = useSelector((state) => state.category.categories);
|
const categories = useSelector((state) => state.category.categories);
|
||||||
const rootCategoryId = useSelector(selectCategoryRootId);
|
const rootCategoryId = useSelector(selectCategoryRootId);
|
||||||
|
const currentCategoryId = useSelector(selectCurrentCategoryId);
|
||||||
|
|
||||||
const syncCategoryListPhoto = (next) => {
|
const syncCategoryListPhoto = (next) => {
|
||||||
const photo = primaryPhoto(next);
|
const photo = primaryPhoto(next);
|
||||||
@@ -57,6 +60,12 @@ export default function ArticleView({
|
|||||||
categoryIds: next.categoryIds,
|
categoryIds: next.categoryIds,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Reload articles to reflect the update
|
||||||
|
// The reducer handles removing from lists where article no longer belongs
|
||||||
|
if (currentCategoryId != null && String(currentCategoryId) !== String(rootCategoryId)) {
|
||||||
|
dispatch(loadCategoryArticles(currentCategoryId));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleArticleDeleted = () => {
|
const handleArticleDeleted = () => {
|
||||||
|
|||||||
@@ -343,14 +343,55 @@ const categorySlice = createSlice({
|
|||||||
state.articlesTotal = state.articles.length;
|
state.articlesTotal = state.articles.length;
|
||||||
state.rootArticles = state.rootArticles.filter((row) => row.sku !== sku);
|
state.rootArticles = state.rootArticles.filter((row) => row.sku !== sku);
|
||||||
},
|
},
|
||||||
/** Keep category tile list in sync with article detail (e.g. after photo upload). */
|
/** Keep category tile list in sync with article detail (e.g. after photo upload or category change). */
|
||||||
patchArticleInLists(state, action) {
|
patchArticleInLists(state, action) {
|
||||||
const { sku, ...fields } = action.payload;
|
const { sku, categoryIds, ...fields } = action.payload;
|
||||||
if (sku == null) return;
|
if (sku == null) return;
|
||||||
|
|
||||||
|
// Merge fields into existing article in both lists
|
||||||
const patchList = (list) =>
|
const patchList = (list) =>
|
||||||
list.map((row) => (row.sku === sku ? { ...row, ...fields } : row));
|
list.map((row) => {
|
||||||
|
if (row.sku !== sku) return row;
|
||||||
|
return { ...row, ...fields };
|
||||||
|
});
|
||||||
state.articles = patchList(state.articles);
|
state.articles = patchList(state.articles);
|
||||||
state.rootArticles = patchList(state.rootArticles);
|
state.rootArticles = patchList(state.rootArticles);
|
||||||
|
|
||||||
|
if (categoryIds === undefined) return;
|
||||||
|
const newCategoryIds = categoryIds ?? [];
|
||||||
|
|
||||||
|
// Helper: find the article object in either list
|
||||||
|
const findArticle = (list) => list.find((row) => row.sku === sku);
|
||||||
|
const articleObj = findArticle(state.articles) || findArticle(state.rootArticles);
|
||||||
|
if (!articleObj) return;
|
||||||
|
|
||||||
|
// Handle root category membership
|
||||||
|
if (state.rootCategoryId != null) {
|
||||||
|
const inRootCategory = newCategoryIds.some(
|
||||||
|
(id) => String(id) === String(state.rootCategoryId),
|
||||||
|
);
|
||||||
|
const alreadyInRoot = state.rootArticles.some((row) => row.sku === sku);
|
||||||
|
if (!inRootCategory) {
|
||||||
|
state.rootArticles = state.rootArticles.filter((row) => row.sku !== sku);
|
||||||
|
} else if (!alreadyInRoot) {
|
||||||
|
state.rootArticles = [...state.rootArticles, articleObj];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle current category membership
|
||||||
|
if (state.currentCategoryId != null) {
|
||||||
|
const inCurrentCategory = newCategoryIds.some(
|
||||||
|
(id) => String(id) === String(state.currentCategoryId),
|
||||||
|
);
|
||||||
|
const alreadyInCurrent = state.articles.some((row) => row.sku === sku);
|
||||||
|
if (!inCurrentCategory) {
|
||||||
|
state.articles = state.articles.filter((row) => row.sku !== sku);
|
||||||
|
state.articlesTotal = state.articles.length;
|
||||||
|
} else if (!alreadyInCurrent) {
|
||||||
|
state.articles = [...state.articles, articleObj];
|
||||||
|
state.articlesTotal = state.articles.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extraReducers: (builder) => {
|
extraReducers: (builder) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user