reroute
This commit is contained in:
118
src/routes/artikel/_sku.jsx
Normal file
118
src/routes/artikel/_sku.jsx
Normal file
@@ -0,0 +1,118 @@
|
||||
import { Component } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import CircularProgress from '@mui/material/CircularProgress';
|
||||
import { StorageManagerContext } from '../../api/storageManagerContext';
|
||||
import BackendError from '../../components/BackendError';
|
||||
import { ArticleView } from '../../components/article';
|
||||
import {
|
||||
artikelAutomat,
|
||||
createArticleSelector,
|
||||
getArticle,
|
||||
setLastArticleSku,
|
||||
} from '../../automats';
|
||||
import withSkuRoute from './withSkuRoute';
|
||||
|
||||
/** Full-screen loading state while the shared article cache resolves. */
|
||||
function ArticleLoading() {
|
||||
return (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center', py: 8 }}>
|
||||
<CircularProgress size={32} />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
class ArtikelSkuPage extends Component {
|
||||
static contextType = StorageManagerContext;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
this.state = {
|
||||
article: getArticle(props.sku),
|
||||
ready: context.getCategoryState() != null,
|
||||
error: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this._mounted = true;
|
||||
this.installEscape();
|
||||
setLastArticleSku(this.props.sku);
|
||||
this.unsub = artikelAutomat.subscribe(this, (state) => ({
|
||||
article: createArticleSelector(this.props.sku)(state),
|
||||
}));
|
||||
void this.ensureArticle();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
if (prevProps.sku !== this.props.sku) {
|
||||
setLastArticleSku(this.props.sku);
|
||||
this.setState({ article: getArticle(this.props.sku), error: null });
|
||||
this.unsub?.();
|
||||
this.unsub = artikelAutomat.subscribe(this, (state) => ({
|
||||
article: createArticleSelector(this.props.sku)(state),
|
||||
}));
|
||||
void this.ensureArticle();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this._mounted = false;
|
||||
this.removeEscape();
|
||||
this.unsub?.();
|
||||
this.unsub = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates the article fetch to the shared artikelAutomat cache; also waits
|
||||
* for the category tree/company/session the view tiles depend on.
|
||||
*/
|
||||
async ensureArticle() {
|
||||
const sku = this.props.sku;
|
||||
if (!sku) return;
|
||||
try {
|
||||
await Promise.all([
|
||||
artikelAutomat.actions.loadArticle(sku),
|
||||
this.context.categoryTreePromise,
|
||||
this.context.companyPromise,
|
||||
this.context.authMePromise,
|
||||
]);
|
||||
if (this._mounted) this.setState({ ready: true });
|
||||
} catch (error) {
|
||||
if (this._mounted) this.setState({ error });
|
||||
}
|
||||
}
|
||||
|
||||
handleRetry = () => {
|
||||
this.setState({ error: null });
|
||||
void this.ensureArticle();
|
||||
};
|
||||
|
||||
installEscape() {
|
||||
this._onKeyDown = (e) => {
|
||||
if (e.key !== 'Escape') return;
|
||||
e.preventDefault();
|
||||
this.props.navigate(-1);
|
||||
};
|
||||
document.addEventListener('keydown', this._onKeyDown);
|
||||
}
|
||||
|
||||
removeEscape() {
|
||||
if (this._onKeyDown) {
|
||||
document.removeEventListener('keydown', this._onKeyDown);
|
||||
this._onKeyDown = null;
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sku } = this.props;
|
||||
const { article, ready, error } = this.state;
|
||||
|
||||
if (error) {
|
||||
return <BackendError error={error} sx={{ mt: 2 }} onRetry={this.handleRetry} />;
|
||||
}
|
||||
if (!article || !ready) return <ArticleLoading />;
|
||||
return <ArticleView sku={sku} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default withSkuRoute(ArtikelSkuPage);
|
||||
Reference in New Issue
Block a user