This commit is contained in:
seb
2026-09-28 06:49:46 +02:00
parent 0daf9fef3d
commit c4f8ebb41b
15 changed files with 2659 additions and 324 deletions

View File

@@ -3,6 +3,7 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import WarehouseIcon from '@mui/icons-material/Warehouse';
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
import Tooltip from '@mui/material/Tooltip';
import { PanelTile } from 'dashgui/panels';
import { formatStock } from '../../../pages/artikel/searchFormat';
import ArticleStockAdjustDialog from '../ArticleStockAdjustDialog';
@@ -30,6 +31,9 @@ export default class ArticleViewStock extends PureComponent {
render() {
const { article: articleData } = this.props;
const { adjustOpen } = this.state;
const isTrackStock =
articleData?.track_stock !== false && articleData?.track_stock !== 0;
const rawWarehouses = Array.isArray(articleData?.warehouses)
? articleData.warehouses
: [];
@@ -63,149 +67,196 @@ export default class ArticleViewStock extends PureComponent {
onClick: this.handleOpenAdjust,
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
height: '100%',
justifyContent: 'space-between',
}}
>
{/* Top section: Headline and Total Stock */}
<Box>
<Typography
variant="caption"
color="text.secondary"
sx={{
textTransform: 'uppercase',
letterSpacing: 0.6,
fontWeight: 600,
display: 'block',
}}
>
Bestand
</Typography>
<Box
sx={{
display: 'flex',
alignItems: 'baseline',
gap: 0.75,
my: 0.5,
}}
>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
height: '100%',
justifyContent: 'space-between',
}}
>
{/* Top section: Headline and Total Stock */}
<Box>
<Typography
component="div"
variant="caption"
color="text.secondary"
sx={{
fontSize: '2.4rem',
fontWeight: 700,
lineHeight: 1.1,
letterSpacing: '-0.02em',
color: totalStock > 0 ? 'text.primary' : 'text.secondary',
textTransform: 'uppercase',
letterSpacing: 0.6,
fontWeight: 600,
display: 'block',
}}
>
{formatStock(totalStock)}
Bestand
</Typography>
{unit ? (
<Typography
variant="body2"
color="text.secondary"
sx={{ fontWeight: 500 }}
>
{unit}
</Typography>
) : null}
</Box>
</Box>
{/* Bottom section: Per-warehouse breakdown */}
{hasWarehouses ? (
<Box
sx={{
mt: 1,
flex: 1,
minHeight: 0,
overflowY: 'auto',
pr: 0.5,
'&::-webkit-scrollbar': { width: 4 },
'&::-webkit-scrollbar-thumb': {
backgroundColor: 'rgba(0, 0, 0, 0.15)',
borderRadius: 2,
},
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
{warehouses.map((wh) => (
{isTrackStock ? (
<Tooltip title="Klicken, um Bestand anzupassen" arrow placement="top-start">
<Box
key={wh.id}
onClick={this.handleOpenAdjust}
sx={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
py: 0.35,
px: 0.75,
display: 'inline-flex',
alignItems: 'baseline',
gap: 0.75,
my: 0.5,
cursor: 'pointer',
borderRadius: 1,
backgroundColor: 'rgba(255, 255, 255, 0.55)',
px: 0.5,
mx: -0.5,
transition: 'background-color 0.15s ease',
'&:hover': {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
},
}}
>
<Typography
component="div"
sx={{
fontSize: '2.4rem',
fontWeight: 700,
lineHeight: 1.1,
letterSpacing: '-0.02em',
color: totalStock > 0 ? 'text.primary' : 'text.secondary',
}}
>
{formatStock(totalStock)}
</Typography>
{unit ? (
<Typography
variant="body2"
color="text.secondary"
sx={{ fontWeight: 500 }}
>
{unit}
</Typography>
) : null}
</Box>
</Tooltip>
) : (
<Box
onClick={this.handleOpenAdjust}
sx={{
my: 0.75,
cursor: 'pointer',
borderRadius: 1,
px: 0.5,
mx: -0.5,
transition: 'background-color 0.15s ease',
'&:hover': {
backgroundColor: 'rgba(0, 0, 0, 0.05)',
},
}}
>
<Typography
component="div"
sx={{
fontSize: '1.25rem',
fontWeight: 700,
lineHeight: 1.2,
color: 'text.secondary',
}}
>
Keine Erfassung
</Typography>
<Typography
variant="caption"
color="text.secondary"
sx={{ display: 'block', mt: 0.25 }}
>
Bestand wird nicht überwacht
</Typography>
</Box>
)}
</Box>
{/* Bottom section: Per-warehouse breakdown */}
{isTrackStock && hasWarehouses ? (
<Box
sx={{
mt: 1,
flex: 1,
minHeight: 0,
overflowY: 'auto',
pr: 0.5,
'&::-webkit-scrollbar': { width: 4 },
'&::-webkit-scrollbar-thumb': {
backgroundColor: 'rgba(0, 0, 0, 0.15)',
borderRadius: 2,
},
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
{warehouses.map((wh) => (
<Box
key={wh.id}
sx={{
display: 'flex',
alignItems: 'center',
minWidth: 0,
mr: 1,
justifyContent: 'space-between',
py: 0.35,
px: 0.75,
borderRadius: 1,
backgroundColor: 'rgba(255, 255, 255, 0.55)',
}}
>
<WarehouseIcon
<Box
sx={{
fontSize: 15,
color: 'text.secondary',
mr: 0.5,
flexShrink: 0,
}}
/>
<Typography
variant="body2"
noWrap
title={wh.name}
sx={{
fontWeight: 500,
fontSize: '0.82rem',
color: 'text.primary',
display: 'flex',
alignItems: 'center',
minWidth: 0,
mr: 1,
}}
>
{wh.name}
<WarehouseIcon
sx={{
fontSize: 15,
color: 'text.secondary',
mr: 0.5,
flexShrink: 0,
}}
/>
<Typography
variant="body2"
noWrap
title={wh.name}
sx={{
fontWeight: 500,
fontSize: '0.82rem',
color: 'text.primary',
}}
>
{wh.name}
</Typography>
</Box>
<Typography
variant="body2"
sx={{
fontWeight: 700,
fontSize: '0.82rem',
flexShrink: 0,
color:
Number(wh.stock) > 0
? 'text.primary'
: 'text.secondary',
}}
>
{formatStock(wh.stock)}
</Typography>
</Box>
<Typography
variant="body2"
sx={{
fontWeight: 700,
fontSize: '0.82rem',
flexShrink: 0,
color:
Number(wh.stock) > 0
? 'text.primary'
: 'text.secondary',
}}
>
{formatStock(wh.stock)}
</Typography>
</Box>
))}
))}
</Box>
</Box>
</Box>
) : null}
</Box>
</PanelTile>
) : null}
</Box>
</PanelTile>
<ArticleStockAdjustDialog
open={adjustOpen}
onClose={this.handleCloseAdjust}
article={articleData}
/>
</>
);
}
<ArticleStockAdjustDialog
open={adjustOpen}
onClose={this.handleCloseAdjust}
article={articleData}
/>
</>
);
}
}