u
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
primaryPrice,
|
||||
} from '../../utils/articleDetail';
|
||||
import { formatPrice } from '../../utils/price';
|
||||
import { PANEL_TILE_KEYS } from '../../theme';
|
||||
import { formatStock } from '../../pages/artikel/searchFormat';
|
||||
|
||||
function PanelValue({ label, children }) {
|
||||
@@ -46,7 +47,6 @@ function ArticlePhoto() {
|
||||
}
|
||||
|
||||
const headerTileSx = {
|
||||
p: 1.25,
|
||||
minHeight: 0,
|
||||
};
|
||||
|
||||
@@ -99,6 +99,7 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
|
||||
<PanelTileGrid>
|
||||
<EditablePanelTile
|
||||
wide={3}
|
||||
tileKey={PANEL_TILE_KEYS.name}
|
||||
minHeight={0}
|
||||
sx={headerTileSx}
|
||||
value={{ name: articleData.name ?? '' }}
|
||||
@@ -145,21 +146,21 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
|
||||
)}
|
||||
/>
|
||||
|
||||
<PanelTile wide={1} minHeight={0} sx={headerTileSx}>
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.photo} minHeight={0} sx={headerTileSx}>
|
||||
<ArticlePhoto />
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={1} title="Bestand">
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.stock} title="Bestand">
|
||||
<PanelValue>
|
||||
{articleData.stock != null ? formatStock(articleData.stock) : null}
|
||||
</PanelValue>
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={1} title="Marke">
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.brand} title="Marke">
|
||||
<PanelValue>{brandName(articleData)}</PanelValue>
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={1} title="SKU / EAN">
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.identifiers} title="SKU / EAN">
|
||||
<PanelValue label="SKU">{articleData.sku}</PanelValue>
|
||||
{eans.map((ean) => (
|
||||
<PanelValue key={ean} label="EAN">
|
||||
@@ -168,7 +169,7 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
|
||||
))}
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={1} title="Preis">
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.price} title="Preis">
|
||||
<PanelValue label="Netto">
|
||||
{basePrice?.net != null ? formatPrice(basePrice.net) : null}
|
||||
</PanelValue>
|
||||
@@ -180,14 +181,14 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
|
||||
</PanelValue>
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={3} title="SEO & Beschreibung" minHeight={200}>
|
||||
<PanelTile wide={3} tileKey={PANEL_TILE_KEYS.content} title="SEO & Beschreibung" minHeight={200}>
|
||||
<PanelValue label="Slug">{articleData.slug}</PanelValue>
|
||||
<PanelValue label="SEO-Titel">{articleData.seoTitle}</PanelValue>
|
||||
<PanelValue label="SEO-Beschreibung">{articleData.seoDescription}</PanelValue>
|
||||
<PanelValue label="Beschreibung">{articleData.description}</PanelValue>
|
||||
</PanelTile>
|
||||
|
||||
<PanelTile wide={1} title="Listen" minHeight={200}>
|
||||
<PanelTile wide={1} tileKey={PANEL_TILE_KEYS.lists} title="Listen" minHeight={200}>
|
||||
<RelationLine
|
||||
label="Vaterartikel"
|
||||
active={articleData.childCount > 0}
|
||||
|
||||
@@ -8,6 +8,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { injectMuiTheme } from './injectMuiTheme';
|
||||
import { enqueueSnackbar } from 'notistack';
|
||||
import { backendErrorFrom } from '../../utils/backendError';
|
||||
import { panelTilePaperSx } from './panelTileLayout';
|
||||
@@ -20,7 +21,7 @@ function valuesEqual(a, b) {
|
||||
* Panel tile with centralized inline-edit chrome.
|
||||
* Pass `onSave` to enable edit UI; omit it for read-only tiles (no edit icon).
|
||||
*/
|
||||
export class EditablePanelTile extends Component {
|
||||
class EditablePanelTileBase extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.inputRef = createRef();
|
||||
@@ -186,9 +187,11 @@ export class EditablePanelTile extends Component {
|
||||
|
||||
render() {
|
||||
const {
|
||||
theme,
|
||||
wide = 1,
|
||||
sx,
|
||||
minHeight = 120,
|
||||
tileKey,
|
||||
renderDisplay,
|
||||
renderEdit,
|
||||
} = this.props;
|
||||
@@ -198,8 +201,15 @@ export class EditablePanelTile extends Component {
|
||||
|
||||
return (
|
||||
<Paper
|
||||
variant="outlined"
|
||||
sx={panelTilePaperSx({ wide, sx, minHeight, pending })}
|
||||
elevation={0}
|
||||
sx={panelTilePaperSx({
|
||||
wide,
|
||||
sx,
|
||||
minHeight,
|
||||
pending,
|
||||
tileKey,
|
||||
theme,
|
||||
})}
|
||||
>
|
||||
{this.renderActions()}
|
||||
{this.renderTitle()}
|
||||
@@ -220,3 +230,5 @@ export class EditablePanelTile extends Component {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const EditablePanelTile = injectMuiTheme(EditablePanelTileBase);
|
||||
|
||||
@@ -2,9 +2,10 @@ import { Component } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import Paper from '@mui/material/Paper';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { injectMuiTheme } from './injectMuiTheme';
|
||||
import { GRID_COLUMNS, panelTilePaperSx } from './panelTileLayout';
|
||||
|
||||
export class PanelTile extends Component {
|
||||
class PanelTileBase extends Component {
|
||||
renderTitle() {
|
||||
const { title } = this.props;
|
||||
if (!title) return null;
|
||||
@@ -20,12 +21,18 @@ export class PanelTile extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { wide = 1, children, sx, minHeight = 120 } = this.props;
|
||||
const { theme, wide = 1, children, sx, minHeight = 120, tileKey } = this.props;
|
||||
|
||||
return (
|
||||
<Paper
|
||||
variant="outlined"
|
||||
sx={panelTilePaperSx({ wide, sx, minHeight })}
|
||||
elevation={0}
|
||||
sx={panelTilePaperSx({
|
||||
wide,
|
||||
sx,
|
||||
minHeight,
|
||||
tileKey,
|
||||
theme,
|
||||
})}
|
||||
>
|
||||
{this.renderTitle()}
|
||||
<Box sx={{ flex: 1, minWidth: 0 }}>{children}</Box>
|
||||
@@ -34,6 +41,8 @@ export class PanelTile extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export const PanelTile = injectMuiTheme(PanelTileBase);
|
||||
|
||||
export function PanelTileGrid({ children, sx }) {
|
||||
return (
|
||||
<Box
|
||||
|
||||
13
src/components/panels/injectMuiTheme.jsx
Normal file
13
src/components/panels/injectMuiTheme.jsx
Normal file
@@ -0,0 +1,13 @@
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
|
||||
/** Injects MUI theme into class components (replaces removed withTheme HOC). */
|
||||
export function injectMuiTheme(Wrapped) {
|
||||
function ComponentWithTheme(props) {
|
||||
const theme = useTheme();
|
||||
return <Wrapped {...props} theme={theme} />;
|
||||
}
|
||||
|
||||
const name = Wrapped.displayName || Wrapped.name || 'Component';
|
||||
ComponentWithTheme.displayName = `injectMuiTheme(${name})`;
|
||||
return ComponentWithTheme;
|
||||
}
|
||||
@@ -17,7 +17,21 @@ export function responsiveColumnSpan(wide) {
|
||||
|
||||
export const PENDING_EDIT_RING_PX = 4;
|
||||
|
||||
export function panelTilePaperSx({ wide, sx, minHeight = 120, pending = false }) {
|
||||
export function panelTileBackground(theme, tileKey) {
|
||||
if (!tileKey || !theme?.panelTiles) return undefined;
|
||||
return theme.panelTiles[tileKey];
|
||||
}
|
||||
|
||||
export function panelTilePaperSx({
|
||||
wide,
|
||||
sx,
|
||||
minHeight = 120,
|
||||
pending = false,
|
||||
tileKey,
|
||||
theme,
|
||||
}) {
|
||||
const tileBg = panelTileBackground(theme, tileKey);
|
||||
|
||||
return {
|
||||
gridColumn: responsiveColumnSpan(wide),
|
||||
position: 'relative',
|
||||
@@ -25,6 +39,9 @@ export function panelTilePaperSx({ wide, sx, minHeight = 120, pending = false })
|
||||
minHeight,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
border: 'none',
|
||||
boxShadow: 'none',
|
||||
...(tileBg ? { bgcolor: tileBg } : {}),
|
||||
...(pending
|
||||
? {
|
||||
boxShadow: `inset 0 0 0 ${PENDING_EDIT_RING_PX}px ${PENDING_EDIT_BORDER}`,
|
||||
|
||||
Reference in New Issue
Block a user