This commit is contained in:
seb
2026-09-23 17:24:33 +02:00
parent 0391e845f0
commit b331f8f535
17 changed files with 2352 additions and 202 deletions

View File

@@ -32,35 +32,10 @@ export function buildCategoryPath(categories, rootCategoryId, categoryId) {
return categoryPathFromCrumbs(crumbs);
}
export function resolveCategoryIdFromSlugPath(categories, rootCategoryId, slugPath) {
if (!categories || rootCategoryId == null) return null;
let segments = (slugPath ?? '')
.split('/')
.filter(Boolean)
.map((segment) => decodeURIComponent(segment));
// Legacy slug URLs: .../Home/...
if (segments[0] === ROOT_CATEGORY_NAME) {
segments = segments.slice(1);
}
if (segments.length === 0) {
return rootCategoryId;
}
let currentId = rootCategoryId;
for (const slug of segments) {
const children = getCategoryChildren(categories, currentId);
const match = children.find(
(child) => categorySlug(child, rootCategoryId) === slug,
);
if (!match) return null;
currentId = match.id;
}
return currentId;
}
export {
resolveCategoryIdFromSlugPath,
cleanCategorySlugPath,
} from '../../utils/categoryUtils';
export function defaultCategoryPath() {
return KATEGORIEN_BASE;

View File

@@ -25,7 +25,7 @@ import {
resolveCategoryIdFromSlugPath,
ROOT_CATEGORY_NAME,
} from './categoryRoute';
import categoryAutomat, { getOrCreateCategoryAutomat } from '../../automats/categoryAutomat';
import categoryAutomat from '../../automats/categoryAutomat';
import posterminalAutomat from '../../automats/posterminalAutomat';
import companyAutomat from '../../automats/companyAutomat';
import { setLastArticleSku } from '../../automats';
@@ -73,18 +73,19 @@ class ArtikelKategorienPage extends PureComponent {
);
}
this.routeAutomat = resolvedCategoryId != null
? getOrCreateCategoryAutomat({ slugPath: props.categorySlugPath, categoryId: resolvedCategoryId })
: null;
this.handle = categoryAutomat.key(props.categorySlugPath ?? '');
const view = this.handle?.state;
const catId = view?.data?.categoryId ?? resolvedCategoryId;
this.state = {
drafts: {},
...catState,
resolvedCategoryId,
articles: this.routeAutomat?.state?.articles ?? [],
loaded: this.routeAutomat?.state?.loaded ?? false,
loading: this.routeAutomat?.state?.loading ?? false,
routeError: this.routeAutomat?.state?.error ?? null,
resolvedCategoryId: catId,
articles: view?.data?.articles ?? [],
childCategories: view?.data?.childCategories ?? (catId != null ? getCategoryChildren(categories, catId) : []),
loaded: view?.loaded ?? false,
loading: view?.loading ?? false,
routeError: view?.error ?? null,
...selectTerminals(posterminalAutomat.state),
companyId: companyAutomat.state.current?.id ?? null,
moveCategory: null,
@@ -104,8 +105,7 @@ class ArtikelKategorienPage extends PureComponent {
}));
this.ensureTreeLoaded();
this.ensurePosterminalsLoaded();
this.syncCategoryFromUrl();
this.subscribeRouteAutomat();
this.subscribeViewHandle();
this.syncSortable();
}
@@ -135,20 +135,27 @@ class ArtikelKategorienPage extends PureComponent {
this._unsubCat?.();
this._unsubTerm?.();
this._unsubCompany?.();
this._unsubRoute?.();
this._unsubHandle?.();
this.sortableModule?.destroy();
}
subscribeRouteAutomat() {
this._unsubRoute?.();
this._unsubRoute = null;
if (this.routeAutomat) {
this._unsubRoute = this.routeAutomat.subscribe(this, (s) => ({
articles: s.articles,
loaded: s.loaded,
loading: s.loading,
routeError: s.error,
}));
subscribeViewHandle() {
this._unsubHandle?.();
this._unsubHandle = null;
if (this.handle) {
this._unsubHandle = this.handle.subscribe(this, (item) => {
const catId = item.data?.categoryId ?? this.state.resolvedCategoryId;
const categories = this.state.categories;
return {
resolvedCategoryId: catId,
articles: item.data?.articles ?? [],
childCategories: item.data?.childCategories ?? (catId != null ? getCategoryChildren(categories, catId) : []),
loaded: item.loaded,
loading: item.loading,
routeError: item.error,
};
});
void this.handle.load().catch(() => {});
}
}
@@ -217,23 +224,25 @@ class ArtikelKategorienPage extends PureComponent {
navigate(buildCategoryPath(categories, rootCategoryId, resolvedId), { replace: true });
}
const cleanSlug = (categorySlugPath ?? '').replace(/^\/+|\/+$/g, '');
const currentRouteSlug = this.routeAutomat?.state?.slug;
if (resolvedId !== resolvedCategoryId || cleanSlug !== currentRouteSlug || !this.routeAutomat) {
this._unsubRoute?.();
this.routeAutomat = getOrCreateCategoryAutomat({
slugPath: categorySlugPath,
categoryId: resolvedId,
const nextHandle = categoryAutomat.key(categorySlugPath ?? '');
if (this.handle !== nextHandle) {
this.handle = nextHandle;
const view = this.handle.state;
const catId = view?.data?.categoryId ?? resolvedId;
this.setState({
resolvedCategoryId: catId,
articles: view?.data?.articles ?? [],
childCategories: view?.data?.childCategories ?? (catId != null ? getCategoryChildren(categories, catId) : []),
loaded: view?.loaded ?? false,
loading: view?.loading ?? false,
routeError: view?.error ?? null,
});
this.subscribeViewHandle();
} else if (resolvedId !== resolvedCategoryId) {
this.setState({
resolvedCategoryId: resolvedId,
articles: this.routeAutomat?.state?.articles ?? [],
loaded: this.routeAutomat?.state?.loaded ?? false,
loading: this.routeAutomat?.state?.loading ?? false,
routeError: this.routeAutomat?.state?.error ?? null,
childCategories: getCategoryChildren(categories, resolvedId),
});
this.subscribeRouteAutomat();
}
};
@@ -294,14 +303,8 @@ class ArtikelKategorienPage extends PureComponent {
};
handleRetryArticles = () => {
if (this.routeAutomat) {
if (typeof this.routeAutomat.retry === 'function') {
void this.routeAutomat.retry();
} else if (typeof this.routeAutomat.actions?.retry === 'function') {
void this.routeAutomat.actions.retry();
} else {
void this.routeAutomat.setDirty({ keep: false, now: true });
}
if (this.handle) {
void this.handle.reload().catch(() => {});
}
};
@@ -369,7 +372,10 @@ class ArtikelKategorienPage extends PureComponent {
}
const breadcrumbs = getCategoryBreadcrumbs(categories, resolvedCategoryId, rootCategoryId);
const childCategories = getCategoryChildren(categories, resolvedCategoryId);
const childCategories =
this.state.childCategories && this.state.childCategories.length > 0
? this.state.childCategories
: getCategoryChildren(categories, resolvedCategoryId);
const canGoBack =
resolvedCategoryId != null &&
rootCategoryId != null &&