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);