diff --git a/README.md b/README.md
index 46f5780..a2380ec 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,8 @@ Reusable custom GUI class components live in the **`dashgui`** package
so source imports are reflected instantly.
- `dashgui/panels` — `PanelTile`, `PanelTileGrid`, `EditablePanelTile`, layout helpers
+- `dashgui/lists` — `RecordList`, the generic presentational list used by the
+ Lieferungen / Angebote / Bestellungen / Kunden list pages
- `dashgui/tiles` — base `Tile` (extended by `src/components/tiles/*`)
- `dashgui/SingleLineTextEdit`, `dashgui/ElevatedPill`
diff --git a/src/components/manifest/ManifestList.jsx b/src/components/manifest/ManifestList.jsx
index 8ab3e12..9c0c313 100644
--- a/src/components/manifest/ManifestList.jsx
+++ b/src/components/manifest/ManifestList.jsx
@@ -1,21 +1,7 @@
import { PureComponent } from 'react';
-import Box from '@mui/material/Box';
-import Button from '@mui/material/Button';
-import CircularProgress from '@mui/material/CircularProgress';
-import IconButton from '@mui/material/IconButton';
-import Stack from '@mui/material/Stack';
-import Table from '@mui/material/Table';
-import TableBody from '@mui/material/TableBody';
-import TableCell from '@mui/material/TableCell';
-import TableContainer from '@mui/material/TableContainer';
-import TableHead from '@mui/material/TableHead';
-import TableRow from '@mui/material/TableRow';
-import Typography from '@mui/material/Typography';
-import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
-import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import { enqueueSnackbar } from 'notistack';
import BackendError from '../BackendError';
-import { PanelTile, PanelTileGrid } from 'dashgui/panels';
+import { RecordList } from 'dashgui/lists';
import { StorageManagerContext } from '../../api/storageManagerContext';
import { backendErrorFrom } from '../../utils/backendError';
import { notifyError } from '../../utils/notify';
@@ -133,98 +119,43 @@ class ManifestList extends PureComponent {
const cfg = this.cfg;
const partyField = cfg.partyField;
- if (status === 'loading') {
- return (
-
-
-
- );
- }
-
- if (status === 'failed') {
- return ;
+ 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 (
-
-
-
-
-
-
-
- {docs.length === 0 ? (
-
- {cfg.emptyList}
-
- ) : (
-
-
-
-
- Nummer
- {cfg.externalNumber ? (
- Referenz
- ) : null}
- {cfg.dateLabel}
- {cfg.partyLabel}
-
-
-
-
- {docs.map((row) => (
- this.handleEdit(row)}
- >
- {row.number}
- {cfg.externalNumber ? (
-
- {numberDisplay(row.externalNumber)}
-
- ) : null}
- {formatDate(row.date)}
- {this.partyName(row[partyField])}
- e.stopPropagation()}
- >
- this.handleEdit(row)}
- >
-
-
- void this.handleDelete(row)}
- >
-
-
-
-
- ))}
-
-
-
- )}
-
-
-
+ }
+ 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`}
+ />
);
}
}
diff --git a/src/pages/kunde/index.jsx b/src/pages/kunde/index.jsx
index 211f360..3532249 100644
--- a/src/pages/kunde/index.jsx
+++ b/src/pages/kunde/index.jsx
@@ -1,21 +1,7 @@
import { PureComponent } from 'react';
-import Box from '@mui/material/Box';
-import Button from '@mui/material/Button';
-import CircularProgress from '@mui/material/CircularProgress';
-import IconButton from '@mui/material/IconButton';
-import Stack from '@mui/material/Stack';
-import Table from '@mui/material/Table';
-import TableBody from '@mui/material/TableBody';
-import TableCell from '@mui/material/TableCell';
-import TableContainer from '@mui/material/TableContainer';
-import TableHead from '@mui/material/TableHead';
-import TableRow from '@mui/material/TableRow';
-import Typography from '@mui/material/Typography';
-import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
-import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import { enqueueSnackbar } from 'notistack';
import BackendError from '../../components/BackendError';
-import { PanelTile, PanelTileGrid } from 'dashgui/panels';
+import { RecordList } from 'dashgui/lists';
import { StorageManagerContext } from '../../api/storageManagerContext';
import { router } from '../../appRouter';
import { backendErrorFrom } from '../../utils/backendError';
@@ -119,86 +105,47 @@ class KundeListePage extends PureComponent {
}
render() {
- const { status, error, entities, busyId } = this.state;
-
- if (status === 'loading') {
- return (
-
-
-
- );
- }
+ const { status, error, entities, groupsById, busyId } = this.state;
if (status === 'failed') {
return ;
}
- 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),
+ },
+ ];
- {entities.length === 0 ? (
-
- Noch keine Kunden.
-
- ) : (
-
-
-
-
- Kundennummer
- Name
- Vorname
- Gruppe
- Erstellt am
-
-
-
-
- {entities.map((row) => (
- this.handleEdit(row)}
- >
- {row.number}
- {row.name}
- {row.firstName}
- {this.groupName(row.customergroupId)}
- {formatDate(row.createdAt)}
- e.stopPropagation()}>
- this.handleEdit(row)}
- >
-
-
- void this.handleDelete(row)}
- >
-
-
-
-
- ))}
-
-
-
- )}
-
-
-
+ 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`}
+ />
);
}
}