This commit is contained in:
seb
2026-07-31 08:34:51 +02:00
parent a95b7f4b1e
commit 797ea59bed
24 changed files with 1151 additions and 130 deletions

View File

@@ -0,0 +1,18 @@
import AddIcon from '@mui/icons-material/Add';
import Typography from '@mui/material/Typography';
import { Tile } from './Tile';
export class ActionTile extends Tile {
renderIcon() {
return <AddIcon color="primary" sx={{ fontSize: 40 }} />;
}
renderLabel() {
const { label = 'Aktion' } = this.props;
return (
<Typography variant="body2" fontWeight={600} sx={{ lineHeight: 1.2 }}>
{label}
</Typography>
);
}
}

View File

@@ -0,0 +1,27 @@
import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined';
import Typography from '@mui/material/Typography';
import { Tile } from './Tile';
import { formatPrice } from '../../utils/price';
export class ArticleTile extends Tile {
renderIcon() {
return <Inventory2OutlinedIcon color="action" sx={{ fontSize: 36 }} />;
}
renderSecondary() {
const { article } = this.props;
if (!article) return null;
return (
<>
<Typography variant="caption" color="text.secondary" noWrap sx={{ maxWidth: '100%' }}>
{article.sku}
</Typography>
{article.price != null && (
<Typography variant="caption" fontWeight={600}>
{formatPrice(article.price)}
</Typography>
)}
</>
);
}
}

View File

@@ -0,0 +1,18 @@
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
import Typography from '@mui/material/Typography';
import { Tile } from './Tile';
export class BackTile extends Tile {
renderIcon() {
return <ArrowBackIcon color="action" sx={{ fontSize: 36 }} />;
}
renderLabel() {
const { label = 'Zurück' } = this.props;
return (
<Typography variant="body2" fontWeight={600} sx={{ lineHeight: 1.2 }}>
{label}
</Typography>
);
}
}

View File

@@ -0,0 +1,8 @@
import FolderIcon from '@mui/icons-material/Folder';
import { Tile } from './Tile';
export class CategoryTile extends Tile {
renderIcon() {
return <FolderIcon color="primary" sx={{ fontSize: 40 }} />;
}
}

View File

@@ -0,0 +1,81 @@
import { Component } from 'react';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
export const TILE_SIZE = 140;
export const tileBaseSx = {
aspectRatio: '1 / 1',
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
gap: 1,
p: 1.5,
cursor: 'pointer',
userSelect: 'none',
textAlign: 'center',
transition: 'border-color 0.15s, background-color 0.15s',
'&:hover': {
bgcolor: 'action.hover',
borderColor: 'primary.main',
},
};
export class Tile extends Component {
handleClick = () => {
this.props.onClick?.();
};
renderIcon() {
return null;
}
renderLabel() {
const { label } = this.props;
if (!label) return null;
return (
<Typography variant="body2" fontWeight={600} sx={{ lineHeight: 1.2 }}>
{label}
</Typography>
);
}
renderSecondary() {
const { secondary } = this.props;
if (!secondary) return null;
return (
<Typography variant="caption" color="text.secondary" sx={{ lineHeight: 1.2 }}>
{secondary}
</Typography>
);
}
render() {
const { sx, disabled } = this.props;
return (
<Paper
variant="outlined"
component="button"
type="button"
disabled={disabled}
onClick={this.handleClick}
sx={{
...tileBaseSx,
border: '1px solid',
borderColor: 'divider',
bgcolor: 'background.paper',
...(disabled
? { opacity: 0.5, pointerEvents: 'none' }
: {}),
...sx,
}}
>
{this.renderIcon()}
{this.renderLabel()}
{this.renderSecondary()}
</Paper>
);
}
}

View File

@@ -0,0 +1,5 @@
export { TILE_SIZE, Tile, tileBaseSx } from './Tile';
export { BackTile } from './BackTile';
export { CategoryTile } from './CategoryTile';
export { ArticleTile } from './ArticleTile';
export { ActionTile } from './ActionTile';