Files
reactShop/src/PrerenderProduct.js

425 lines
14 KiB
JavaScript

const React = require('react');
const {
Container,
Typography,
Card,
CardMedia,
Grid,
Box,
Chip,
Stack,
AppBar,
Toolbar
} = require('@mui/material');
const Footer = require('./components/Footer.js').default;
const { Logo } = require('./components/header/index.js');
const ProductImage = require('./components/ProductImage.js').default;
// 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(
Box,
{ sx: { p: 4, textAlign: "center" } },
React.createElement(
Typography,
{ variant: 'h5', gutterBottom: true },
'Produkt nicht gefunden'
),
React.createElement(
Typography,
null,
'Das gesuchte Produkt existiert nicht oder wurde entfernt.'
)
);
}
const product = productData.product;
const attributes = productData.attributes || [];
const mainImage = product.pictureList && product.pictureList.trim()
? `/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,
{
sx: {
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
mb: 0,
pb: 0,
bgcolor: 'background.default'
}
},
React.createElement(
AppBar,
{ position: 'sticky', color: 'primary', elevation: 0, sx: { zIndex: 1100 } },
React.createElement(
Toolbar,
{ sx: { minHeight: 64 } },
React.createElement(
Container,
{ maxWidth: 'lg', sx: { display: 'flex', alignItems: 'center', px: { xs: 0, sm: 3 } } },
React.createElement(Logo)
)
)
),
React.createElement(
Box,
{ sx: { flexGrow: 1 } },
React.createElement(
Container,
{
maxWidth: "lg",
sx: {
p: { xs: 2, md: 2 },
pb: { xs: 4, md: 8 },
flexGrow: 1
}
},
// Back button (breadcrumbs section)
React.createElement(
Box,
{
sx: {
mb: 2,
position: ["-webkit-sticky", "sticky"],
top: {
xs: "80px",
sm: "80px",
md: "80px",
lg: "80px",
},
left: 0,
width: "100%",
display: "flex",
zIndex: 999, // Just below the AppBar
py: 0,
px: 2,
}
},
React.createElement(
Box,
{
sx: {
ml: { xs: 0, md: 0 },
display: "inline-flex",
px: 0,
py: 1,
backgroundColor: "#2e7d32", // primary dark green
borderRadius: 1,
}
},
React.createElement(
Typography,
{ variant: "body2", color: "text.secondary" },
React.createElement(
'a',
{
href: "#",
onClick: (e) => {
e.preventDefault();
if (window.history.length > 1) {
window.history.back();
} else {
window.location.href = '/';
}
},
style: {
paddingLeft: 16,
paddingRight: 16,
paddingTop: 8,
paddingBottom: 8,
textDecoration: "none",
color: "#fff",
fontWeight: "bold",
cursor: "pointer"
}
},
this.props.t ? this.props.t('common.back') : 'Zurück'
)
)
)
),
React.createElement(
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(
ProductImage,
{
product: product,
isPrerender: true
}
),
// Product Details Section
React.createElement(
Box,
{
sx: {
flex: "1 1 60%",
p: { xs: 2, md: 4 },
display: "flex",
flexDirection: "column",
}
},
// Product identifiers
React.createElement(
Box,
{ sx: { mb: 1 } },
React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
(this.props.t ? this.props.t('product.articleNumber') : 'Artikelnummer')+': '+product.articleNumber+' '+(product.gtin ? ` | GTIN: ${product.gtin}` : "")
)
),
// Product title
React.createElement(
Typography,
{
variant: 'h4',
component: 'h1',
gutterBottom: true,
sx: {
fontWeight: 600,
color: "#333"
}
},
cleanProductName(product.name)
),
// Manufacturer if available
React.createElement(
Box,
{ sx: { display: "flex", alignItems: "center", mb: 2 } },
product.manufacturer && React.createElement(
Typography,
{ variant: 'body2', sx: { fontStyle: "italic" } },
(this.props.t ? this.props.t('product.manufacturer') : 'Hersteller')+': '+product.manufacturer
)
),
// Attribute images and chips with action buttons section
(attributes.length > 0) && React.createElement(
Box,
{ sx: { display: "flex", justifyContent: "space-between", alignItems: "flex-start", mb: 2, gap: 2 } },
// Left side - attributes as chips (visible)
React.createElement(
Stack,
{ direction: 'row', spacing: 2, sx: { flexWrap: "wrap", gap: 1, flex: 1 } },
...attributes.map((attr, index) =>
React.createElement(
Chip,
{
key: index,
label: attr.cWert,
disabled: true,
sx: { mb: 1 }
}
)
)
),
// Right side - invisible action buttons (space-filling only)
React.createElement(
Stack,
{ direction: 'column', spacing: 1, sx: { flexShrink: 0 } },
// Invisible "Frage zum Artikel" button
React.createElement(
Box,
{ sx: { height: "32px", width: "120px", visibility: "hidden" } }
),
// Invisible "Artikel Bewerten" button
React.createElement(
Box,
{ sx: { height: "32px", width: "120px", visibility: "hidden" } }
),
// Invisible "Verfügbarkeit anfragen" button (conditional)
(product.available !== 1 && product.availableSupplier !== 1) && React.createElement(
Box,
{ sx: { height: "32px", width: "140px", visibility: "hidden" } }
)
)
),
// 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,
}
},
// Left side - Price information
React.createElement(
Box,
{ sx: { flex: 1 } },
React.createElement(
Typography,
{
variant: "h4",
color: "primary",
sx: { fontWeight: "bold", mb: 1 }
},
priceWithTax
),
// VAT info with fixed height
React.createElement(
Box,
{ sx: { minHeight: "20px", mb: 1 } },
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.`)
)
),
// Shipping class with fixed height
React.createElement(
Box,
{ sx: { minHeight: "20px", mb: 1 } },
product.versandklasse &&
product.versandklasse != "standard" &&
product.versandklasse != "kostenlos" && React.createElement(
Typography,
{ variant: 'body2', color: 'text.secondary' },
product.versandklasse
)
)
),
// Right side - Cart button area with availability info
React.createElement(
Box,
{
sx: {
display: "flex",
flexDirection: "column",
minWidth: { xs: "100%", sm: "200px" }
}
},
// Reserved space for AddToCartButton (will be populated by SPA)
React.createElement(
Box,
{
sx: {
minHeight: "48px",
mb: 1
}
}
),
// Availability and delivery time info (matching ProductDetailPage)
React.createElement(
Typography,
{
variant: 'caption',
sx: {
fontStyle: "italic",
color: "text.secondary",
textAlign: "center",
minHeight: "28px",
display: "flex",
alignItems: "center",
justifyContent: "center"
}
},
product.id && product.id.toString().endsWith("steckling") ?
(this.props.t ? this.props.t('delivery.times.cutting14Days') : "Lieferzeit: 14 Tage") :
product.available == 1 ?
(this.props.t ? this.props.t('delivery.times.standard2to3Days') : "Lieferzeit: 2-3 Tage") :
product.availableSupplier == 1 ?
(this.props.t ? this.props.t('delivery.times.supplier7to9Days') : "Lieferzeit: 7-9 Tage") :
(product.available ? '✅ Verfügbar' : '❌ Nicht verfügbar')
)
)
)
)
)
),
// Product full description - separate card
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)
);
}
}
module.exports = { default: PrerenderProduct };