164 lines
4.3 KiB
JavaScript
164 lines
4.3 KiB
JavaScript
import Inventory2OutlinedIcon from '@mui/icons-material/Inventory2Outlined';
|
|
import Box from '@mui/material/Box';
|
|
import ButtonBase from '@mui/material/ButtonBase';
|
|
import Typography from '@mui/material/Typography';
|
|
import { Tile, tileBaseSx } from 'dashgui/tiles';
|
|
import { formatPrice } from '../../utils/price';
|
|
import { articleSku } from '../article/articleRoute';
|
|
import ArticlePhoto from '../article/ArticlePhoto';
|
|
import { BrandLabel } from '../brand';
|
|
|
|
export class ArticleTile extends Tile {
|
|
hasPhoto() {
|
|
const { article } = this.props;
|
|
return article?.thumbHash != null || article?.fullHash != null;
|
|
}
|
|
|
|
renderIcon() {
|
|
return <Inventory2OutlinedIcon color="action" sx={{ fontSize: 36 }} />;
|
|
}
|
|
|
|
renderSecondary() {
|
|
const { article } = this.props;
|
|
if (!article) return null;
|
|
const sku = articleSku(article);
|
|
const brand = article.brand;
|
|
return (
|
|
<>
|
|
{brand?.name ? (
|
|
<BrandLabel
|
|
brand={brand}
|
|
name={brand.name}
|
|
size={16}
|
|
spacing={0.5}
|
|
typographyProps={{
|
|
variant: 'caption',
|
|
color: 'text.secondary',
|
|
fontWeight: 500,
|
|
noWrap: true,
|
|
}}
|
|
/>
|
|
) : null}
|
|
{sku ? (
|
|
<Typography variant="caption" color="text.secondary" noWrap sx={{ maxWidth: '100%' }}>
|
|
{sku}
|
|
</Typography>
|
|
) : null}
|
|
{article.net != null && (
|
|
<Typography variant="caption" fontWeight={600}>
|
|
{formatPrice(article.net)}
|
|
</Typography>
|
|
)}
|
|
</>
|
|
);
|
|
}
|
|
|
|
renderExtra() {
|
|
const childCount = Number(this.props.article?.childCount) || 0;
|
|
if (childCount <= 0) return null;
|
|
return (
|
|
<Box
|
|
sx={{
|
|
position: 'absolute',
|
|
top: 6,
|
|
right: 6,
|
|
zIndex: 1,
|
|
px: 0.75,
|
|
py: 0.25,
|
|
borderRadius: 999,
|
|
bgcolor: 'rgba(0, 0, 0, 0.65)',
|
|
color: 'common.white',
|
|
fontSize: 11,
|
|
fontWeight: 600,
|
|
lineHeight: 1.2,
|
|
whiteSpace: 'nowrap',
|
|
pointerEvents: 'none',
|
|
}}
|
|
>
|
|
{childCount}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
render() {
|
|
if (!this.hasPhoto()) {
|
|
return super.render();
|
|
}
|
|
|
|
const { article, label, sx, disabled } = this.props;
|
|
const sku = articleSku(article);
|
|
|
|
return (
|
|
<ButtonBase
|
|
component="button"
|
|
type="button"
|
|
disabled={disabled}
|
|
onClick={this.handleClick}
|
|
sx={{
|
|
...tileBaseSx,
|
|
p: 0,
|
|
gap: 0,
|
|
position: 'relative',
|
|
...(disabled ? { opacity: 0.5, pointerEvents: 'none' } : {}),
|
|
...sx,
|
|
}}
|
|
>
|
|
<Box sx={{ position: 'absolute', inset: 0 }}>
|
|
<ArticlePhoto
|
|
fill
|
|
photo={{
|
|
fullHash: article.fullHash,
|
|
thumbW: article.thumbW,
|
|
thumbH: article.thumbH,
|
|
thumbHash: article.thumbHash,
|
|
}}
|
|
/>
|
|
</Box>
|
|
{this.renderExtra()}
|
|
<Box
|
|
sx={{
|
|
position: 'absolute',
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
px: 1,
|
|
py: 0.75,
|
|
background: 'linear-gradient(transparent, rgba(0,0,0,0.65))',
|
|
textAlign: 'left',
|
|
}}
|
|
>
|
|
{article?.brand?.name ? (
|
|
<BrandLabel
|
|
brand={article.brand}
|
|
name={article.brand.name}
|
|
size={14}
|
|
spacing={0.5}
|
|
typographyProps={{
|
|
variant: 'caption',
|
|
noWrap: true,
|
|
sx: { color: 'rgba(255,255,255,0.9)', fontWeight: 500, lineHeight: 1.1 },
|
|
}}
|
|
sx={{ mb: 0.25 }}
|
|
/>
|
|
) : null}
|
|
{label ? (
|
|
<Typography
|
|
variant="body2"
|
|
fontWeight={600}
|
|
noWrap
|
|
sx={{ color: '#fff', lineHeight: 1.2 }}
|
|
>
|
|
{label}
|
|
</Typography>
|
|
) : null}
|
|
{sku ? (
|
|
<Typography variant="caption" noWrap sx={{ color: 'rgba(255,255,255,0.85)' }}>
|
|
{sku}
|
|
</Typography>
|
|
) : null}
|
|
</Box>
|
|
</ButtonBase>
|
|
);
|
|
}
|
|
}
|