diff --git a/src/pages/cart/components/youMayLike/YouMayAlsoLike.module.css b/src/pages/cart/components/youMayLike/YouMayAlsoLike.module.css index b420998..7d29536 100644 --- a/src/pages/cart/components/youMayLike/YouMayAlsoLike.module.css +++ b/src/pages/cart/components/youMayLike/YouMayAlsoLike.module.css @@ -1,67 +1,124 @@ .youMightAlsoLikeContainer { - display: flex; - flex-direction: row; - justify-content: space-between; - overflow-y: scroll; + display: flex; + flex-direction: row; + justify-content: flex-start; + overflow-x: hidden; + padding: 0; + scroll-behavior: smooth; } :global(.darkApp) .youMightAlsoLikeContainer path { - fill: var(--primary); + fill: var(--primary); } .popularMenuItemImage { - width: 73px; - height: 73px; - object-fit: cover; - border-radius: 8px; - transition: transform 0.3s ease; + width: 73px; + height: 73px; + object-fit: cover; + border-radius: 8px; + transition: transform 0.3s ease; } .popularMenuItemImage:hover { - transform: scale(1.05); + transform: scale(1.05); } .popularMenuItemImageMobile { - width: 73px; - height: 73px; - min-height: 73px; - object-fit: cover; + width: 73px; + height: 73px; + min-height: 73px; + object-fit: cover; } .popularMenuItemImageTablet { - width: 90px; - height: 90px; - border-radius: 12px; + width: 90px; + height: 90px; + border-radius: 12px; } .popularMenuItemImageDesktop { - width: 110px; - height: 110px; - border-radius: 16px; + width: 110px; + height: 110px; + border-radius: 16px; } -[data-theme="dark"] .popularMenuItemImage { - border-color: rgba(255, 255, 255, 0.1); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); -} -@media (min-width: 768px) { - .popularMenuItemImage:focus { - outline-offset: 4px; - } +[data-theme="dark"] .popularMenuItemImage { + border-color: rgba(255, 255, 255, 0.1); + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +@media (min-width: 768px) { + .popularMenuItemImage:focus { + outline-offset: 4px; + } } /* Hover effects for devices that support hover */ @media (hover: hover) { - .popularMenuItemImage:hover { - transform: scale(1.05); - } + .popularMenuItemImage:hover { + transform: scale(1.05); + } } + /* Focus states for accessibility */ .popularMenuItemImage:focus { - outline: 2px solid var(--primary); - outline-offset: 2px; + outline: 2px solid var(--primary); + outline-offset: 2px; } + .itemDescriptionIcons svg { - width: 18px; - height: 18px; -} \ No newline at end of file + width: 18px; + height: 18px; +} + +.arrowButton { + display: flex; + align-items: center; + justify-content: center; + background: rgba(255, 255, 255, 0.95); + border: 1px solid rgba(0, 0, 0, 0.1); + border-radius: 50%; + width: 30px; + height: 30px; + cursor: pointer; + transition: all 0.2s ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(8px); +} + +.arrowButton:hover { + background: rgba(255, 255, 255, 1); + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.arrowButton:active { + transform: scale(0.95); +} + +.arrowButton:focus { + outline: 2px solid var(--primary); + outline-offset: 2px; +} + +.arrowIcon { + width: 24px; + height: 24px; + transition: transform 0.2s ease; +} + +.arrowButton:hover .arrowIcon { + transform: scale(1.1); +} + +/* Dark theme styles */ +[data-theme="dark"] .arrowButton { + background: rgba(30, 30, 30, 0.95); + border-color: rgba(255, 255, 255, 0.1); + color: white; +} + +[data-theme="dark"] .arrowButton:hover { + background: rgba(40, 40, 40, 1); + border-color: rgba(255, 255, 255, 0.2); +} diff --git a/src/pages/cart/components/youMayLike/YouMightAlsoLike.tsx b/src/pages/cart/components/youMayLike/YouMightAlsoLike.tsx index 488d09f..aeea8ba 100644 --- a/src/pages/cart/components/youMayLike/YouMightAlsoLike.tsx +++ b/src/pages/cart/components/youMayLike/YouMightAlsoLike.tsx @@ -1,11 +1,15 @@ import { PlusOutlined } from "@ant-design/icons"; -import { Grid, Space } from "antd"; +import { Space } from "antd"; import ArabicPrice from "components/ArabicPrice"; +import BackIcon from "components/Icons/BackIcon"; +import NextIcon from "components/Icons/NextIcon"; import ImageWithFallback from "components/ImageWithFallback"; import { ItemDescriptionIcons } from "components/ItemDescriptionIcons/ItemDescriptionIcons.tsx"; import ProText from "components/ProText.tsx"; import { menuItems } from "data/menuItems.ts"; import { addItem } from "features/order/orderSlice.ts"; +import useBreakPoint from "hooks/useBreakPoint"; +import { useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { useAppDispatch, useAppSelector } from "redux/hooks.ts"; import { colors } from "ThemeConstants.ts"; @@ -13,15 +17,88 @@ import { default_image } from "utils/constants.ts"; import { Product } from "utils/types/appTypes.ts"; import styles from "./YouMayAlsoLike.module.css"; -const { useBreakpoint } = Grid; - export default function YouMightAlsoLike() { const { t } = useTranslation(); const dispatch = useAppDispatch(); const { isRTL } = useAppSelector((state) => state.locale); - const { sm, md } = useBreakpoint(); - const isMobile = !sm; - const isTablet = sm && !md; + const { isMobile, isTablet, isDesktop } = useBreakPoint(); + + const [currentIndex, setCurrentIndex] = useState(0); + const containerRef = useRef(null); + + // Check if scrolling is needed based on container width + const [containerWidth, setContainerWidth] = useState(0); + + useEffect(() => { + const updateContainerWidth = () => { + if (containerRef.current) { + setContainerWidth(containerRef.current.offsetWidth); + } + }; + + updateContainerWidth(); + window.addEventListener("resize", updateContainerWidth); + return () => window.removeEventListener("resize", updateContainerWidth); + }, []); + + // Calculate actual visible items based on container width + const itemWidth = isMobile ? 95 + 16 : isTablet ? 120 + 16 : 140 + 16; + const totalItemsWidth = menuItems.length * itemWidth; + const needsScrolling = totalItemsWidth > containerWidth; + + const canNavigateLeft = currentIndex > 0; + const canNavigateRight = + needsScrolling && + currentIndex * itemWidth + containerWidth < totalItemsWidth; + + const scrollToIndex = (index: number) => { + if (containerRef.current) { + const scrollLeft = isRTL ? -(index * itemWidth) : index * itemWidth; + containerRef.current.scrollTo({ + left: scrollLeft, + behavior: "smooth", + }); + } + }; + + const handlePrevious = () => { + if (canNavigateLeft) { + const newIndex = Math.max(0, currentIndex - 1); + setCurrentIndex(newIndex); + scrollToIndex(newIndex); + } + }; + + const handleNext = () => { + if (canNavigateRight) { + const maxPossibleIndex = Math.floor( + (totalItemsWidth - containerWidth) / itemWidth, + ); + const newIndex = Math.min(maxPossibleIndex, currentIndex + 1); + setCurrentIndex(newIndex); + scrollToIndex(newIndex); + } + }; + + // RTL-specific handlers + const handleRTLPrevious = () => { + if (canNavigateRight) { + const maxPossibleIndex = Math.floor( + (totalItemsWidth - containerWidth) / itemWidth, + ); + const newIndex = Math.min(maxPossibleIndex, currentIndex + 1); + setCurrentIndex(newIndex); + scrollToIndex(newIndex); + } + }; + + const handleRTLNext = () => { + if (canNavigateLeft) { + const newIndex = Math.max(0, currentIndex - 1); + setCurrentIndex(newIndex); + scrollToIndex(newIndex); + } + }; const handleQuickAdd = (item: Product) => { dispatch( addItem({ @@ -51,119 +128,174 @@ export default function YouMightAlsoLike() { -
- {menuItems.map((item: Product) => ( -
-
+
+ {/* Left Arrow - Tablet and Desktop only */} + {(isTablet || isDesktop) && ( + + )} + + {/* Right Arrow - Tablet and Desktop only */} + {(isTablet || isDesktop) && ( + + )} + +
+ {menuItems.map((item: Product) => ( +
- { - e.stopPropagation(); - handleQuickAdd(item); - }} +
-
- - - -
- -
- - -
- + { + e.stopPropagation(); + handleQuickAdd(item); + }} style={{ - whiteSpace: "nowrap", + color: colors.primary, + fontSize: isMobile ? 14 : 16, + }} + /> +
+ + + +
+ +
+ + +
+ + {item.name} + +
+ + - {item.name} - -
- - - + /> + +
-
- ))} + ))} +
);