import { StarOutlined } from "@ant-design/icons"; import { Badge, Button, Card } from "antd"; import ArabicPrice from "components/ArabicPrice"; import ImageWithFallback from "components/ImageWithFallback"; import { ItemDescriptionIcons } from "components/ItemDescriptionIcons/ItemDescriptionIcons"; import ProText from "components/ProText"; import ProTitle from "components/ProTitle"; import useBreakPoint from "hooks/useBreakPoint"; import { AddToCartButton } from "pages/menu/components/AddToCartButton/AddToCartButton.tsx"; import { ProductPreviewDialog } from "pages/menu/components/ProductPreviewDialog"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useNavigate, useParams } from "react-router-dom"; import { useAppSelector } from "redux/hooks"; import { colors } from "ThemeConstants"; import { Product } from "utils/types/appTypes"; import styles from "./MenuList.module.css"; interface MenuListProps { data: | { products: Product[]; categories: { id: number; name: string; image?: string }[]; } | undefined; categoryRefs: React.RefObject<{ [key: number]: HTMLDivElement | null }>; } export function MenuList({ data, categoryRefs }: MenuListProps) { const { isRTL } = useAppSelector((state) => state.locale); const products = data?.products; const { isMobile, isTablet, isDesktop } = useBreakPoint(); const { items } = useAppSelector((state) => state.order); const { subdomain } = useParams(); const navigate = useNavigate(); const { t } = useTranslation(); const { themeName } = useAppSelector((state) => state.theme); // Dialog state const [isDialogOpen, setIsDialogOpen] = useState(false); // Handle product click - open dialog on desktop, navigate on mobile/tablet const handleProductClick = (item: Product) => { localStorage.setItem("product", JSON.stringify(item)); if (isDesktop) { setIsDialogOpen(true); } else { navigate(`/${subdomain}/product/${item.id}`); } }; // Handle dialog close const handleDialogClose = () => { setIsDialogOpen(false); }; // Show error state if data exists but has no products if (data && (!data.products || data.products.length === 0)) { return (
{t("menu.noMenuItemsAvailable")}
); } // Group products by category const productsByCategory = products?.reduce( (acc, product) => { if (product.categoryId && !acc[product?.categoryId]) { acc[product?.categoryId] = []; } acc[product?.categoryId || 0].push(product); return acc; }, {} as Record, ); return ( <>
{data?.categories?.map((category) => { const categoryProducts = productsByCategory?.[category.id] || []; if (categoryProducts.length === 0) return null; return (
{ if (categoryRefs.current) { categoryRefs.current[category.id] = el; } }} style={{ marginBottom: "1rem" }} > {isRTL ? category.name : category.name}
{categoryProducts.map((item: Product) => (
handleProductClick(item)} >
{isRTL ? item.name : item.nameOther} {item.description && ( {item.description} )}
{item.original_price !== item.price && ( )}
{item.isHasLoyalty && (
))}
); })}
{/* Product Preview Dialog for Desktop */} ); }