u
This commit is contained in:
1214
src/components/article/ArticleUnifyDialog.jsx
Normal file
1214
src/components/article/ArticleUnifyDialog.jsx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1485,7 +1485,7 @@ export default class ArticleViewLists extends PureComponent {
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
<Typography variant="subtitle2" sx={{ fontWeight: 700, fontSize: '0.88rem' }}>
|
||||
Variantsvater für
|
||||
Vater für Auswahl-Merkmal
|
||||
</Typography>
|
||||
<Chip
|
||||
label={articleData.parentAttributeName || parentAttrDef?.name || 'Varianten'}
|
||||
|
||||
@@ -5,3 +5,4 @@ export { default as ArticleImageSearchDialog } from './ArticleImageSearchDialog'
|
||||
export { default as ArticleTileTab } from './ArticleTileTab';
|
||||
export { default as NewArticleTile } from './NewArticleTile';
|
||||
export { default as ArticleSearch } from './ArticleSearch';
|
||||
export { default as ArticleUnifyDialog } from './ArticleUnifyDialog';
|
||||
|
||||
@@ -1,16 +1,53 @@
|
||||
import { Component } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import CallMergeIcon from '@mui/icons-material/CallMerge';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
|
||||
import { article as articleApi } from '../../../api';
|
||||
import { artikelAutomat } from '../../../automats';
|
||||
import { artikelAutomat, getArticle } from '../../../automats';
|
||||
import { notifyError } from '../../../utils/notify';
|
||||
import ArticleSearch from '../ArticleSearch';
|
||||
import ArticleUnifyDialog from '../ArticleUnifyDialog';
|
||||
|
||||
export function isArticleFather(article) {
|
||||
if (!article) return false;
|
||||
return Boolean(
|
||||
article.isParent ||
|
||||
article.is_parent ||
|
||||
(article.childCount ?? 0) > 0 ||
|
||||
(Array.isArray(article.children) && article.children.length > 0) ||
|
||||
article.parent_attribute_id != null ||
|
||||
article.parentAttributeNameId != null
|
||||
);
|
||||
}
|
||||
|
||||
export function isArticleStueckliste(article) {
|
||||
if (!article) return false;
|
||||
return Boolean(
|
||||
article.articlelistId != null ||
|
||||
(article.articleListCount ?? 0) > 0 ||
|
||||
(Array.isArray(article.articlelist) && article.articlelist.length > 0) ||
|
||||
(Array.isArray(article.components) && article.components.length > 0) ||
|
||||
(Array.isArray(article.stueckliste) && article.stueckliste.length > 0)
|
||||
);
|
||||
}
|
||||
|
||||
export default class ArticleSettingsTab extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { busy: false };
|
||||
this.state = {
|
||||
busy: false,
|
||||
searchOpen: false,
|
||||
unifyOpen: false,
|
||||
targetArticle: null,
|
||||
};
|
||||
this.handleDeleteArticle = this.handleDeleteArticle.bind(this);
|
||||
this.handleOpenSearch = this.handleOpenSearch.bind(this);
|
||||
this.handleSelectTargetArticle = this.handleSelectTargetArticle.bind(this);
|
||||
}
|
||||
|
||||
async handleDeleteArticle() {
|
||||
@@ -31,21 +68,131 @@ export default class ArticleSettingsTab extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
handleOpenSearch() {
|
||||
const { article: articleData } = this.props;
|
||||
if (isArticleFather(articleData)) {
|
||||
enqueueSnackbar('Ein Vaterartikel kann nicht vereint werden.', { variant: 'warning' });
|
||||
return;
|
||||
}
|
||||
if (isArticleStueckliste(articleData)) {
|
||||
enqueueSnackbar('Ein Stücklisten-Artikel kann nicht vereint werden.', { variant: 'warning' });
|
||||
return;
|
||||
}
|
||||
this.setState({ searchOpen: true });
|
||||
}
|
||||
|
||||
async handleSelectTargetArticle(selected) {
|
||||
if (!selected?.sku) return;
|
||||
this.setState({ searchOpen: false, busy: true });
|
||||
try {
|
||||
let fullTarget = getArticle(selected.sku);
|
||||
if (!fullTarget || !fullTarget.warehouses || !fullTarget.prices) {
|
||||
fullTarget = await artikelAutomat.actions.loadArticle(selected.sku);
|
||||
}
|
||||
|
||||
if (isArticleFather(fullTarget)) {
|
||||
enqueueSnackbar('Der ausgewählte Artikel ist ein Vaterartikel und kann nicht vereint werden.', {
|
||||
variant: 'error',
|
||||
});
|
||||
this.setState({ busy: false });
|
||||
return;
|
||||
}
|
||||
|
||||
if (isArticleStueckliste(fullTarget)) {
|
||||
enqueueSnackbar('Der ausgewählte Artikel ist ein Stücklisten-Artikel und kann nicht vereint werden.', {
|
||||
variant: 'error',
|
||||
});
|
||||
this.setState({ busy: false });
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
busy: false,
|
||||
targetArticle: fullTarget,
|
||||
unifyOpen: true,
|
||||
});
|
||||
} catch (err) {
|
||||
this.setState({ busy: false });
|
||||
notifyError(err);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { busy } = this.state;
|
||||
const { busy, searchOpen, unifyOpen, targetArticle } = this.state;
|
||||
const { article: articleData } = this.props;
|
||||
|
||||
const isFather = isArticleFather(articleData);
|
||||
const isStueckliste = isArticleStueckliste(articleData);
|
||||
const cannotUnify = isFather || isStueckliste;
|
||||
const unifyDisabledReason = isFather
|
||||
? 'Ein Vaterartikel kann nicht vereint werden.'
|
||||
: isStueckliste
|
||||
? 'Ein Stücklisten-Artikel kann nicht vereint werden.'
|
||||
: null;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Button
|
||||
type="button"
|
||||
color="error"
|
||||
variant="contained"
|
||||
startIcon={<DeleteIcon />}
|
||||
disabled={busy}
|
||||
onClick={() => void this.handleDeleteArticle()}
|
||||
>
|
||||
Artikel löschen
|
||||
</Button>
|
||||
<Stack direction="row" spacing={1.5} alignItems="center" flexWrap="wrap">
|
||||
<Button
|
||||
type="button"
|
||||
color="error"
|
||||
variant="contained"
|
||||
startIcon={<DeleteIcon />}
|
||||
disabled={busy}
|
||||
onClick={() => void this.handleDeleteArticle()}
|
||||
>
|
||||
Artikel löschen
|
||||
</Button>
|
||||
|
||||
{unifyDisabledReason ? (
|
||||
<Tooltip title={unifyDisabledReason}>
|
||||
<span>
|
||||
<Button
|
||||
type="button"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
startIcon={<CallMergeIcon />}
|
||||
disabled
|
||||
>
|
||||
Artikel vereinen
|
||||
</Button>
|
||||
</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<Button
|
||||
type="button"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
startIcon={<CallMergeIcon />}
|
||||
disabled={busy}
|
||||
onClick={this.handleOpenSearch}
|
||||
>
|
||||
Artikel vereinen
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<ArticleSearch
|
||||
open={searchOpen}
|
||||
allowParent={false}
|
||||
excludeSkus={[articleData.sku]}
|
||||
title="Artikel zum Vereinen auswählen"
|
||||
placeholder="Artikel suchen…"
|
||||
actionLabel="Auswählen"
|
||||
onClose={() => this.setState({ searchOpen: false })}
|
||||
onSelect={this.handleSelectTargetArticle}
|
||||
/>
|
||||
|
||||
{unifyOpen && targetArticle && (
|
||||
<ArticleUnifyDialog
|
||||
open={unifyOpen}
|
||||
articleLeft={articleData}
|
||||
articleRight={targetArticle}
|
||||
onClose={() => this.setState({ unifyOpen: false, targetArticle: null })}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import DeleteSweepOutlinedIcon from '@mui/icons-material/DeleteSweepOutlined';
|
||||
import { PanelTile } from 'dashgui/panels';
|
||||
import { LINE_COLUMNS, hasArticleLines } from './manifestConfig';
|
||||
import ManifestFormLine from './ManifestFormLine';
|
||||
import ArticleSearch from '../article/ArticleSearch';
|
||||
|
||||
class ManifestLines extends PureComponent {
|
||||
render() {
|
||||
@@ -23,7 +22,6 @@ class ManifestLines extends PureComponent {
|
||||
linesColor,
|
||||
onLineChange,
|
||||
onAddLine,
|
||||
onAddArticleLine,
|
||||
onRemoveLine,
|
||||
onRemoveAllLines,
|
||||
columns = LINE_COLUMNS,
|
||||
@@ -120,24 +118,13 @@ class ManifestLines extends PureComponent {
|
||||
</Table>
|
||||
</TableContainer>
|
||||
<Box sx={{ display: 'flex', gap: 1.5, alignItems: 'center', flexWrap: 'wrap' }}>
|
||||
{onAddArticleLine && (
|
||||
<ArticleSearch
|
||||
size="small"
|
||||
clearOnSelect
|
||||
allowParent={false}
|
||||
placeholder="Artikel suchen und hinzufügen…"
|
||||
disabled={saving}
|
||||
onSelect={onAddArticleLine}
|
||||
sx={{ minWidth: 260, flex: 1, maxWidth: 440 }}
|
||||
/>
|
||||
)}
|
||||
<Button
|
||||
size="small"
|
||||
startIcon={<AddIcon />}
|
||||
disabled={saving}
|
||||
onClick={onAddLine}
|
||||
>
|
||||
{onAddArticleLine ? 'Leere Zeile' : 'Zeile hinzufügen'}
|
||||
Zeile
|
||||
</Button>
|
||||
<Button
|
||||
size="small"
|
||||
|
||||
Reference in New Issue
Block a user