200 lines
6.2 KiB
JavaScript
200 lines
6.2 KiB
JavaScript
import { PureComponent } from 'react';
|
||
import Box from '@mui/material/Box';
|
||
import Button from '@mui/material/Button';
|
||
import AppDialog from '../AppDialog';
|
||
import DialogActions from '@mui/material/DialogActions';
|
||
import DialogContent from '@mui/material/DialogContent';
|
||
import DialogTitle from '@mui/material/DialogTitle';
|
||
import IconButton from '@mui/material/IconButton';
|
||
import Typography from '@mui/material/Typography';
|
||
import Alert from '@mui/material/Alert';
|
||
import CloseIcon from '@mui/icons-material/Close';
|
||
import ArticleSearch from '../article/ArticleSearch';
|
||
|
||
import deliveryEditorAutomat from '../../automats/deliveryEditorAutomat';
|
||
|
||
export default class ArticleSearchDialog extends PureComponent {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {
|
||
assigningSku: null,
|
||
error: null,
|
||
};
|
||
}
|
||
|
||
componentDidUpdate(prevProps) {
|
||
if (!prevProps.open && this.props.open) {
|
||
this.setState({ assigningSku: null, error: null });
|
||
}
|
||
}
|
||
|
||
handleClose = () => {
|
||
this.setState({ assigningSku: null, error: null });
|
||
this.props.onClose?.();
|
||
};
|
||
|
||
handleSelect = async (article) => {
|
||
const { onAssign, line, kind = 'delivery' } = this.props;
|
||
const isDelivery = kind === 'delivery';
|
||
if (!onAssign || !article?.sku) return;
|
||
|
||
if (article.isParent || article.is_parent) {
|
||
this.setState({ error: 'Ein Vaterartikel kann nicht auf Belege gebucht werden.' });
|
||
return;
|
||
}
|
||
|
||
this.setState({ assigningSku: article.sku, error: null });
|
||
try {
|
||
await onAssign(article, line);
|
||
} catch (err) {
|
||
this.setState({
|
||
error:
|
||
err?.message ||
|
||
(isDelivery
|
||
? (line ? 'Fehler beim Verknüpfen des Lieferanten-Artikels.' : 'Fehler beim Hinzufügen des Artikels.')
|
||
: 'Fehler beim Zuordnen des Artikels.'),
|
||
});
|
||
} finally {
|
||
this.setState({ assigningSku: null });
|
||
}
|
||
};
|
||
|
||
render() {
|
||
const { open, onClose, line, kind = 'delivery', supplierArticles: propSupplierArticles } = this.props;
|
||
const { assigningSku, error } = this.state;
|
||
const isDelivery = kind === 'delivery';
|
||
const onlySupplierArticles = isDelivery && !line;
|
||
const rawSku = line?.sku != null ? String(line.sku).trim() : '';
|
||
|
||
const supplierArticlesList = onlySupplierArticles
|
||
? (propSupplierArticles ?? deliveryEditorAutomat.state.supplierArticles ?? [])
|
||
: null;
|
||
|
||
const includeSkus = onlySupplierArticles
|
||
? supplierArticlesList.map((sa) => sa.article?.sku || sa.sku).filter(Boolean)
|
||
: null;
|
||
|
||
const extraArticles = onlySupplierArticles
|
||
? supplierArticlesList.map((sa) => ({
|
||
id: sa.article?.id ?? sa.id,
|
||
sku: sa.article?.sku || sa.sku,
|
||
name: sa.article?.name || sa.name || sa.sku || '',
|
||
brand: sa.article?.brand,
|
||
brandName: sa.article?.brand?.name || sa.article?.brandName,
|
||
stock: sa.article?.stock ?? sa.stock,
|
||
available: sa.article?.available,
|
||
price: sa.price?.net ?? sa.article?.price ?? sa.article?.vknetto,
|
||
eans: sa.article?.eans || [sa.sku].filter(Boolean),
|
||
isParent: false,
|
||
}))
|
||
: [];
|
||
|
||
return (
|
||
<AppDialog
|
||
open={Boolean(open)}
|
||
onClose={this.handleClose}
|
||
maxWidth="md"
|
||
fullWidth
|
||
aria-labelledby="article-search-dialog-title"
|
||
slotProps={{
|
||
paper: {
|
||
sx: {
|
||
height: '80vh',
|
||
minHeight: '80vh',
|
||
maxHeight: '80vh',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
overflow: 'hidden',
|
||
},
|
||
},
|
||
}}
|
||
>
|
||
<DialogTitle
|
||
id="article-search-dialog-title"
|
||
sx={{
|
||
display: 'flex',
|
||
alignItems: 'center',
|
||
justifyContent: 'space-between',
|
||
pb: 1,
|
||
flexShrink: 0,
|
||
}}
|
||
>
|
||
<Box>
|
||
<Typography variant="h6" component="div" fontWeight={600}>
|
||
{line
|
||
? 'Existierenden Artikel zuordnen'
|
||
: isDelivery
|
||
? 'Lieferanten-Artikel auswählen'
|
||
: 'Artikel auswählen'}
|
||
</Typography>
|
||
<Typography variant="caption" color="text.secondary">
|
||
{line ? (
|
||
<>
|
||
{isDelivery ? 'Lieferanten-SKU' : 'SKU'}: <strong>{rawSku || '–'}</strong>
|
||
{line?.name ? ` · ${line.name}` : ''}
|
||
</>
|
||
) : isDelivery ? (
|
||
'Nur mit dem ausgewählten Lieferanten verknüpfte Artikel'
|
||
) : (
|
||
'Artikel für Beleg auswählen'
|
||
)}
|
||
</Typography>
|
||
</Box>
|
||
<IconButton
|
||
size="small"
|
||
aria-label="Schließen"
|
||
onClick={this.handleClose}
|
||
>
|
||
<CloseIcon fontSize="small" />
|
||
</IconButton>
|
||
</DialogTitle>
|
||
|
||
<DialogContent
|
||
dividers
|
||
sx={{
|
||
p: 2,
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
flex: 1,
|
||
minHeight: 0,
|
||
overflow: 'hidden',
|
||
}}
|
||
>
|
||
{error && (
|
||
<Alert severity="error" sx={{ mb: 2, flexShrink: 0 }}>
|
||
{error}
|
||
</Alert>
|
||
)}
|
||
|
||
{onlySupplierArticles && supplierArticlesList.length === 0 && (
|
||
<Alert severity="info" sx={{ mb: 2, flexShrink: 0 }}>
|
||
Für diesen Lieferanten sind noch keine Artikel verknüpft.
|
||
</Alert>
|
||
)}
|
||
|
||
<ArticleSearch
|
||
mode="list"
|
||
autoFocus
|
||
allowParent={false}
|
||
busySku={assigningSku}
|
||
initialQuery={line?.name ? String(line.name) : ''}
|
||
includeSkus={includeSkus}
|
||
extraArticles={extraArticles}
|
||
actionLabel={assigningSku ? (line ? 'Zuordnen…' : 'Hinzufügen…') : (line ? 'Zuordnen' : 'Hinzufügen')}
|
||
onSelect={this.handleSelect}
|
||
/>
|
||
</DialogContent>
|
||
|
||
<DialogActions sx={{ px: 2, py: 1.5 }}>
|
||
<Button
|
||
size="small"
|
||
onClick={this.handleClose}
|
||
>
|
||
Abbrechen
|
||
</Button>
|
||
</DialogActions>
|
||
</AppDialog>
|
||
);
|
||
}
|
||
}
|