import { PureComponent } from 'react'; import { enqueueSnackbar } from 'notistack'; import BackendError from '../BackendError'; import { RecordList } from 'dashgui/lists'; import { backendErrorFrom } from '../../utils/backendError'; import { notifyError } from '../../utils/notify'; import withNavigate from '../withNavigate'; import DeliveryList from './DeliveryList'; import { formatDate, loadParties, manifestConfig, numberDisplay, partyDisplayName, sortDocs, apiFor, } from './manifestConfig'; class ManifestList extends PureComponent { constructor(props) { super(props); this.cfg = manifestConfig(props.kind); this.state = { status: 'loading', error: null, docs: [], partiesById: {}, busyId: null, }; this._cancelled = false; this.handleRetry = this.handleRetry.bind(this); this.handleCreate = this.handleCreate.bind(this); this.handleEdit = this.handleEdit.bind(this); this.handleDelete = this.handleDelete.bind(this); } componentDidMount() { this._cancelled = false; if (this.props.kind !== 'delivery') { void this.load(); } } componentWillUnmount() { this._cancelled = true; } async load() { const cfg = this.cfg; this.setState({ status: 'loading', error: null }); try { const [docs, parties] = await Promise.all([ cfg.listAutomat.actions.ensureLoaded(), loadParties(this.props.kind), ]); if (this._cancelled) return; const sortedDocs = sortDocs(docs); this.setState({ status: 'ready', docs: sortedDocs, partiesById: cfg.partiesByIdFromList(parties), }); } catch (err) { if (this._cancelled) return; this.setState({ status: 'failed', error: backendErrorFrom(err) }); } } handleRetry() { void this.load(); } go(to) { const { navigate } = this.props; if (typeof navigate === 'function') { navigate(to); return; } window.location.assign(to); } handleCreate() { this.go(this.cfg.createPath); } handleEdit(doc) { this.go(this.cfg.editPath(doc.id)); } async handleDelete(doc) { if (this.state.busyId != null) return; if (!window.confirm(this.cfg.confirmDelete(doc.number))) return; const cfg = this.cfg; this.setState({ busyId: doc.id }); try { const api = apiFor(cfg.kind); await api.delete(doc.id); const list = await cfg.listAutomat.actions.reload(); if (this._cancelled) return; this.setState({ docs: sortDocs(list), busyId: null, }); enqueueSnackbar(cfg.deletedMsg, { variant: 'success' }); } catch (err) { if (this._cancelled) return; notifyError(err); this.setState({ busyId: null }); } } partyName(partyId) { if (partyId == null) return null; return partyDisplayName( this.props.kind, this.state.partiesById[partyId], ); } render() { if (this.props.kind === 'delivery') { return ; } const { status, error, docs, busyId } = this.state; const cfg = this.cfg; const partyField = cfg.partyField; const columns = [{ key: 'number', label: 'Nummer' }]; if (cfg.externalNumber) { columns.push({ key: 'externalNumber', label: 'Referenz', render: (row) => numberDisplay(row.externalNumber), }); } columns.push( { key: 'date', label: cfg.dateLabel, render: (row) => formatDate(row.date), }, { key: partyField, label: cfg.partyLabel, render: (row) => this.partyName(row[partyField]), }, ); return ( } rows={docs} columns={columns} createLabel={cfg.createButton} onCreate={this.handleCreate} onEdit={this.handleEdit} onDelete={this.handleDelete} deleteDisabled={busyId != null} emptyMessage={cfg.emptyList} color={cfg.listColor} getEditLabel={(row) => `„${row.number}“ bearbeiten`} getDeleteLabel={(row) => `„${row.number}“ löschen`} /> ); } } export default withNavigate(ManifestList);