Files
dashfront/src/components/manifest/ArticleSearchDialog.jsx
2026-10-10 00:48:55 +02:00

149 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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';
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 });
}
}
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({
assigningSku: null,
error:
err?.message ||
(isDelivery
? 'Fehler beim Verknüpfen des Lieferanten-Artikels.'
: 'Fehler beim Zuordnen des Artikels.'),
});
}
};
render() {
const { open, onClose, line, kind = 'delivery' } = this.props;
const { assigningSku, error } = this.state;
const isDelivery = kind === 'delivery';
const rawSku = line?.sku != null ? String(line.sku).trim() : '';
return (
<AppDialog
open={Boolean(open)}
onClose={assigningSku ? undefined : onClose}
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' : 'Artikel auswählen'}
</Typography>
<Typography variant="caption" color="text.secondary">
{isDelivery ? 'Lieferanten-SKU' : 'SKU'}: <strong>{rawSku || '–'}</strong>
{line?.name ? ` · ${line.name}` : ''}
</Typography>
</Box>
<IconButton
size="small"
aria-label="Schließen"
disabled={Boolean(assigningSku)}
onClick={onClose}
>
<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>
)}
<ArticleSearch
mode="list"
autoFocus
allowParent={false}
busySku={assigningSku}
actionLabel={assigningSku ? 'Zuordnen…' : 'Zuordnen'}
onSelect={this.handleSelect}
/>
</DialogContent>
<DialogActions sx={{ px: 2, py: 1.5 }}>
<Button
size="small"
disabled={Boolean(assigningSku)}
onClick={onClose}
>
Abbrechen
</Button>
</DialogActions>
</AppDialog>
);
}
}