import { PureComponent } from 'react'; import { enqueueSnackbar } from 'notistack'; import BackendError from '../components/BackendError'; import { RecordList } from 'dashgui/lists'; import { StorageManagerContext } from '../api/storageManagerContext'; import { router } from '../appRouter'; import { backendErrorFrom } from '../utils/backendError'; import { notifyError } from '../utils/notify'; function sortEntities(entities) { return [...entities].sort((a, b) => { const byName = String(a.name).localeCompare(String(b.name), 'de'); if (byName !== 0) return byName; return String(a.firstName ?? '').localeCompare(String(b.firstName ?? ''), 'de'); }); } function formatDate(value) { if (!value) return ''; return new Intl.DateTimeFormat('de-DE', { dateStyle: 'medium' }).format(new Date(value)); } class KundeListePage extends PureComponent { static contextType = StorageManagerContext; constructor(props) { super(props); this.state = { status: 'loading', error: null, entities: [], groupsById: {}, busyId: null, }; this._cancelled = false; this.handleRetry = this.handleRetry.bind(this); this.handleCreate = this.handleCreate.bind(this); } componentDidMount() { this._cancelled = false; void this.load(); } componentWillUnmount() { this._cancelled = true; } async load() { this.setState({ status: 'loading', error: null }); try { const [entities, groups] = await Promise.all([ this.context.entities ?? this.context.entityPromise, this.context.customergroups ?? this.context.customergroupPromise, ]); if (this._cancelled) return; const groupsById = Object.fromEntries(groups.map((row) => [row.id, row])); this.setState({ status: 'ready', entities: sortEntities(entities), groupsById, }); } catch (err) { if (this._cancelled) return; this.setState({ status: 'failed', error: backendErrorFrom(err) }); } } handleRetry() { void this.load(); } handleCreate() { void router.navigate('/kunde/neu'); } handleEdit(entity) { void router.navigate(`/kunde/${entity.id}`); } groupName(customergroupId) { return this.state.groupsById[customergroupId]?.name; } async handleDelete(entity) { if (this.state.busyId != null) return; const label = [entity.firstName, entity.name].filter(Boolean).join(' '); if (!window.confirm(`Kunde „${label}“ wirklich löschen?`)) return; this.setState({ busyId: entity.id }); try { await this.context.entity.delete(entity.id); const list = await this.context.updateEntity(); if (this._cancelled) return; this.setState({ entities: sortEntities(list), busyId: null, }); enqueueSnackbar('Kunde gelöscht.', { variant: 'success' }); } catch (err) { if (this._cancelled) return; notifyError(err); this.setState({ busyId: null }); } } render() { const { status, error, entities, busyId } = this.state; if (status === 'failed') { return ; } const columns = [ { key: 'number', label: 'Kundennummer' }, { key: 'name', label: 'Name' }, { key: 'firstName', label: 'Vorname' }, { key: 'customergroupId', label: 'Gruppe', render: (row) => this.groupName(row.customergroupId), }, { key: 'createdAt', label: 'Erstellt am', render: (row) => formatDate(row.createdAt), }, ]; const label = (row) => [row.firstName, row.name].filter(Boolean).join(' ') || String(row.number); return ( } rows={entities} columns={columns} createLabel="Neuer Kunde" onCreate={this.handleCreate} onEdit={this.handleEdit} onDelete={this.handleDelete} deleteDisabled={busyId != null} emptyMessage="Noch keine Kunden." color="#bfdbfe" getEditLabel={(row) => `„${label(row)}“ bearbeiten`} getDeleteLabel={(row) => `„${label(row)}“ löschen`} /> ); } } export default KundeListePage;