This commit is contained in:
seb
2026-07-31 18:20:46 +02:00
parent a6a9777f31
commit ce8d7d04da
4 changed files with 83 additions and 24 deletions

View File

@@ -6,6 +6,12 @@ import Typography from '@mui/material/Typography';
import { article } from '../../api';
import { EditablePanelTile, PanelTile, PanelTileGrid } from '../panels';
import { requireObject } from '../../utils/apiShape';
import {
articleEans,
brandName,
priceBrutto,
primaryPrice,
} from '../../utils/articleDetail';
import { formatPrice } from '../../utils/price';
import { formatStock } from '../../pages/artikel/searchFormat';
@@ -68,11 +74,6 @@ function RelationLine({ label, active, children }) {
);
}
function articleBrutto(article) {
if (article.net == null || article.taxRate == null) return null;
return article.net * (1 + article.taxRate / 100);
}
function nameDraftDirty(draft, saved) {
return draft.name.trim() !== String(saved.name ?? '').trim();
}
@@ -82,7 +83,9 @@ function nameDraftValid(draft) {
}
export default function ArticleView({ article: articleData, onArticleUpdated }) {
const brutto = articleBrutto(articleData);
const basePrice = primaryPrice(articleData);
const brutto = priceBrutto(basePrice);
const eans = articleEans(articleData);
const handleSaveName = async (draft) => {
const name = draft.name.trim();
@@ -108,7 +111,7 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
display: 'flex',
alignItems: 'center',
minHeight: { xs: 0, sm: 200 },
pr: 4,
pr: 5,
}}
>
<Typography variant="h6" sx={{ fontWeight: 700, lineHeight: 1.25 }}>
@@ -153,20 +156,24 @@ export default function ArticleView({ article: articleData, onArticleUpdated })
</PanelTile>
<PanelTile wide={1} title="Marke">
<PanelValue>{articleData.brand}</PanelValue>
<PanelValue>{brandName(articleData)}</PanelValue>
</PanelTile>
<PanelTile wide={1} title="SKU / EAN">
<PanelValue label="SKU">{articleData.sku}</PanelValue>
<PanelValue label="EAN">{articleData.ean}</PanelValue>
{eans.map((ean) => (
<PanelValue key={ean} label="EAN">
{ean}
</PanelValue>
))}
</PanelTile>
<PanelTile wide={1} title="Preis">
<PanelValue label="Netto">
{articleData.net != null ? formatPrice(articleData.net) : null}
{basePrice?.net != null ? formatPrice(basePrice.net) : null}
</PanelValue>
<PanelValue label="MwSt.">
{articleData.taxRate != null ? `${articleData.taxRate} %` : null}
{basePrice?.taxRate != null ? `${basePrice.taxRate} %` : null}
</PanelValue>
<PanelValue label="Brutto">
{brutto != null ? formatPrice(brutto) : null}

View File

@@ -70,7 +70,7 @@ export class EditablePanelTile extends Component {
};
handleCancel = (event) => {
event.stopPropagation();
event?.stopPropagation();
this.setState({
editing: false,
draft: null,
@@ -82,8 +82,25 @@ export class EditablePanelTile extends Component {
this.setState({ draft: nextDraft, error: null });
};
handleEditKeyDown = (event) => {
if (event.key === 'Escape') {
event.preventDefault();
event.stopPropagation();
this.handleCancel();
return;
}
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
event.stopPropagation();
if (this.canSave()) {
void this.handleSave(event);
}
}
};
handleSave = async (event) => {
event.stopPropagation();
event?.stopPropagation();
if (!this.canSave()) return;
const { onSave } = this.props;
@@ -109,7 +126,7 @@ export class EditablePanelTile extends Component {
<Typography
variant="overline"
color="text.secondary"
sx={{ display: 'block', mb: 1, pr: editing ? 7 : 4 }}
sx={{ display: 'block', mb: 1, pr: editing ? 9 : 5 }}
>
{title}
</Typography>
@@ -126,16 +143,16 @@ export class EditablePanelTile extends Component {
top: 4,
color: 'text.secondary',
};
const iconSx = { fontSize: 28 };
if (!editing) {
return (
<IconButton
size="small"
onClick={this.handleStartEdit}
aria-label="Bearbeiten"
sx={{ ...actionSx, right: 4 }}
>
<EditOutlinedIcon fontSize="small" />
<EditOutlinedIcon sx={iconSx} />
</IconButton>
);
}
@@ -143,16 +160,14 @@ export class EditablePanelTile extends Component {
return (
<>
<IconButton
size="small"
onClick={this.handleCancel}
disabled={saving}
aria-label="Abbrechen"
sx={{ ...actionSx, right: 40 }}
sx={{ ...actionSx, right: 48 }}
>
<CloseOutlinedIcon fontSize="small" />
<CloseOutlinedIcon sx={iconSx} />
</IconButton>
<IconButton
size="small"
onClick={this.handleSave}
disabled={!this.canSave()}
aria-label="Speichern"
@@ -160,9 +175,9 @@ export class EditablePanelTile extends Component {
sx={{ ...actionSx, right: 4 }}
>
{saving ? (
<CircularProgress size={18} color="inherit" />
<CircularProgress size={22} color="inherit" />
) : (
<SaveOutlinedIcon fontSize="small" />
<SaveOutlinedIcon sx={iconSx} />
)}
</IconButton>
</>
@@ -188,7 +203,10 @@ export class EditablePanelTile extends Component {
>
{this.renderActions()}
{this.renderTitle()}
<Box sx={{ flex: 1, minWidth: 0, pr: editing ? 1 : 0 }}>
<Box
sx={{ flex: 1, minWidth: 0, pr: editing ? 1 : 0 }}
onKeyDown={editing ? this.handleEditKeyDown : undefined}
>
{editing && draft != null
? renderEdit(draft, this.handleDraftChange, this.inputRef)
: renderDisplay(savedValue)}