diff --git a/src/PrerenderProduct.js b/src/PrerenderProduct.js index 0db1cc2..f6baa2e 100644 --- a/src/PrerenderProduct.js +++ b/src/PrerenderProduct.js @@ -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)