Refactor PrerenderProduct layout: Introduced a back button for navigation, improved styling with Box components, and ensured consistent heights for product details and price sections. Enhanced product display with fixed height placeholders and updated availability messaging for better user experience.
This commit is contained in:
@@ -90,6 +90,70 @@ class PrerenderProduct extends React.Component {
|
||||
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,
|
||||
{
|
||||
@@ -110,6 +174,7 @@ class PrerenderProduct extends React.Component {
|
||||
width: { xs: "100%", sm: "555px" },
|
||||
maxWidth: "100%",
|
||||
minHeight: "400px",
|
||||
height: "400px", // Fixed height to prevent shifts
|
||||
background: "#f8f8f8",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
@@ -124,7 +189,12 @@ class PrerenderProduct extends React.Component {
|
||||
height: '400',
|
||||
image: mainImage,
|
||||
alt: product.name,
|
||||
sx: { objectFit: 'contain', p: 2 }
|
||||
sx: {
|
||||
objectFit: 'contain',
|
||||
p: 2,
|
||||
width: '100%',
|
||||
maxWidth: '100%'
|
||||
}
|
||||
}
|
||||
)
|
||||
),
|
||||
@@ -137,44 +207,56 @@ class PrerenderProduct extends React.Component {
|
||||
p: { xs: 2, md: 4 },
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
minHeight: "400px", // Ensure consistent minimum height
|
||||
}
|
||||
},
|
||||
// Product identifiers
|
||||
// Product identifiers - fixed height to prevent shifts
|
||||
React.createElement(
|
||||
Box,
|
||||
{ sx: { mb: 1 } },
|
||||
{ sx: { mb: 1, minHeight: "24px" } },
|
||||
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
|
||||
// Product title - reserve space for 2 lines
|
||||
React.createElement(
|
||||
Box,
|
||||
{ sx: { mb: 2, minHeight: "72px" } },
|
||||
React.createElement(
|
||||
Typography,
|
||||
{
|
||||
variant: 'h4',
|
||||
component: 'h1',
|
||||
gutterBottom: true,
|
||||
sx: { fontWeight: 600, color: "#333" }
|
||||
sx: {
|
||||
fontWeight: 600,
|
||||
color: "#333",
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 2,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
overflow: 'hidden',
|
||||
lineHeight: 1.2
|
||||
}
|
||||
},
|
||||
cleanProductName(product.name)
|
||||
)
|
||||
),
|
||||
// Manufacturer if available
|
||||
product.manufacturer && React.createElement(
|
||||
Box,
|
||||
{ sx: { display: "flex", alignItems: "center", mb: 2 } },
|
||||
// Manufacturer if available - fixed height placeholder
|
||||
React.createElement(
|
||||
Box,
|
||||
{ sx: { display: "flex", alignItems: "center", mb: 2, minHeight: "28px" } },
|
||||
product.manufacturer && React.createElement(
|
||||
Typography,
|
||||
{ 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 } },
|
||||
// Product specifications (attributes) - fixed height container
|
||||
React.createElement(
|
||||
Box,
|
||||
{ sx: { mb: 2, minHeight: attributes.length > 0 ? "auto" : "0px" } },
|
||||
attributes.length > 0 && React.createElement(
|
||||
Stack,
|
||||
{ direction: 'row', spacing: 1, flexWrap: 'wrap', gap: 1 },
|
||||
...attributes.map((attr, index) =>
|
||||
@@ -184,23 +266,24 @@ class PrerenderProduct extends React.Component {
|
||||
key: index,
|
||||
label: `${attr.cName}: ${attr.cWert}`,
|
||||
disabled: true,
|
||||
size: "small",
|
||||
sx: { mb: 1 }
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
// Weight
|
||||
product.weight && product.weight > 0 && React.createElement(
|
||||
Box,
|
||||
{ sx: { mb: 2 } },
|
||||
// Weight - fixed height placeholder
|
||||
React.createElement(
|
||||
Box,
|
||||
{ sx: { mb: 2, minHeight: "28px" } },
|
||||
product.weight && product.weight > 0 && 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
|
||||
// Price and availability section - positioned at bottom
|
||||
React.createElement(
|
||||
Box,
|
||||
{
|
||||
@@ -209,6 +292,7 @@ class PrerenderProduct extends React.Component {
|
||||
p: 3,
|
||||
background: "#f9f9f9",
|
||||
borderRadius: 2,
|
||||
minHeight: "120px", // Fixed minimum height for price section
|
||||
}
|
||||
},
|
||||
React.createElement(
|
||||
@@ -222,46 +306,106 @@ class PrerenderProduct extends React.Component {
|
||||
gap: 2,
|
||||
}
|
||||
},
|
||||
// Left side - Price information
|
||||
React.createElement(
|
||||
Box,
|
||||
null,
|
||||
{ sx: { flex: 1 } },
|
||||
React.createElement(
|
||||
Typography,
|
||||
{
|
||||
variant: "h4",
|
||||
color: "primary",
|
||||
sx: { fontWeight: "bold" }
|
||||
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" }
|
||||
}
|
||||
},
|
||||
// Placeholder for AddToCartButton area
|
||||
React.createElement(
|
||||
Box,
|
||||
{
|
||||
sx: {
|
||||
minHeight: "48px",
|
||||
mb: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "#f0f0f0",
|
||||
borderRadius: 2,
|
||||
border: "1px dashed #ccc"
|
||||
}
|
||||
},
|
||||
React.createElement(
|
||||
Typography,
|
||||
{
|
||||
variant: 'body1',
|
||||
color: product.available ? 'success.main' : 'error.main',
|
||||
fontWeight: 'medium',
|
||||
sx: { mt: 1 }
|
||||
variant: 'body2',
|
||||
color: 'text.secondary',
|
||||
sx: { fontStyle: 'italic' }
|
||||
},
|
||||
product.available ? '✅ Verfügbar' : '❌ Nicht verfügbar'
|
||||
'Add to Cart Button'
|
||||
)
|
||||
),
|
||||
// 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
|
||||
// Product full description - separate card
|
||||
product.description && React.createElement(
|
||||
Box,
|
||||
{
|
||||
@@ -271,6 +415,7 @@ class PrerenderProduct extends React.Component {
|
||||
background: "#fff",
|
||||
borderRadius: 2,
|
||||
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
|
||||
minHeight: "100px" // Minimum height to prevent shifts
|
||||
}
|
||||
},
|
||||
React.createElement(
|
||||
|
||||
Reference in New Issue
Block a user