import React, { Component } from 'react'; import Box from '@mui/material/Box'; import CardMedia from '@mui/material/CardMedia'; import Stack from '@mui/material/Stack'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import IconButton from '@mui/material/IconButton'; import Badge from '@mui/material/Badge'; import CloseIcon from '@mui/icons-material/Close'; import LoupeIcon from '@mui/icons-material/Loupe'; class Images extends Component { constructor(props) { super(props); this.state = { mainPic:0,pics:[] }; } componentDidMount () { this.updatePics(0); } componentDidUpdate(prevProps) { if (prevProps.fullscreenOpen !== this.props.fullscreenOpen) { this.updatePics(); } } componentWillUnmount() { window.productImageUrl = null; } updatePics = (newMainPic = this.state.mainPic) => { if (!window.tinyPicCache) window.tinyPicCache = {}; if (!window.smallPicCache) window.smallPicCache = {}; if (!window.mediumPicCache) window.mediumPicCache = {}; if (!window.largePicCache) window.largePicCache = {}; if(this.props.pictureList && this.props.pictureList.length > 0){ const bildIds = this.props.pictureList.split(','); const pics = []; const mainPicId = bildIds[newMainPic]; for(const bildId of bildIds){ if(bildId == mainPicId){ if(window.productImageUrl) continue; if(window.largePicCache[bildId]){ pics.push(window.largePicCache[bildId]); }else if(window.mediumPicCache[bildId]){ pics.push(window.mediumPicCache[bildId]); if(this.props.fullscreenOpen) this.loadPic('large',bildId,newMainPic); }else if(window.smallPicCache[bildId]){ pics.push(window.smallPicCache[bildId]); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); }else if(window.tinyPicCache[bildId]){ pics.push(window.tinyPicCache[bildId]); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); }else{ pics.push(`/assets/images/prod${bildId}.jpg`); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); } }else{ if(window.tinyPicCache[bildId]){ pics.push(window.tinyPicCache[bildId]); }else if(window.mediumPicCache[bildId]){ pics.push(window.mediumPicCache[bildId]); this.loadPic('tiny',bildId,newMainPic); }else{ pics.push(null); this.loadPic('tiny',bildId,pics.length-1); } } } console.log('DEBUG: pics array contents:', pics); console.log('DEBUG: pics array types:', pics.map(p => typeof p + ': ' + p)); this.setState({ pics, mainPic: newMainPic }); }else{ if(this.state.pics.length > 0) this.setState({ pics:[], mainPic: newMainPic }); } } loadPic = (size,bildId,index) => { window.socketManager.emit('getPic', { bildId, size }, (res) => { if(res.success){ const url = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' })); if(size === 'medium') window.mediumPicCache[bildId] = url; if(size === 'small') window.smallPicCache[bildId] = url; if(size === 'tiny') window.tinyPicCache[bildId] = url; if(size === 'large') window.largePicCache[bildId] = url; const pics = this.state.pics; pics[index] = url this.setState({ pics }); } }) } handleThumbnailClick = (clickedPic) => { // Find the original index of the clicked picture in the full pics array const originalIndex = this.state.pics.findIndex(pic => pic === clickedPic); if (originalIndex !== -1) { this.updatePics(originalIndex); } } render() { // SPA version - full functionality with static fallback const getImageSrc = () => { if(window.productImageUrl) return window.productImageUrl; // If dynamic image is loaded, use it if (this.state.pics[this.state.mainPic]) { return this.state.pics[this.state.mainPic]; } // Otherwise, use static fallback (same as prerender) if (!this.props.pictureList || !this.props.pictureList.trim()) { return '/assets/images/nopicture.jpg'; } return `/assets/images/prod${this.props.pictureList.split(',')[0].trim()}.jpg`; }; return ( <> { // Ensure alt text is always present even on error if (!e.target.alt) { e.target.alt = this.props.productName || 'Produktbild'; } }} sx={{ objectFit: 'contain', cursor: 'pointer', transition: 'transform 0.2s ease-in-out', width: '499px', maxWidth: '100%', '&:hover': { transform: 'scale(1.02)' } }} image={getImageSrc()} onClick={this.props.onOpenFullscreen} /> {this.state.pics.filter(pic => pic !== null && pic !== this.state.pics[this.state.mainPic]).map((pic, filterIndex) => { // Find the original index in the full pics array const originalIndex = this.state.pics.findIndex(p => p === pic); return ( { // Ensure alt text is always present even on error if (!e.target.alt) { e.target.alt = `${this.props.productName || 'Produktbild'} - Bild ${originalIndex + 1}`; } }} sx={{ objectFit: 'contain', cursor: 'pointer', borderRadius: 1, border: '2px solid transparent', transition: 'all 0.2s ease-in-out', '&:hover': { border: '2px solid #1976d2', transform: 'scale(1.05)', boxShadow: '0 4px 8px rgba(0,0,0,0.2)' } }} image={pic} onClick={() => this.handleThumbnailClick(pic)} /> ); })} {/* Fullscreen Dialog */} { // Only close if clicking on the background (DialogContent itself) if (e.target === e.currentTarget) { this.props.onCloseFullscreen(); } }} > {/* Close Button */} {/* Main Image in Fullscreen */} {this.state.pics[this.state.mainPic] && ( { // Ensure alt text is always present even on error if (!e.target.alt) { e.target.alt = this.props.productName || 'Produktbild'; } }} sx={{ objectFit: 'contain', width: '90vw', height: '80vh' }} image={this.state.pics[this.state.mainPic]} onClick={this.props.onCloseFullscreen} /> )} {/* Thumbnail Stack in Fullscreen */} e.stopPropagation()} > {this.state.pics.filter(pic => pic !== null && pic !== this.state.pics[this.state.mainPic]).map((pic, filterIndex) => { // Find the original index in the full pics array const originalIndex = this.state.pics.findIndex(p => p === pic); return ( { // Ensure alt text is always present even on error if (!e.target.alt) { e.target.alt = `${this.props.productName || 'Produktbild'} - Miniaturansicht ${originalIndex + 1}`; } }} sx={{ objectFit: 'contain', cursor: 'pointer', borderRadius: 1, border: '2px solid rgba(255, 255, 255, 0.3)', transition: 'all 0.2s ease-in-out', '&:hover': { border: '2px solid #1976d2', transform: 'scale(1.1)', boxShadow: '0 4px 8px rgba(25, 118, 210, 0.5)' } }} image={pic} onClick={() => this.handleThumbnailClick(pic)} /> ); })} ); } } export default Images;