no redux
This commit is contained in:
@@ -24,7 +24,7 @@ import {
|
||||
resolveCategoryIdFromSlugPath,
|
||||
ROOT_CATEGORY_NAME,
|
||||
} from './categoryRoute';
|
||||
import categoryAutomat from '../../automats/categoryAutomat';
|
||||
import categoryAutomat, { getOrCreateCategoryAutomat } from '../../automats/categoryAutomat';
|
||||
import posterminalAutomat from '../../automats/posterminalAutomat';
|
||||
import companyAutomat from '../../automats/companyAutomat';
|
||||
import { setLastArticleSku } from '../../automats';
|
||||
@@ -37,29 +37,13 @@ import {
|
||||
|
||||
// ─── Helper selectors for this page ────────────────────────────────────────────
|
||||
function selectFromCategory(s) {
|
||||
const { categories, rootCategoryId, currentCategoryId, articles, articlesTotal, renameMode, treeStatus, articlesStatus, error } = s;
|
||||
const breadcrumbs = getCategoryBreadcrumbs(categories, currentCategoryId, rootCategoryId);
|
||||
const childCategories = getCategoryChildren(categories, currentCategoryId);
|
||||
const canGoBack =
|
||||
currentCategoryId != null &&
|
||||
rootCategoryId != null &&
|
||||
String(currentCategoryId) !== String(rootCategoryId) &&
|
||||
categories?.[String(currentCategoryId)]?.parentId != null &&
|
||||
categories[String(currentCategoryId)].parentId !== 0;
|
||||
|
||||
const { categories, rootCategoryId, renameMode, treeStatus, error } = s;
|
||||
return {
|
||||
categories,
|
||||
rootCategoryId,
|
||||
treeStatus,
|
||||
articlesStatus,
|
||||
error,
|
||||
currentCategoryId,
|
||||
breadcrumbs,
|
||||
childCategories,
|
||||
articles,
|
||||
articlesTotal,
|
||||
canGoBack,
|
||||
renameMode,
|
||||
treeStatus,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -76,9 +60,30 @@ const gridSx = {
|
||||
class ArtikelKategorienPage extends PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const catState = selectFromCategory(categoryAutomat.state);
|
||||
const { categories, rootCategoryId, treeStatus } = catState;
|
||||
|
||||
let resolvedCategoryId = null;
|
||||
if (treeStatus === 'succeeded' && categories && rootCategoryId != null) {
|
||||
resolvedCategoryId = resolveCategoryIdFromSlugPath(
|
||||
categories,
|
||||
rootCategoryId,
|
||||
props.categorySlugPath,
|
||||
);
|
||||
}
|
||||
|
||||
this.routeAutomat = resolvedCategoryId != null
|
||||
? getOrCreateCategoryAutomat({ slugPath: props.categorySlugPath, categoryId: resolvedCategoryId })
|
||||
: null;
|
||||
|
||||
this.state = {
|
||||
drafts: {},
|
||||
...selectFromCategory(categoryAutomat.state),
|
||||
...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,
|
||||
...selectTerminals(posterminalAutomat.state),
|
||||
companyId: companyAutomat.state.current?.id ?? null,
|
||||
moveCategory: null,
|
||||
@@ -99,31 +104,28 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
this.ensureTreeLoaded();
|
||||
this.ensurePosterminalsLoaded();
|
||||
this.syncCategoryFromUrl();
|
||||
this.ensureArticlesLoaded();
|
||||
this.subscribeRouteAutomat();
|
||||
this.syncSortable();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevState) {
|
||||
// Note: PureComponent — comparisons use this.state not this.props
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (this.state.companyId !== prevState.companyId) {
|
||||
this.ensureTreeLoaded();
|
||||
}
|
||||
if (this.state.treeStatus === 'succeeded' && prevState.treeStatus !== 'succeeded') {
|
||||
this.syncCategoryFromUrl();
|
||||
this.ensureArticlesLoaded();
|
||||
}
|
||||
if (
|
||||
this.state.treeStatus === 'succeeded' &&
|
||||
this.props.categorySlugPath !== (this._prevSlugPath ?? this.props.categorySlugPath)
|
||||
this.props.categorySlugPath !== prevProps.categorySlugPath ||
|
||||
this.state.categories !== prevState.categories ||
|
||||
this.state.rootCategoryId !== prevState.rootCategoryId
|
||||
) {
|
||||
this.syncCategoryFromUrl();
|
||||
}
|
||||
this._prevSlugPath = this.props.categorySlugPath;
|
||||
|
||||
if (this.state.currentCategoryId !== prevState.currentCategoryId) {
|
||||
this.ensureArticlesLoaded();
|
||||
}
|
||||
if (this.state.renameMode !== prevState.renameMode) {
|
||||
if (
|
||||
this.state.renameMode !== prevState.renameMode ||
|
||||
(this.state.renameMode && this.state.resolvedCategoryId !== prevState.resolvedCategoryId)
|
||||
) {
|
||||
this.syncSortable();
|
||||
}
|
||||
}
|
||||
@@ -132,16 +134,33 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
this._unsubCat?.();
|
||||
this._unsubTerm?.();
|
||||
this._unsubCompany?.();
|
||||
this._unsubRoute?.();
|
||||
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,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
#ensureModules = () => {
|
||||
const el = this.gridRef.current;
|
||||
if (!el) return;
|
||||
if (!this.sortableModule) {
|
||||
this.sortableModule = new CategorySortable(el, {
|
||||
onReorder: ({ categoryIds }) =>
|
||||
categoryAutomat.actions.reorderCategories({ categoryIds }),
|
||||
categoryAutomat.actions.reorderCategories({
|
||||
parentId: this.state.resolvedCategoryId,
|
||||
categoryIds,
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -168,19 +187,12 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
void posterminalAutomat.actions.load();
|
||||
};
|
||||
|
||||
ensureArticlesLoaded = () => {
|
||||
const { currentCategoryId, articlesStatus, rootCategoryId, treeStatus } = this.state;
|
||||
if (treeStatus !== 'succeeded' || !currentCategoryId || articlesStatus !== 'idle') return;
|
||||
if (String(currentCategoryId) === String(rootCategoryId)) return;
|
||||
void categoryAutomat.actions.loadArticles(currentCategoryId);
|
||||
};
|
||||
|
||||
syncCategoryFromUrl = () => {
|
||||
const {
|
||||
categories,
|
||||
rootCategoryId,
|
||||
currentCategoryId,
|
||||
treeStatus,
|
||||
resolvedCategoryId,
|
||||
} = this.state;
|
||||
const { categorySlugPath, navigate } = this.props;
|
||||
|
||||
@@ -204,8 +216,23 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
navigate(buildCategoryPath(categories, rootCategoryId, resolvedId), { replace: true });
|
||||
}
|
||||
|
||||
if (resolvedId !== currentCategoryId) {
|
||||
categoryAutomat.actions.navigateTo(resolvedId);
|
||||
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,
|
||||
});
|
||||
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,
|
||||
});
|
||||
this.subscribeRouteAutomat();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -266,14 +293,20 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
};
|
||||
|
||||
handleRetryArticles = () => {
|
||||
const { currentCategoryId } = this.state;
|
||||
if (currentCategoryId) {
|
||||
void categoryAutomat.actions.loadArticles(currentCategoryId);
|
||||
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 });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
handleNavigateBack = () => {
|
||||
const { breadcrumbs } = this.state;
|
||||
const { categories, resolvedCategoryId, rootCategoryId } = this.state;
|
||||
const breadcrumbs = getCategoryBreadcrumbs(categories, resolvedCategoryId, rootCategoryId);
|
||||
if (breadcrumbs.length < 2) return;
|
||||
this.navigateToCategoryById(breadcrumbs[breadcrumbs.length - 2].id);
|
||||
};
|
||||
@@ -289,13 +322,12 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
categories,
|
||||
rootCategoryId,
|
||||
treeStatus,
|
||||
articlesStatus,
|
||||
error,
|
||||
canGoBack,
|
||||
breadcrumbs,
|
||||
currentCategoryId,
|
||||
childCategories,
|
||||
resolvedCategoryId,
|
||||
articles,
|
||||
loaded,
|
||||
loading,
|
||||
routeError,
|
||||
renameMode,
|
||||
terminals,
|
||||
drafts,
|
||||
@@ -335,7 +367,16 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
);
|
||||
}
|
||||
|
||||
const showArticlesLoading = articlesStatus === 'loading';
|
||||
const breadcrumbs = getCategoryBreadcrumbs(categories, resolvedCategoryId, rootCategoryId);
|
||||
const childCategories = getCategoryChildren(categories, resolvedCategoryId);
|
||||
const canGoBack =
|
||||
resolvedCategoryId != null &&
|
||||
rootCategoryId != null &&
|
||||
String(resolvedCategoryId) !== String(rootCategoryId) &&
|
||||
categories?.[String(resolvedCategoryId)]?.parentId != null &&
|
||||
categories[String(resolvedCategoryId)].parentId !== 0;
|
||||
|
||||
const showArticlesLoading = loading;
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -344,9 +385,9 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
onNavigate={this.navigateToCategoryById}
|
||||
/>
|
||||
|
||||
{error && articlesStatus === 'failed' && (
|
||||
{routeError && (
|
||||
<BackendError
|
||||
error={error}
|
||||
error={routeError}
|
||||
sx={{ mb: 2 }}
|
||||
onRetry={this.handleRetryArticles}
|
||||
/>
|
||||
@@ -356,12 +397,12 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
{canGoBack && (
|
||||
<BackTile
|
||||
onClick={this.handleNavigateBack}
|
||||
data-id={String(breadcrumbs[breadcrumbs.length - 2].id)}
|
||||
data-id={breadcrumbs.length >= 2 ? String(breadcrumbs[breadcrumbs.length - 2].id) : undefined}
|
||||
className="sortable-item not-sortable"
|
||||
/>
|
||||
)}
|
||||
|
||||
{childCategories.map((item, index) => {
|
||||
{childCategories.map((item) => {
|
||||
const label = categoryDisplayName(item.name, item.id, rootCategoryId);
|
||||
const draftName =
|
||||
drafts[item.id] !== undefined
|
||||
@@ -469,10 +510,10 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
/>
|
||||
))}
|
||||
|
||||
{renameMode && <NewCategoryTile parentId={currentCategoryId} />}
|
||||
{renameMode && articlesStatus === 'succeeded' && (
|
||||
{renameMode && <NewCategoryTile parentId={resolvedCategoryId} />}
|
||||
{renameMode && loaded && (
|
||||
<NewArticleTile
|
||||
parentId={currentCategoryId}
|
||||
parentId={resolvedCategoryId}
|
||||
onOpenArticle={this.handleArticleClick}
|
||||
sx={{ gridColumnStart: 1 }}
|
||||
/>
|
||||
@@ -505,3 +546,4 @@ class ArtikelKategorienPage extends PureComponent {
|
||||
}
|
||||
|
||||
export default withCategoryRoute(ArtikelKategorienPage);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user