import { PureComponent } from 'react'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import CircularProgress from '@mui/material/CircularProgress'; import Dialog from '@mui/material/Dialog'; 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 InputAdornment from '@mui/material/InputAdornment'; import List from '@mui/material/List'; import ListItemAvatar from '@mui/material/ListItemAvatar'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import Chip from '@mui/material/Chip'; import Alert from '@mui/material/Alert'; import CloseIcon from '@mui/icons-material/Close'; import SearchIcon from '@mui/icons-material/Search'; import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined'; import LinkIcon from '@mui/icons-material/Link'; import articleIndexAutomat from '../../automats/articleIndexAutomat'; import ArticlePhoto from '../article/ArticlePhoto'; import { BrandLabel } from '../brand'; export default class ArticleSearchDialog extends PureComponent { constructor(props) { super(props); this.state = { query: '', articles: [], loading: false, error: null, assigningSku: null, }; this.handleQueryChange = this.handleQueryChange.bind(this); this.handleClearQuery = this.handleClearQuery.bind(this); this.handleSelect = this.handleSelect.bind(this); } componentDidMount() { if (this.props.open) { this.initFromLine(); void this.loadArticles(); } } componentDidUpdate(prevProps) { if (!prevProps.open && this.props.open) { this.initFromLine(); void this.loadArticles(); } } initFromLine() { const { line } = this.props; const initialQuery = line?.name?.trim() || line?.sku?.trim() || ''; this.setState({ query: initialQuery, assigningSku: null, error: null, }); } async loadArticles() { this.setState({ loading: true, error: null }); try { const list = await articleIndexAutomat.actions.ensureLoaded(); this.setState({ articles: Array.isArray(list) ? list : [], loading: false }); } catch (err) { console.error('Fehler beim Laden des Artikel-Index:', err); this.setState({ loading: false, error: err?.message || 'Artikel-Index konnte nicht geladen werden.', }); } } handleQueryChange(e) { this.setState({ query: e.target.value }); } handleClearQuery() { this.setState({ query: '' }); } async handleSelect(article) { const { onAssign, line } = this.props; 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 || 'Fehler beim Verknüpfen des Lieferanten-Artikels.', }); } } render() { const { open, onClose, line } = this.props; const { query, articles, loading, error, assigningSku } = this.state; const bookableArticles = articles.filter((a) => !a.isParent && !a.is_parent); const trimmed = query.trim().toLowerCase(); const filtered = trimmed ? bookableArticles.filter((a) => { const skuMatch = a.sku?.toLowerCase().includes(trimmed); const nameMatch = a.name?.toLowerCase().includes(trimmed); const eanMatch = Array.isArray(a.eans) ? a.eans.some((e) => String(e).toLowerCase().includes(trimmed)) : false; return skuMatch || nameMatch || eanMatch; }) : bookableArticles.slice(0, 50); const rawSku = line?.sku != null ? String(line.sku).trim() : ''; return ( Existierenden Artikel zuordnen Lieferanten-SKU: {rawSku || '–'} {line?.name ? ` · ${line.name}` : ''} {error && ( {error} )} ), endAdornment: query ? ( ) : null, }, }} sx={{ mb: 1.5 }} /> {loading ? ( Artikel werden geladen… ) : filtered.length === 0 ? ( Keine Artikel für „{query}“ gefunden. ) : ( {filtered.map((article) => { const photo = article.photos?.[0] || article.articlepic?.[0]; const fullHash = photo?.hash || photo?.fullHash; const thumbHash = photo?.thumbhash || photo?.thumbHash; const thumbW = photo?.thumbw || photo?.thumbW; const thumbH = photo?.thumbh || photo?.thumbH; const hasPhoto = fullHash != null || thumbHash != null; const primaryEan = Array.isArray(article.eans) ? article.eans[0] : article.eans; const isAssigning = assigningSku === article.sku; return ( this.handleSelect(article)} sx={{ py: 1, px: 1.5, '&:hover': { bgcolor: 'action.hover', }, }} > {hasPhoto ? ( ) : ( )} {article.name || '–'} } secondary={ {(article.brand?.name || article.brandName) && ( )} {primaryEan ? ( EAN: {primaryEan} ) : null} } /> ); })} )} ); } }