feat: Wrap product carousel title in a React Router Link and add a ChevronRight icon.

This commit is contained in:
sebseb7
2025-12-14 10:01:37 +01:00
parent 57515bfb85
commit dbd5df28f8

View File

@@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { Link } from "react-router-dom";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton"; import IconButton from "@mui/material/IconButton";
@@ -26,7 +27,7 @@ class ProductCarousel extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const { i18n } = props; const { i18n } = props;
this.state = { this.state = {
products: [], products: [],
currentLanguage: (i18n && i18n.language) || 'de', currentLanguage: (i18n && i18n.language) || 'de',
@@ -39,14 +40,14 @@ class ProductCarousel extends React.Component {
componentDidMount() { componentDidMount() {
this._isMounted = true; this._isMounted = true;
const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language; const currentLanguage = this.props.languageContext?.currentLanguage || this.props.i18n.language;
console.log("ProductCarousel componentDidMount: Loading products for categoryId", this.props.categoryId, "language", currentLanguage); console.log("ProductCarousel componentDidMount: Loading products for categoryId", this.props.categoryId, "language", currentLanguage);
this.loadProducts(currentLanguage); this.loadProducts(currentLanguage);
} }
componentDidUpdate(prevProps) { componentDidUpdate(prevProps) {
console.log("ProductCarousel componentDidUpdate", prevProps.languageContext?.currentLanguage, this.props.languageContext?.currentLanguage); 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.setState({ products: [] }, () => {
this.loadProducts(this.props.languageContext?.currentLanguage || this.props.i18n.language); this.loadProducts(this.props.languageContext?.currentLanguage || this.props.i18n.language);
}); });
@@ -55,13 +56,13 @@ class ProductCarousel extends React.Component {
loadProducts = (language) => { loadProducts = (language) => {
const { categoryId } = this.props; const { categoryId } = this.props;
window.socketManager.emit( window.socketManager.emit(
"getCategoryProducts", "getCategoryProducts",
{ {
categoryId: categoryId === "neu" ? "neu" : categoryId, categoryId: categoryId === "neu" ? "neu" : categoryId,
language: language, language: language,
requestTranslation: language === 'de' ? false : true requestTranslation: language === 'de' ? false : true
}, },
(response) => { (response) => {
console.log("ProductCarousel getCategoryProducts response:", response); console.log("ProductCarousel getCategoryProducts response:", response);
@@ -136,7 +137,7 @@ class ProductCarousel extends React.Component {
showScrollbarFlash = () => { showScrollbarFlash = () => {
this.clearScrollbarTimer(); this.clearScrollbarTimer();
this.setState({ showScrollbar: true }); this.setState({ showScrollbar: true });
this.scrollbarTimer = setTimeout(() => { this.scrollbarTimer = setTimeout(() => {
if (this._isMounted) { if (this._isMounted) {
this.setState({ showScrollbar: false }); this.setState({ showScrollbar: false });
@@ -146,7 +147,7 @@ class ProductCarousel extends React.Component {
handleAutoScroll = () => { handleAutoScroll = () => {
if (!this.autoScrollActive || this.originalProducts.length === 0) return; if (!this.autoScrollActive || this.originalProducts.length === 0) return;
this.translateX -= AUTO_SCROLL_SPEED; this.translateX -= AUTO_SCROLL_SPEED;
this.updateTrackTransform(); this.updateTrackTransform();
@@ -185,7 +186,7 @@ class ProductCarousel extends React.Component {
scrollBy = (direction) => { scrollBy = (direction) => {
if (this.originalProducts.length === 0) return; if (this.originalProducts.length === 0) return;
// direction: 1 = left (scroll content right), -1 = right (scroll content left) // direction: 1 = left (scroll content right), -1 = right (scroll content left)
const originalItemCount = this.originalProducts.length; const originalItemCount = this.originalProducts.length;
const maxScroll = ITEM_WIDTH * originalItemCount; const maxScroll = ITEM_WIDTH * originalItemCount;
@@ -202,7 +203,7 @@ class ProductCarousel extends React.Component {
} }
this.updateTrackTransform(); this.updateTrackTransform();
// Force scrollbar to update immediately after wrap-around // Force scrollbar to update immediately after wrap-around
if (this.state.showScrollbar) { if (this.state.showScrollbar) {
this.forceUpdate(); this.forceUpdate();
@@ -217,10 +218,10 @@ class ProductCarousel extends React.Component {
const originalItemCount = this.originalProducts.length; const originalItemCount = this.originalProducts.length;
const viewportWidth = 1080; // carousel container max-width const viewportWidth = 1080; // carousel container max-width
const itemsInView = Math.floor(viewportWidth / ITEM_WIDTH); const itemsInView = Math.floor(viewportWidth / ITEM_WIDTH);
// Calculate which item is currently at the left edge (first visible) // Calculate which item is currently at the left edge (first visible)
let currentItemIndex; let currentItemIndex;
if (this.translateX === 0) { if (this.translateX === 0) {
currentItemIndex = 0; currentItemIndex = 0;
} else if (this.translateX > 0) { } else if (this.translateX > 0) {
@@ -230,10 +231,10 @@ class ProductCarousel extends React.Component {
} else { } else {
currentItemIndex = Math.floor(Math.abs(this.translateX) / ITEM_WIDTH); currentItemIndex = Math.floor(Math.abs(this.translateX) / ITEM_WIDTH);
} }
// Ensure we stay within bounds // Ensure we stay within bounds
currentItemIndex = Math.max(0, Math.min(currentItemIndex, originalItemCount - 1)); currentItemIndex = Math.max(0, Math.min(currentItemIndex, originalItemCount - 1));
// Calculate scrollbar position // Calculate scrollbar position
const lastPossibleFirstItem = Math.max(0, originalItemCount - itemsInView); const lastPossibleFirstItem = Math.max(0, originalItemCount - itemsInView);
const thumbPosition = lastPossibleFirstItem > 0 ? Math.min((currentItemIndex / lastPossibleFirstItem) * 100, 100) : 0; 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 { t, title } = this.props;
const { products } = this.state; const { products } = this.state;
if(!products || products.length === 0) { if (!products || products.length === 0) {
return null; return null;
} }
return ( return (
<Box sx={{ mt: 3 }}> <Box sx={{ mt: 3 }}>
<Typography <Box
variant="h4" component={Link}
component="h2" to="/Kategorie/neu"
sx={{ sx={{
mb: 2, display: "flex",
fontFamily: "SwashingtonCP", alignItems: "center",
justifyContent: "center",
textDecoration: "none",
color: "primary.main", color: "primary.main",
textAlign: "center", mb: 2,
textShadow: "3px 3px 10px rgba(0, 0, 0, 0.4)" transition: "all 0.3s ease",
"&:hover": {
transform: "translateX(5px)",
color: "primary.dark"
}
}} }}
> >
{title || t('product.new')} <Typography
</Typography> variant="h4"
component="span"
sx={{
fontFamily: "SwashingtonCP",
textShadow: "3px 3px 10px rgba(0, 0, 0, 0.4)"
}}
>
{title || t('product.new')}
</Typography>
<ChevronRight sx={{ fontSize: "2.5rem", ml: 1 }} />
</Box>
<div <div
className="product-carousel-wrapper" className="product-carousel-wrapper"
@@ -420,7 +437,7 @@ class ProductCarousel extends React.Component {
</div> </div>
))} ))}
</div> </div>
{/* Virtual Scrollbar */} {/* Virtual Scrollbar */}
{this.renderVirtualScrollbar()} {this.renderVirtualScrollbar()}
</div> </div>