feat: Wrap product carousel title in a React Router Link and add a ChevronRight icon.
This commit is contained in:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user