u
This commit is contained in:
@@ -39,6 +39,8 @@ import articleIndexAutomat from '../../../automats/articleIndexAutomat';
|
||||
import {
|
||||
MAGENTA_PANEL,
|
||||
SHADOW_CARD,
|
||||
WHITE,
|
||||
alpha,
|
||||
} from '../../../colors';
|
||||
|
||||
export default class ArticleViewLists extends PureComponent {
|
||||
@@ -1095,9 +1097,21 @@ export default class ArticleViewLists extends PureComponent {
|
||||
assignedMatch?.attributeValue ||
|
||||
null;
|
||||
|
||||
const siblings = (parentArticle?.children || []).filter(
|
||||
(c) => c.sku !== articleData.sku && c.id !== articleData.id
|
||||
const childrenList = parentArticle?.children || [];
|
||||
const hasSelf = childrenList.some(
|
||||
(c) => c.sku === articleData.sku || (articleData.id != null && c.id === articleData.id)
|
||||
);
|
||||
const siblings = hasSelf
|
||||
? childrenList
|
||||
: [
|
||||
...childrenList,
|
||||
{
|
||||
id: articleData.id,
|
||||
sku: articleData.sku,
|
||||
name: articleData.name,
|
||||
attributeValue: variationValue,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1, flex: 1, minHeight: 0 }}>
|
||||
@@ -1206,10 +1220,10 @@ export default class ArticleViewLists extends PureComponent {
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Link(s) Geschwister */}
|
||||
{/* Varianten */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.4, mt: 0.5 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, color: 'text.secondary' }}>
|
||||
Geschwister:
|
||||
Varianten:
|
||||
</Typography>
|
||||
{siblings.length === 0 ? (
|
||||
<Typography variant="body2" color="text.secondary" sx={{ py: 0.5, fontSize: '0.8rem' }}>
|
||||
@@ -1217,82 +1231,131 @@ export default class ArticleViewLists extends PureComponent {
|
||||
</Typography>
|
||||
) : (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||
{siblings.map((sibling) => (
|
||||
<Box
|
||||
key={sibling.id || sibling.sku}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 1,
|
||||
py: 0.6,
|
||||
borderRadius: 1,
|
||||
bgcolor: 'background.paper',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
transition: 'all 0.15s ease-in-out',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
boxShadow: SHADOW_CARD,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={artikelDetailPath(sibling.sku)}
|
||||
{siblings.map((sibling) => {
|
||||
const isSelf =
|
||||
sibling.sku === articleData.sku ||
|
||||
(articleData.id != null && sibling.id === articleData.id);
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={sibling.id || sibling.sku}
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
py: 0.25,
|
||||
cursor: 'pointer',
|
||||
'&:hover .child-name': {
|
||||
color: 'primary.main',
|
||||
},
|
||||
'&:hover .child-sku': {
|
||||
color: 'primary.dark',
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 1,
|
||||
py: 0.6,
|
||||
borderRadius: 1,
|
||||
bgcolor: isSelf ? alpha(WHITE, 0.6) : 'background.paper',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
transition: 'all 0.15s ease-in-out',
|
||||
...(!isSelf && {
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
boxShadow: SHADOW_CARD,
|
||||
},
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
className="child-name"
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
transition: 'color 0.15s ease',
|
||||
}}
|
||||
>
|
||||
{sibling.attributeValue || sibling.name || sibling.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
className="child-sku"
|
||||
variant="caption"
|
||||
{isSelf ? (
|
||||
<Box
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'primary.main',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
py: 0.25,
|
||||
}}
|
||||
>
|
||||
{sibling.sku}
|
||||
</Typography>
|
||||
<OpenInNewIcon sx={{ fontSize: 13, color: 'primary.main', opacity: 0.8 }} />
|
||||
</Box>
|
||||
</Link>
|
||||
</Box>
|
||||
))}
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
}}
|
||||
>
|
||||
{sibling.attributeValue || variationValue || sibling.name || sibling.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'text.secondary',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
}}
|
||||
>
|
||||
{sibling.sku}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
) : (
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={artikelDetailPath(sibling.sku)}
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
py: 0.25,
|
||||
cursor: 'pointer',
|
||||
'&:hover .child-name': {
|
||||
color: 'primary.main',
|
||||
},
|
||||
'&:hover .child-sku': {
|
||||
color: 'primary.dark',
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
className="child-name"
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
transition: 'color 0.15s ease',
|
||||
}}
|
||||
>
|
||||
{sibling.attributeValue || sibling.name || sibling.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
className="child-sku"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'primary.main',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
}}
|
||||
>
|
||||
{sibling.sku}
|
||||
</Typography>
|
||||
<OpenInNewIcon sx={{ fontSize: 13, color: 'primary.main', opacity: 0.8 }} />
|
||||
</Box>
|
||||
</Link>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
@@ -1510,6 +1573,176 @@ export default class ArticleViewLists extends PureComponent {
|
||||
) : null}
|
||||
</Box>
|
||||
|
||||
{/* Vaterartikel */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.4, mt: 0.25 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, color: 'text.secondary' }}>
|
||||
Vaterartikel:
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 1,
|
||||
py: 0.6,
|
||||
borderRadius: 1,
|
||||
bgcolor: alpha(WHITE, 0.6),
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
py: 0.25,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
className="link-title"
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
}}
|
||||
>
|
||||
{articleData.name || articleData.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
className="link-sku"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'text.secondary',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
}}
|
||||
>
|
||||
{articleData.sku}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Varianten */}
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.4, mt: 0.5 }}>
|
||||
<Typography variant="caption" sx={{ fontWeight: 600, color: 'text.secondary' }}>
|
||||
Varianten:
|
||||
</Typography>
|
||||
{children.length === 0 ? (
|
||||
<Typography variant="body2" color="text.secondary" sx={{ py: 1, fontSize: '0.8rem' }}>
|
||||
Noch keine Varianten angelegt.
|
||||
</Typography>
|
||||
) : (
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
|
||||
{children.map((child) => (
|
||||
<Box
|
||||
key={child.id || child.sku}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 1,
|
||||
py: 0.6,
|
||||
borderRadius: 1,
|
||||
bgcolor: 'background.paper',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
transition: 'all 0.15s ease-in-out',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
boxShadow: SHADOW_CARD,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={artikelDetailPath(child.sku)}
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
py: 0.25,
|
||||
mr: 1,
|
||||
cursor: 'pointer',
|
||||
'&:hover .child-name': {
|
||||
color: 'primary.main',
|
||||
},
|
||||
'&:hover .child-sku': {
|
||||
color: 'primary.dark',
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
className="child-name"
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
transition: 'color 0.15s ease',
|
||||
}}
|
||||
>
|
||||
{child.attributeValue || child.name || child.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
className="child-sku"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'primary.main',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.35,
|
||||
}}
|
||||
>
|
||||
{child.sku}
|
||||
</Typography>
|
||||
<OpenInNewIcon sx={{ fontSize: 13, color: 'primary.main', opacity: 0.8 }} />
|
||||
</Box>
|
||||
</Link>
|
||||
|
||||
<IconButton
|
||||
size="small"
|
||||
disabled={busy}
|
||||
onClick={() => this.handleOpenRemoveDialog(child)}
|
||||
title="Variante entfernen"
|
||||
sx={{
|
||||
p: 0.35,
|
||||
color: 'text.secondary',
|
||||
'&:hover': { color: 'error.main' },
|
||||
}}
|
||||
>
|
||||
<DeleteOutlinedIcon sx={{ fontSize: 17 }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
{/* Add Child Variant Row */}
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mt: 0.5 }}>
|
||||
{isCustomChildValue || availableParentValues.length === 0 ? (
|
||||
@@ -1533,7 +1766,17 @@ export default class ArticleViewLists extends PureComponent {
|
||||
label="Variante"
|
||||
value={selectedChildValueId}
|
||||
disabled={busy}
|
||||
onChange={(e) => this.setState({ selectedChildValueId: e.target.value })}
|
||||
onChange={(e) => {
|
||||
if (e.target.value === '__custom__') {
|
||||
this.setState({
|
||||
isCustomChildValue: true,
|
||||
selectedChildValueId: '',
|
||||
newChildText: '',
|
||||
});
|
||||
} else {
|
||||
this.setState({ selectedChildValueId: e.target.value });
|
||||
}
|
||||
}}
|
||||
sx={{ flex: 1, minWidth: 0 }}
|
||||
>
|
||||
<MenuItem value="" disabled>
|
||||
@@ -1544,6 +1787,9 @@ export default class ArticleViewLists extends PureComponent {
|
||||
{v.value}
|
||||
</MenuItem>
|
||||
))}
|
||||
<MenuItem value="__custom__">
|
||||
<em>+ Neuer Wert...</em>
|
||||
</MenuItem>
|
||||
</TextInput>
|
||||
)}
|
||||
|
||||
@@ -1597,117 +1843,6 @@ export default class ArticleViewLists extends PureComponent {
|
||||
</Link>
|
||||
</Box>
|
||||
) : null}
|
||||
|
||||
{/* Children List */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 0.5,
|
||||
mt: 0.5,
|
||||
}}
|
||||
>
|
||||
{children.length === 0 ? (
|
||||
<Typography variant="body2" color="text.secondary" sx={{ py: 1, fontSize: '0.8rem' }}>
|
||||
Noch keine Varianten angelegt.
|
||||
</Typography>
|
||||
) : (
|
||||
children.map((child) => (
|
||||
<Box
|
||||
key={child.id || child.sku}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
px: 1,
|
||||
py: 0.6,
|
||||
borderRadius: 1,
|
||||
bgcolor: 'background.paper',
|
||||
border: '1px solid',
|
||||
borderColor: 'divider',
|
||||
transition: 'all 0.15s ease-in-out',
|
||||
'&:hover': {
|
||||
borderColor: 'primary.main',
|
||||
boxShadow: SHADOW_CARD,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={artikelDetailPath(child.sku)}
|
||||
sx={{
|
||||
minWidth: 0,
|
||||
flex: 1,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
textDecoration: 'none',
|
||||
color: 'inherit',
|
||||
py: 0.25,
|
||||
mr: 1,
|
||||
cursor: 'pointer',
|
||||
'&:hover .child-name': {
|
||||
color: 'primary.main',
|
||||
},
|
||||
'&:hover .child-sku': {
|
||||
color: 'primary.dark',
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
className="child-name"
|
||||
variant="body2"
|
||||
sx={{
|
||||
fontWeight: 600,
|
||||
fontSize: '0.86rem',
|
||||
lineHeight: 1.3,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'text.primary',
|
||||
transition: 'color 0.15s ease',
|
||||
}}
|
||||
>
|
||||
{child.attributeValue || child.name || child.sku}
|
||||
</Typography>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.4, mt: 0.2 }}>
|
||||
<Typography
|
||||
className="child-sku"
|
||||
variant="caption"
|
||||
sx={{
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 600,
|
||||
color: 'primary.main',
|
||||
fontFamily: 'monospace',
|
||||
letterSpacing: '0.02em',
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.35,
|
||||
}}
|
||||
>
|
||||
{child.sku}
|
||||
</Typography>
|
||||
<OpenInNewIcon sx={{ fontSize: 13, color: 'primary.main', opacity: 0.8 }} />
|
||||
</Box>
|
||||
</Link>
|
||||
|
||||
<IconButton
|
||||
size="small"
|
||||
disabled={busy}
|
||||
onClick={() => this.handleOpenRemoveDialog(child)}
|
||||
title="Variante entfernen"
|
||||
sx={{
|
||||
p: 0.35,
|
||||
color: 'text.secondary',
|
||||
'&:hover': { color: 'error.main' },
|
||||
}}
|
||||
>
|
||||
<DeleteOutlinedIcon sx={{ fontSize: 17 }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
))
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
) : isChild && parentSku ? (
|
||||
/* ── Mode 2: Child Variant Article ───────────────────────────────── */
|
||||
|
||||
Reference in New Issue
Block a user