This commit is contained in:
seb
2026-07-19 17:29:28 +02:00
parent cf1d3e2880
commit 831456f36c
2 changed files with 44 additions and 31 deletions

View File

@@ -21,7 +21,7 @@ export const NAV_ITEMS = [
export const SUB_NAV = { export const SUB_NAV = {
'/artikel': [ '/artikel': [
{ segment: '', label: 'Übersicht', icon: ViewListIcon }, { segment: '', icon: ViewListIcon },
{ segment: 'kategorien', label: 'Kategorien', icon: CategoryIcon }, { segment: 'kategorien', label: 'Kategorien', icon: CategoryIcon },
{ segment: 'lager', label: 'Lager', icon: WarehouseIcon }, { segment: 'lager', label: 'Lager', icon: WarehouseIcon },
], ],

View File

@@ -11,6 +11,7 @@ import Paper from '@mui/material/Paper';
import TextField from '@mui/material/TextField'; import TextField from '@mui/material/TextField';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import SearchIcon from '@mui/icons-material/Search'; import SearchIcon from '@mui/icons-material/Search';
import ClearIcon from '@mui/icons-material/Clear';
import { article } from '../../api'; import { article } from '../../api';
import { formatPrice } from '../../utils/price'; import { formatPrice } from '../../utils/price';
@@ -44,7 +45,8 @@ function formatCategoryList(catStr, facets) {
if (!catStr) return ''; if (!catStr) return '';
return catStr return catStr
.split(',') .split(',')
.map((id) => facets[id]?.name ?? id) .map((id) => facets[id]?.name)
.filter(Boolean)
.join(', '); .join(', ');
} }
@@ -71,6 +73,7 @@ function ResultsPagination({ offset, totalCount, pageCount, currentPage, onPageC
onChange={onPageChange} onChange={onPageChange}
color="primary" color="primary"
size="small" size="small"
onMouseDown={(e) => e.preventDefault()}
/> />
</Box> </Box>
); );
@@ -186,7 +189,8 @@ class ArtikelUebersichtPage extends Component {
const facetEntries = categoryFacets const facetEntries = categoryFacets
? Object.entries(categoryFacets) ? Object.entries(categoryFacets)
.map(([id, { count, name, parent }]) => ({ .filter(([, meta]) => meta?.name)
.map(([id, { count, name }]) => ({
id, id,
count, count,
name, name,
@@ -198,6 +202,8 @@ class ArtikelUebersichtPage extends Component {
const pageCount = Math.max(1, Math.ceil(totalCount / PAGE_SIZE)); const pageCount = Math.max(1, Math.ceil(totalCount / PAGE_SIZE));
const currentPage = Math.floor(offset / PAGE_SIZE) + 1; const currentPage = Math.floor(offset / PAGE_SIZE) + 1;
const emptyRowCount = Math.max(0, PAGE_SIZE - recordset.length); const emptyRowCount = Math.max(0, PAGE_SIZE - recordset.length);
const showResultsPanel =
facetEntries.length > 0 || recordset.length > 0 || (searchActive && !error && totalCount === 0);
const handlePageChange = (_e, page) => { const handlePageChange = (_e, page) => {
this.updateParams(input, filterParam, (page - 1) * PAGE_SIZE); this.updateParams(input, filterParam, (page - 1) * PAGE_SIZE);
@@ -211,15 +217,15 @@ class ArtikelUebersichtPage extends Component {
autoFocus autoFocus
type="search" type="search"
autoComplete="off" autoComplete="off"
inputProps={{
autocapitalize: 'off',
autocorrect: 'off',
spellcheck: false,
}}
placeholder="Artikel suchen (EAN, Artikelnr., Name, Barcode)…" placeholder="Artikel suchen (EAN, Artikelnr., Name, Barcode)…"
value={input} value={input}
onChange={this.handleInputChange} onChange={this.handleInputChange}
slotProps={{ slotProps={{
htmlInput: {
spellCheck: false,
autoCapitalize: 'off',
autoCorrect: 'off',
},
input: { input: {
startAdornment: ( startAdornment: (
<InputAdornment position="start"> <InputAdornment position="start">
@@ -243,11 +249,7 @@ class ArtikelUebersichtPage extends Component {
</Alert> </Alert>
)} )}
{searchActive && !error && totalCount === 0 && ( {showResultsPanel && (
<Typography color="text.secondary">Keine Artikel gefunden.</Typography>
)}
{(facetEntries.length > 0 || recordset.length > 0) && (
<Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}> <Box sx={{ display: 'flex', gap: 3, alignItems: 'flex-start' }}>
{facetEntries.length > 0 && ( {facetEntries.length > 0 && (
<Paper variant="outlined" sx={{ width: 220, flexShrink: 0, overflow: 'hidden' }}> <Paper variant="outlined" sx={{ width: 220, flexShrink: 0, overflow: 'hidden' }}>
@@ -258,29 +260,40 @@ class ArtikelUebersichtPage extends Component {
Kategorien Kategorien
</Typography> </Typography>
<List dense disablePadding> <List dense disablePadding>
{facetEntries.map(({ id, count, name, depth }) => ( {facetEntries.map(({ id, count, name, depth }) => {
<ListItemButton const selected = categories.includes(id);
key={id} return (
selected={categories.includes(id)} <ListItemButton
onClick={() => { key={id}
const next = categories.includes(id) selected={selected}
? categories.filter((c) => c !== id) onMouseDown={(e) => e.preventDefault()}
: [...categories, id]; onClick={() => {
this.updateParams(input, buildFilter(next), 0); const next = selected
}} ? categories.filter((c) => c !== id)
sx={{ pl: 2 + depth * 1.5 }} : [...categories, id];
> this.updateParams(input, buildFilter(next), 0);
<ListItemText }}
primary={`${name ?? id} (${count})`} sx={{ pl: 2 + depth * 1.5 }}
slotProps={{ primary: { variant: 'body2' } }} >
/> <ListItemText
</ListItemButton> primary={`${name} (${count})`}
))} slotProps={{ primary: { variant: 'body2' } }}
/>
{selected && (
<ClearIcon fontSize="small" color="action" sx={{ ml: 1, flexShrink: 0 }} />
)}
</ListItemButton>
);
})}
</List> </List>
</Paper> </Paper>
)} )}
<Box sx={{ flexGrow: 1, minWidth: 0 }}> <Box sx={{ flexGrow: 1, minWidth: 0 }}>
{searchActive && !error && totalCount === 0 && (
<Typography color="text.secondary">Keine Artikel gefunden.</Typography>
)}
{recordset.length > 0 && ( {recordset.length > 0 && (
<> <>
<ResultsPagination <ResultsPagination