Enhance product display in PrerenderProduct: Added a utility function to clean product names, improved layout with Box components for better styling, and formatted price display with tax. Updated product details section to include manufacturer, weight, and availability status, ensuring a more informative and visually appealing product presentation.

This commit is contained in:
sebseb7
2025-07-19 11:23:31 +02:00
parent b602444066
commit 5fb3e10598

View File

@@ -14,18 +14,30 @@ const {
const Footer = require('./components/Footer.js').default;
const { Logo } = require('./components/header/index.js');
// Utility function to clean product names by removing trailing number in parentheses
const cleanProductName = (name) => {
if (!name) return "";
// Remove patterns like " (1)", " (3)", " (10)" at the end of the string
return name.replace(/\s*\(\d+\)\s*$/, "").trim();
};
class PrerenderProduct extends React.Component {
render() {
const { productData } = this.props;
if (!productData) {
return React.createElement(
Container,
{ maxWidth: 'lg', sx: { py: 4 } },
Box,
{ sx: { p: 4, textAlign: "center" } },
React.createElement(
Typography,
{ variant: 'h4', component: 'h1', gutterBottom: true },
'Product not found'
{ variant: 'h5', gutterBottom: true },
'Produkt nicht gefunden'
),
React.createElement(
Typography,
null,
'Das gesuchte Produkt existiert nicht oder wurde entfernt.'
)
);
}
@@ -36,6 +48,12 @@ class PrerenderProduct extends React.Component {
? `/assets/images/prod${product.pictureList.split(',')[0].trim()}.jpg`
: '/assets/images/nopicture.jpg';
// Format price with tax
const priceWithTax = new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR",
}).format(product.price);
return React.createElement(
Box,
{
@@ -48,7 +66,7 @@ class PrerenderProduct extends React.Component {
bgcolor: 'background.default'
}
},
React.createElement(
React.createElement(
AppBar,
{ position: 'sticky', color: 'primary', elevation: 0, sx: { zIndex: 1100 } },
React.createElement(
@@ -62,18 +80,43 @@ class PrerenderProduct extends React.Component {
)
),
React.createElement(
Container,
{ maxWidth: 'lg', sx: { py: 4, flexGrow: 1 } },
Box,
{
sx: {
p: { xs: 2, md: 2 },
pb: { xs: 4, md: 8 },
maxWidth: "1400px",
mx: "auto",
flexGrow: 1
}
},
React.createElement(
Grid,
{ container: true, spacing: 4 },
// Product Image
React.createElement(
Grid,
{ item: true, xs: 12, md: 6 },
Box,
{
sx: {
display: "flex",
flexDirection: { xs: "column", md: "row" },
gap: 4,
background: "#fff",
borderRadius: 2,
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
}
},
// Product Image Section
React.createElement(
Card,
{ sx: { height: '100%' } },
Box,
{
sx: {
width: { xs: "100%", sm: "555px" },
maxWidth: "100%",
minHeight: "400px",
background: "#f8f8f8",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
}
},
React.createElement(
CardMedia,
{
@@ -84,108 +127,175 @@ class PrerenderProduct extends React.Component {
sx: { objectFit: 'contain', p: 2 }
}
)
)
),
// Product Details
React.createElement(
Grid,
{ item: true, xs: 12, md: 6 },
),
// Product Details Section
React.createElement(
Stack,
{ spacing: 3 },
React.createElement(
Typography,
{ variant: 'h3', component: 'h1', gutterBottom: true },
product.name
),
React.createElement(
Typography,
{ variant: 'h6', color: 'text.secondary' },
(this.props.t ? this.props.t('product.articleNumber') : 'Artikelnummer')+': '+product.articleNumber+' '+(product.gtin ? ` | GTIN: ${product.gtin}` : "")
),
Box,
{
sx: {
flex: "1 1 60%",
p: { xs: 2, md: 4 },
display: "flex",
flexDirection: "column",
}
},
// Product identifiers
React.createElement(
Box,
{ sx: { mt: 1 } },
{ sx: { mb: 1 } },
React.createElement(
Typography,
{ variant: 'h4', color: 'primary', fontWeight: 'bold' },
new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
}).format(product.price)
),
product.vat && React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
`inkl. ${product.vat}% MwSt.`
),
React.createElement(
Typography,
{
variant: 'body1',
color: product.available ? 'success.main' : 'error.main',
fontWeight: 'medium',
sx: { mt: 1 }
},
product.available ? '✅ Verfügbar' : '❌ Nicht verfügbar'
(this.props.t ? this.props.t('product.articleNumber') : 'Artikelnummer')+': '+product.articleNumber+' '+(product.gtin ? ` | GTIN: ${product.gtin}` : "")
)
),
product.description && React.createElement(
Box,
{ sx: { mt: 2 } },
React.createElement(
Typography,
{ variant: 'h6', gutterBottom: true },
'Beschreibung'
),
React.createElement(
'div',
{
dangerouslySetInnerHTML: { __html: product.description },
style: {
fontFamily: '"Roboto","Helvetica","Arial",sans-serif',
fontSize: '1rem',
lineHeight: '1.5',
color: '#33691E'
}
}
)
),
// Product specifications
// Product title
React.createElement(
Typography,
{
variant: 'h4',
component: 'h1',
gutterBottom: true,
sx: { fontWeight: 600, color: "#333" }
},
cleanProductName(product.name)
),
// Manufacturer if available
product.manufacturer && React.createElement(
Box,
{ sx: { mt: 2 } },
{ sx: { display: "flex", alignItems: "center", mb: 2 } },
React.createElement(
Typography,
{ variant: 'h6', gutterBottom: true },
'Produktdetails'
),
{ variant: 'body2', sx: { fontStyle: "italic" } },
(this.props.t ? this.props.t('product.manufacturer') : 'Hersteller')+': '+product.manufacturer
)
),
// Product specifications (attributes)
attributes.length > 0 && React.createElement(
Box,
{ sx: { mb: 2 } },
React.createElement(
Stack,
{ direction: 'row', spacing: 1, flexWrap: 'wrap', gap: 1 },
product.manufacturer && React.createElement(
Chip,
{ label: `Hersteller: ${product.manufacturer}`, variant: 'outlined' }
),
product.weight && product.weight > 0 && React.createElement(
Chip,
{ label: `Gewicht: ${product.weight} kg`, variant: 'outlined' }
),
...attributes.map((attr, index) =>
React.createElement(
Chip,
{
key: index,
label: `${attr.cName}: ${attr.cWert}`,
variant: 'outlined',
color: 'primary'
disabled: true,
sx: { mb: 1 }
}
)
)
)
),
// Weight
product.weight && product.weight > 0 && React.createElement(
Box,
{ sx: { mb: 2 } },
React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
(this.props.t ? this.props.t('product.weight', { weight: product.weight.toFixed(1).replace(".", ",") }) : `Gewicht: ${product.weight.toFixed(1).replace(".", ",")} kg`)
)
),
// Price and availability section
React.createElement(
Box,
{
sx: {
mt: "auto",
p: 3,
background: "#f9f9f9",
borderRadius: 2,
}
},
React.createElement(
Box,
{
sx: {
display: "flex",
flexDirection: { xs: "column", sm: "row" },
justifyContent: "space-between",
alignItems: { xs: "flex-start", sm: "flex-start" },
gap: 2,
}
},
React.createElement(
Box,
null,
React.createElement(
Typography,
{
variant: "h4",
color: "primary",
sx: { fontWeight: "bold" }
},
priceWithTax
),
product.vat && React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
(this.props.t ? this.props.t('product.inclVat', { vat: product.vat }) : `inkl. ${product.vat}% MwSt.`)
),
product.versandklasse &&
product.versandklasse != "standard" &&
product.versandklasse != "kostenlos" && React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
product.versandklasse
),
React.createElement(
Typography,
{
variant: 'body1',
color: product.available ? 'success.main' : 'error.main',
fontWeight: 'medium',
sx: { mt: 1 }
},
product.available ? '✅ Verfügbar' : '❌ Nicht verfügbar'
)
)
)
)
)
),
// Product full description
product.description && React.createElement(
Box,
{
sx: {
mt: 4,
p: 4,
background: "#fff",
borderRadius: 2,
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
}
},
React.createElement(
Box,
{
sx: {
mt: 2,
lineHeight: 1.7,
"& p": { mt: 0, mb: 2 },
"& strong": { fontWeight: 600 },
}
},
React.createElement(
'div',
{
dangerouslySetInnerHTML: { __html: product.description },
style: {
fontFamily: '"Roboto","Helvetica","Arial",sans-serif',
fontSize: '1rem',
lineHeight: '1.7',
color: '#333'
}
}
)
)
)
)
),
React.createElement(Footer)