feat(artikel): fill results list viewport with FillSpace

Wrap the article search results list in FillSpace (from dashgui) so it
becomes a scrollable middle section that fills to the bottom of the
viewport. The pagination box is referenced via paginationRef as the
anchor above the spacer; measureElement is temporarily a debug unit to
visualize the repeating fill.
This commit is contained in:
seb
2026-08-12 02:44:32 +02:00
parent b7f60d51fd
commit 4df5110253

View File

@@ -1,4 +1,5 @@
import { Component } from 'react'; import { Component, createRef } from 'react';
import FillSpace from 'dashgui/FillSpace';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
import InputAdornment from '@mui/material/InputAdornment'; import InputAdornment from '@mui/material/InputAdornment';
import List from '@mui/material/List'; import List from '@mui/material/List';
@@ -85,6 +86,7 @@ class ArtikelSearchPage extends Component {
state = initialSearchState(this.props.searchParams); state = initialSearchState(this.props.searchParams);
listSlotRef = { current: null }; listSlotRef = { current: null };
rowMeasureRef = { current: null }; rowMeasureRef = { current: null };
paginationRef = createRef();
setListSlotRef = (node) => { setListSlotRef = (node) => {
if (this.listSlotRef.current === node) return; if (this.listSlotRef.current === node) return;
@@ -368,7 +370,7 @@ class ArtikelSearchPage extends Component {
)} )}
{/* Always mount real pagination height (invisible until needed) so pageSize is correct. */} {/* Always mount real pagination height (invisible until needed) so pageSize is correct. */}
<Box sx={{ mb: 2 }}> <Box ref={this.paginationRef} sx={{ mb: 2 }}>
<ResultsPagination <ResultsPagination
invisible={!showPagination} invisible={!showPagination}
offset={showPagination ? offset : 0} offset={showPagination ? offset : 0}
@@ -380,54 +382,73 @@ class ArtikelSearchPage extends Component {
/> />
</Box> </Box>
<Box ref={this.setListSlotRef}> <FillSpace
{rows.length > 0 && ( aboveRef={this.paginationRef}
<List component={Paper} variant="outlined" disablePadding> debug
{rows.map((row, index) => ( sx={{ overflow: 'auto' }}
<ListItemButton // Temporary dummy unit so the repeating fill is visible.
key={row.id} measureElement={
type="button" <Box
divider={index < rows.length - 1} sx={{
data-result-row bgcolor: '#dbeafe',
onMouseDown={(e) => e.preventDefault()} p: 2,
onClick={() => { borderRadius: 1,
this.persistQuery(); textAlign: 'center',
this.props.navigate(artikelDetailPath(row)); }}
}} >
sx={resultRowSx} <Typography variant="body2">Einheit</Typography>
> </Box>
<ListItemText }
primary={row.name} >
secondary={ <Box ref={this.setListSlotRef}>
<Typography {rows.length > 0 && (
component="span" <List component={Paper} variant="outlined" disablePadding>
variant="body2" {rows.map((row, index) => (
color="text.secondary" <ListItemButton
noWrap key={row.id}
> type="button"
{row.sku} divider={index < rows.length - 1}
{' · '} data-result-row
Bestand {formatStock(row.stock)} onMouseDown={(e) => e.preventDefault()}
{' · '} onClick={() => {
Verfügbar {formatStock(row.available)} this.persistQuery();
{row.categories this.props.navigate(artikelDetailPath(row));
? ` · ${formatCategoryList(row.categories, categoryFacets ?? {})}` }}
: ''} sx={resultRowSx}
</Typography>
}
slotProps={{ primary: { fontWeight: 500, noWrap: true } }}
/>
<Typography
variant="body2"
sx={{ fontWeight: 600, flexShrink: 0, ml: 2 }}
> >
{row.price != null ? formatPrice(row.price) : '—'} <ListItemText
</Typography> primary={row.name}
</ListItemButton> secondary={
))} <Typography
</List> component="span"
)} variant="body2"
</Box> color="text.secondary"
noWrap
>
{row.sku}
{' · '}
Bestand {formatStock(row.stock)}
{' · '}
Verfügbar {formatStock(row.available)}
{row.categories
? ` · ${formatCategoryList(row.categories, categoryFacets ?? {})}`
: ''}
</Typography>
}
slotProps={{ primary: { fontWeight: 500, noWrap: true } }}
/>
<Typography
variant="body2"
sx={{ fontWeight: 600, flexShrink: 0, ml: 2 }}
>
{row.price != null ? formatPrice(row.price) : '—'}
</Typography>
</ListItemButton>
))}
</List>
)}
</Box>
</FillSpace>
</Box> </Box>
</Box> </Box>
)} )}