feat: introduce ProductImage component to streamline image handling in PrerenderProduct and ProductDetailPage
This commit is contained in:
@@ -13,6 +13,7 @@ const {
|
|||||||
} = require('@mui/material');
|
} = require('@mui/material');
|
||||||
const Footer = require('./components/Footer.js').default;
|
const Footer = require('./components/Footer.js').default;
|
||||||
const { Logo } = require('./components/header/index.js');
|
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
|
// Utility function to clean product names by removing trailing number in parentheses
|
||||||
const cleanProductName = (name) => {
|
const cleanProductName = (name) => {
|
||||||
@@ -170,50 +171,11 @@ class PrerenderProduct extends React.Component {
|
|||||||
},
|
},
|
||||||
// Product Image Section
|
// Product Image Section
|
||||||
React.createElement(
|
React.createElement(
|
||||||
Box,
|
ProductImage,
|
||||||
{
|
{
|
||||||
sx: {
|
product: product,
|
||||||
width: { xs: "100%", sm: "555px" },
|
isPrerender: true
|
||||||
maxWidth: "100%",
|
}
|
||||||
minHeight: "400px",
|
|
||||||
background: "#f8f8f8",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
!product.pictureList && React.createElement(
|
|
||||||
CardMedia,
|
|
||||||
{
|
|
||||||
component: 'img',
|
|
||||||
height: '400',
|
|
||||||
image: '/assets/images/nopicture.jpg',
|
|
||||||
alt: product.name,
|
|
||||||
sx: { objectFit: 'cover' }
|
|
||||||
}
|
|
||||||
),
|
|
||||||
product.pictureList && React.createElement(
|
|
||||||
Box,
|
|
||||||
{ sx: { position: 'relative', display: 'inline-block' } },
|
|
||||||
React.createElement(
|
|
||||||
CardMedia,
|
|
||||||
{
|
|
||||||
component: 'img',
|
|
||||||
height: '400',
|
|
||||||
image: mainImage,
|
|
||||||
alt: product.name,
|
|
||||||
sx: {
|
|
||||||
objectFit: 'contain',
|
|
||||||
cursor: 'pointer',
|
|
||||||
transition: 'transform 0.2s ease-in-out',
|
|
||||||
'&:hover': {
|
|
||||||
transform: 'scale(1.02)'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
// Product Details Section
|
// Product Details Section
|
||||||
React.createElement(
|
React.createElement(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Link } from "react-router-dom";
|
|||||||
import parse from "html-react-parser";
|
import parse from "html-react-parser";
|
||||||
import AddToCartButton from "./AddToCartButton.js";
|
import AddToCartButton from "./AddToCartButton.js";
|
||||||
import Images from "./Images.js";
|
import Images from "./Images.js";
|
||||||
|
import ProductImage from "./ProductImage.js";
|
||||||
import { withI18n } from "../i18n/withTranslation.js";
|
import { withI18n } from "../i18n/withTranslation.js";
|
||||||
import ArticleQuestionForm from "./ArticleQuestionForm.js";
|
import ArticleQuestionForm from "./ArticleQuestionForm.js";
|
||||||
import ArticleRatingForm from "./ArticleRatingForm.js";
|
import ArticleRatingForm from "./ArticleRatingForm.js";
|
||||||
@@ -669,38 +670,15 @@ class ProductDetailPage extends Component {
|
|||||||
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
|
boxShadow: "0 2px 8px rgba(0,0,0,0.08)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<ProductImage
|
||||||
sx={{
|
product={product}
|
||||||
width: { xs: "100%", sm: "555px" },
|
socket={this.props.socket}
|
||||||
maxWidth: "100%",
|
socketB={this.props.socketB}
|
||||||
minHeight: "400px",
|
fullscreenOpen={this.state.imageDialogOpen}
|
||||||
background: "#f8f8f8",
|
onOpenFullscreen={this.handleOpenDialog}
|
||||||
display: "flex",
|
onCloseFullscreen={this.handleCloseDialog}
|
||||||
flexDirection: "column",
|
isPrerender={false}
|
||||||
alignItems: "center",
|
/>
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!product.pictureList && (
|
|
||||||
<CardMedia
|
|
||||||
component="img"
|
|
||||||
height="400"
|
|
||||||
image="/assets/images/nopicture.jpg"
|
|
||||||
alt={product.name}
|
|
||||||
sx={{ objectFit: "cover" }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{product.pictureList && (
|
|
||||||
<Images
|
|
||||||
socket={this.props.socket}
|
|
||||||
socketB={this.props.socketB}
|
|
||||||
pictureList={product.pictureList}
|
|
||||||
fullscreenOpen={this.state.imageDialogOpen}
|
|
||||||
onOpenFullscreen={this.handleOpenDialog}
|
|
||||||
onCloseFullscreen={this.handleCloseDialog}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Product Details */}
|
{/* Product Details */}
|
||||||
<Box
|
<Box
|
||||||
|
|||||||
96
src/components/ProductImage.js
Normal file
96
src/components/ProductImage.js
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import CardMedia from '@mui/material/CardMedia';
|
||||||
|
import Images from './Images.js';
|
||||||
|
|
||||||
|
const ProductImage = ({
|
||||||
|
product,
|
||||||
|
socket,
|
||||||
|
socketB,
|
||||||
|
fullscreenOpen,
|
||||||
|
onOpenFullscreen,
|
||||||
|
onCloseFullscreen,
|
||||||
|
isPrerender = false
|
||||||
|
}) => {
|
||||||
|
// For prerender, use static image path
|
||||||
|
const getImagePath = (pictureList) => {
|
||||||
|
if (!pictureList || !pictureList.trim()) {
|
||||||
|
return '/assets/images/nopicture.jpg';
|
||||||
|
}
|
||||||
|
return `/assets/images/prod${pictureList.split(',')[0].trim()}.jpg`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Container styling - same for both versions
|
||||||
|
const containerSx = {
|
||||||
|
width: { xs: "100%", sm: "555px" },
|
||||||
|
maxWidth: "100%",
|
||||||
|
minHeight: "400px",
|
||||||
|
background: "#f8f8f8",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isPrerender) {
|
||||||
|
// Prerender version - use CardMedia with static paths
|
||||||
|
return (
|
||||||
|
<Box sx={containerSx}>
|
||||||
|
{!product.pictureList && (
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="400"
|
||||||
|
image="/assets/images/nopicture.jpg"
|
||||||
|
alt={product.name}
|
||||||
|
sx={{ objectFit: "cover" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{product.pictureList && (
|
||||||
|
<Box sx={{ position: 'relative', display: 'inline-block' }}>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="400"
|
||||||
|
image={getImagePath(product.pictureList)}
|
||||||
|
alt={product.name}
|
||||||
|
sx={{
|
||||||
|
objectFit: 'contain',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'transform 0.2s ease-in-out',
|
||||||
|
'&:hover': {
|
||||||
|
transform: 'scale(1.02)'
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPA version - use existing Images component
|
||||||
|
return (
|
||||||
|
<Box sx={containerSx}>
|
||||||
|
{!product.pictureList && (
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="400"
|
||||||
|
image="/assets/images/nopicture.jpg"
|
||||||
|
alt={product.name}
|
||||||
|
sx={{ objectFit: "cover" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{product.pictureList && (
|
||||||
|
<Images
|
||||||
|
socket={socket}
|
||||||
|
socketB={socketB}
|
||||||
|
pictureList={product.pictureList}
|
||||||
|
fullscreenOpen={fullscreenOpen}
|
||||||
|
onOpenFullscreen={onOpenFullscreen}
|
||||||
|
onCloseFullscreen={onCloseFullscreen}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ProductImage;
|
||||||
Reference in New Issue
Block a user