From dbd5df28f8a2484623f5892c00aa640d2e384c81 Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Sun, 14 Dec 2025 10:01:37 +0100 Subject: [PATCH] feat: Wrap product carousel title in a React Router Link and add a `ChevronRight` icon. --- src/components/ProductCarousel.js | 71 +++++++++++++++++++------------ 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/src/components/ProductCarousel.js b/src/components/ProductCarousel.js index b6eb753..cea9d13 100644 --- a/src/components/ProductCarousel.js +++ b/src/components/ProductCarousel.js @@ -1,4 +1,5 @@ import React from 'react'; +import { Link } from "react-router-dom"; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import IconButton from "@mui/material/IconButton"; @@ -26,7 +27,7 @@ class ProductCarousel extends React.Component { constructor(props) { super(props); const { i18n } = props; - + this.state = { products: [], currentLanguage: (i18n && i18n.language) || 'de', @@ -39,14 +40,14 @@ class ProductCarousel extends React.Component { componentDidMount() { this._isMounted = true; const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language; - + console.log("ProductCarousel componentDidMount: Loading products for categoryId", this.props.categoryId, "language", currentLanguage); this.loadProducts(currentLanguage); } componentDidUpdate(prevProps) { console.log("ProductCarousel componentDidUpdate", prevProps.languageContext?.currentLanguage, this.props.languageContext?.currentLanguage); - if(prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) { + if (prevProps.languageContext?.currentLanguage !== this.props.languageContext?.currentLanguage) { this.setState({ products: [] }, () => { this.loadProducts(this.props.languageContext?.currentLanguage || this.props.i18n.language); }); @@ -55,13 +56,13 @@ class ProductCarousel extends React.Component { loadProducts = (language) => { const { categoryId } = this.props; - + window.socketManager.emit( "getCategoryProducts", - { - categoryId: categoryId === "neu" ? "neu" : categoryId, - language: language, - requestTranslation: language === 'de' ? false : true + { + categoryId: categoryId === "neu" ? "neu" : categoryId, + language: language, + requestTranslation: language === 'de' ? false : true }, (response) => { console.log("ProductCarousel getCategoryProducts response:", response); @@ -136,7 +137,7 @@ class ProductCarousel extends React.Component { showScrollbarFlash = () => { this.clearScrollbarTimer(); this.setState({ showScrollbar: true }); - + this.scrollbarTimer = setTimeout(() => { if (this._isMounted) { this.setState({ showScrollbar: false }); @@ -146,7 +147,7 @@ class ProductCarousel extends React.Component { handleAutoScroll = () => { if (!this.autoScrollActive || this.originalProducts.length === 0) return; - + this.translateX -= AUTO_SCROLL_SPEED; this.updateTrackTransform(); @@ -185,7 +186,7 @@ class ProductCarousel extends React.Component { scrollBy = (direction) => { if (this.originalProducts.length === 0) return; - + // direction: 1 = left (scroll content right), -1 = right (scroll content left) const originalItemCount = this.originalProducts.length; const maxScroll = ITEM_WIDTH * originalItemCount; @@ -202,7 +203,7 @@ class ProductCarousel extends React.Component { } this.updateTrackTransform(); - + // Force scrollbar to update immediately after wrap-around if (this.state.showScrollbar) { this.forceUpdate(); @@ -217,10 +218,10 @@ class ProductCarousel extends React.Component { const originalItemCount = this.originalProducts.length; const viewportWidth = 1080; // carousel container max-width const itemsInView = Math.floor(viewportWidth / ITEM_WIDTH); - + // Calculate which item is currently at the left edge (first visible) let currentItemIndex; - + if (this.translateX === 0) { currentItemIndex = 0; } else if (this.translateX > 0) { @@ -230,10 +231,10 @@ class ProductCarousel extends React.Component { } else { currentItemIndex = Math.floor(Math.abs(this.translateX) / ITEM_WIDTH); } - + // Ensure we stay within bounds currentItemIndex = Math.max(0, Math.min(currentItemIndex, originalItemCount - 1)); - + // Calculate scrollbar position const lastPossibleFirstItem = Math.max(0, originalItemCount - itemsInView); const thumbPosition = lastPossibleFirstItem > 0 ? Math.min((currentItemIndex / lastPossibleFirstItem) * 100, 100) : 0; @@ -277,25 +278,41 @@ class ProductCarousel extends React.Component { const { t, title } = this.props; const { products } = this.state; - if(!products || products.length === 0) { + if (!products || products.length === 0) { return null; } return ( - - {title || t('product.new')} - + + {title || t('product.new')} + + +
))}
- + {/* Virtual Scrollbar */} {this.renderVirtualScrollbar()}