menu: UI enhancements in desktop sizes
- add product dialog - enhance product page layout for desktop size
This commit is contained in:
@@ -1,10 +1,13 @@
|
||||
import { Badge, Card, Grid } from "antd";
|
||||
import { Badge, 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 } from "react-router-dom";
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
@@ -23,18 +26,34 @@ interface MenuListProps {
|
||||
categoryRefs: React.RefObject<{ [key: number]: HTMLDivElement | null }>;
|
||||
}
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
const { isRTL } = useAppSelector((state) => state.locale);
|
||||
const products = data?.products;
|
||||
const { xs, md } = useBreakpoint();
|
||||
const { isMobile, isTablet, isDesktop } = useBreakPoint();
|
||||
const { items } = useAppSelector((state) => state.order);
|
||||
const restaurantName = localStorage.getItem("restaurantName");
|
||||
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(`/${restaurantName}/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 (
|
||||
@@ -104,10 +123,7 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
<div
|
||||
key={item.id}
|
||||
className={styles.productLink}
|
||||
onClick={() => {
|
||||
localStorage.setItem("product", JSON.stringify(item));
|
||||
navigate(`/${restaurantName}/product/${item.id}`);
|
||||
}}
|
||||
onClick={() => handleProductClick(item)}
|
||||
>
|
||||
<Card
|
||||
key={item.id}
|
||||
@@ -126,8 +142,8 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
? "16px 16px 8px 16px"
|
||||
: "16px 16px 24px 16px",
|
||||
overflow: "hide",
|
||||
boxShadow: "none",
|
||||
},
|
||||
boxShadow: "none",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@@ -136,7 +152,7 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
height: "100%",
|
||||
gap: xs ? 10 : 16,
|
||||
gap: isMobile ? 10 : 16,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@@ -225,9 +241,9 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
fallbackSrc="/default.png"
|
||||
alt={item.name}
|
||||
className={`${styles.popularMenuItemImage} ${
|
||||
xs
|
||||
isMobile
|
||||
? styles.popularMenuItemImageMobile
|
||||
: md
|
||||
: isTablet
|
||||
? styles.popularMenuItemImageTablet
|
||||
: styles.popularMenuItemImageDesktop
|
||||
}`}
|
||||
@@ -267,6 +283,9 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* Product Preview Dialog for Desktop */}
|
||||
<ProductPreviewDialog isOpen={isDialogOpen} onClose={handleDialogClose} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.productModal{
|
||||
width: 80vw;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Modal } from "antd";
|
||||
import ProductDetailPage from "pages/product/page";
|
||||
import styles from "./ProductPreviewDialog.module.css";
|
||||
|
||||
interface ProductPreviewDialogProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export function ProductPreviewDialog({
|
||||
isOpen,
|
||||
onClose,
|
||||
}: ProductPreviewDialogProps) {
|
||||
// const { isRTL } = useAppSelector((state) => state.locale);
|
||||
// const { themeName } = useAppSelector((state) => state.theme);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={isOpen}
|
||||
onCancel={onClose}
|
||||
footer={null}
|
||||
width="auto"
|
||||
centered
|
||||
className={styles.productModal}
|
||||
height={600}
|
||||
style={{
|
||||
width: "80vw",
|
||||
minWidth: "80vw",
|
||||
}}
|
||||
>
|
||||
<ProductDetailPage />
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
1
src/pages/menu/components/ProductPreviewDialog/index.ts
Normal file
1
src/pages/menu/components/ProductPreviewDialog/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { ProductPreviewDialog } from "./ProductPreviewDialog";
|
||||
Reference in New Issue
Block a user