fixes
- apply fixed height for footer buttons over app - add floating cart button in cart page in desktop size
This commit is contained in:
23
src/pages/menu/components/CartButton/CartButton.module.css
Normal file
23
src/pages/menu/components/CartButton/CartButton.module.css
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Scroll to Top Button */
|
||||
.scrollToTopButton {
|
||||
animation: fadeInUp 0.3s ease-out;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.scrollToTopButton:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2) !important;
|
||||
}
|
||||
|
||||
/* Dark theme scroll to top button */
|
||||
:global(.darkApp) .scrollToTopButton {
|
||||
background-color: var(--primary) !important;
|
||||
border-color: var(--primary) !important;
|
||||
color: #000000 !important;
|
||||
}
|
||||
|
||||
:global(.darkApp) .scrollToTopButton:hover {
|
||||
background-color: #ffd633 !important;
|
||||
border-color: #ffd633 !important;
|
||||
box-shadow: 0 6px 16px rgba(255, 198, 0, 0.3) !important;
|
||||
}
|
||||
60
src/pages/menu/components/CartButton/CartButton.tsx
Normal file
60
src/pages/menu/components/CartButton/CartButton.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Badge, Button } from "antd";
|
||||
import CartIcon from "components/Icons/cart/CartIcon";
|
||||
import { selectCartItems } from "features/order/orderSlice";
|
||||
import useBreakPoint from "hooks/useBreakPoint";
|
||||
import { useCallback } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
import { colors } from "ThemeConstants";
|
||||
import styles from "./CartButton.module.css";
|
||||
|
||||
export function CartButton() {
|
||||
const { isRTL } = useAppSelector((state) => state.locale);
|
||||
const { themeName } = useAppSelector((state) => state.theme);
|
||||
const { isMobile, isTablet } = useBreakPoint();
|
||||
const { id } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const items = useAppSelector(selectCartItems);
|
||||
|
||||
const onCartClick = useCallback(() => {
|
||||
navigate(`/${id}/cart`);
|
||||
}, [navigate, id]);
|
||||
|
||||
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
type="primary"
|
||||
shape="circle"
|
||||
size={"large"}
|
||||
icon={
|
||||
<div style={{ position: "relative", left: 4, top: 2 }}>
|
||||
<CartIcon />
|
||||
</div>
|
||||
}
|
||||
onClick={onCartClick}
|
||||
className={`${styles.scrollToTopButton}`}
|
||||
style={{
|
||||
position: "fixed",
|
||||
bottom: isMobile ? "100px" : isTablet ? "120px" : "25px",
|
||||
right: !isRTL ? "auto" : isMobile ? "20px" : "32px",
|
||||
left: !isRTL ? (isMobile ? "20px" : "32px") : "auto",
|
||||
zIndex: 1000,
|
||||
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
||||
backgroundColor:
|
||||
themeName === "dark" ? colors.primary : colors.primary,
|
||||
borderColor: themeName === "dark" ? colors.primary : colors.primary,
|
||||
width: isMobile ? 48 : 56,
|
||||
height: isMobile ? 48 : 56,
|
||||
}}
|
||||
>
|
||||
<Badge
|
||||
count={totalItems}
|
||||
size="default"
|
||||
style={{ position: "absolute", top: -35, right: -18 }}
|
||||
/>
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,21 +1,18 @@
|
||||
import { Badge, Button, Grid } from "antd";
|
||||
import { Badge, Button } from "antd";
|
||||
import CartIcon from "components/Icons/cart/CartIcon";
|
||||
import ProText from "components/ProText";
|
||||
import { selectCartItems } from "features/order/orderSlice";
|
||||
import useBreakPoint from "hooks/useBreakPoint";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
import { colors, ProBlack2 } from "ThemeConstants";
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
export function MenuFooter() {
|
||||
const items = useAppSelector(selectCartItems);
|
||||
const restaurantName = localStorage.getItem("restaurantName");
|
||||
const { themeName } = useAppSelector((state) => state.theme);
|
||||
const { xs, sm } = useBreakpoint();
|
||||
const isMobile = xs;
|
||||
const isTablet = sm && !xs;
|
||||
const { isMobile, isTablet } = useBreakPoint();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0);
|
||||
@@ -30,7 +27,7 @@ export function MenuFooter() {
|
||||
position: "fixed",
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
height: "10vh",
|
||||
height: "80px",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-around",
|
||||
@@ -51,8 +48,7 @@ export function MenuFooter() {
|
||||
shape="round"
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 48,
|
||||
marginBottom: 16,
|
||||
height: 50,
|
||||
boxShadow: "none",
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -157,7 +157,7 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
style={{
|
||||
margin: 0,
|
||||
display: "inline-block",
|
||||
fontSize: xs ? "1rem" : 18,
|
||||
fontSize: "1rem" ,
|
||||
fontWeight: 600,
|
||||
letterSpacing: "-0.01em",
|
||||
lineHeight: 1.2,
|
||||
@@ -194,7 +194,7 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
price={item.original_price}
|
||||
strong
|
||||
style={{
|
||||
fontSize: xs ? "1rem" : 22,
|
||||
fontSize: "1rem",
|
||||
fontWeight: 700,
|
||||
color: colors.primary,
|
||||
textDecoration: "line-through",
|
||||
@@ -207,7 +207,7 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
||||
price={item.price}
|
||||
strong
|
||||
style={{
|
||||
fontSize: xs ? "1rem" : 22,
|
||||
fontSize: "1rem",
|
||||
fontWeight: 700,
|
||||
color: colors.primary,
|
||||
}}
|
||||
|
||||
@@ -212,6 +212,7 @@ const MenuSkeleton = ({
|
||||
width: "32px",
|
||||
height: "32px",
|
||||
borderRadius: "50%",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
@@ -449,7 +449,6 @@
|
||||
}
|
||||
|
||||
.contentWrapper {
|
||||
max-width: 800px;
|
||||
margin: 0px auto;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
@@ -546,12 +545,12 @@
|
||||
}
|
||||
|
||||
.leftShape {
|
||||
top: 170px;
|
||||
top: 171px;
|
||||
left: -3px;
|
||||
}
|
||||
|
||||
.rightShape {
|
||||
top: 170px;
|
||||
top: 171px;
|
||||
left: 116px;
|
||||
}
|
||||
|
||||
@@ -615,12 +614,12 @@
|
||||
}
|
||||
|
||||
.leftShape {
|
||||
top: 170px;
|
||||
top: 171px;
|
||||
left: -10px;
|
||||
}
|
||||
|
||||
.rightShape {
|
||||
top: 170px;
|
||||
top: 171px;
|
||||
left: 179px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { StarFilled } from "@ant-design/icons";
|
||||
import { Grid, Image, Space } from "antd";
|
||||
import { Image, Space } from "antd";
|
||||
import { FloatingButton } from "components/FloatingButton/FloatingButton";
|
||||
import ImageWithFallback from "components/ImageWithFallback";
|
||||
import LoyaltyCard from "components/LoyaltyCard/LoyaltyCard";
|
||||
import ProText from "components/ProText";
|
||||
import ProTitle from "components/ProTitle";
|
||||
import { useScrollHandler } from "contexts/ScrollHandlerContext";
|
||||
import useBreakPoint from "hooks/useBreakPoint";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useParams, useSearchParams } from "react-router-dom";
|
||||
import {
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
import { useAppSelector } from "redux/hooks";
|
||||
import { default_image } from "utils/constants";
|
||||
import BackButton from "./components/BackButton";
|
||||
import { CartButton } from "./components/CartButton/CartButton";
|
||||
import { CategoriesList } from "./components/CategoriesList/CategoriesList";
|
||||
import LocalStorageHandler from "./components/LocalStorageHandler";
|
||||
import { MenuFooter } from "./components/MenuFooter/MenuFooter";
|
||||
@@ -24,8 +26,6 @@ import ScrollEventHandler from "./components/ScrollEventHandler";
|
||||
import SearchButton from "./components/SearchButton";
|
||||
import styles from "./menu.module.css";
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
function MenuPage() {
|
||||
const { id } = useParams();
|
||||
const [searchParams] = useSearchParams();
|
||||
@@ -44,8 +44,7 @@ function MenuPage() {
|
||||
},
|
||||
);
|
||||
const { categoryRefs } = useScrollHandler();
|
||||
const { xs, md } = useBreakpoint();
|
||||
const isTablet = !xs && !md;
|
||||
const { isMobile, isTablet, isDesktop } = useBreakPoint();
|
||||
|
||||
const isLoading = isLoadingRestaurant || isLoadingMenu;
|
||||
|
||||
@@ -68,7 +67,7 @@ function MenuPage() {
|
||||
alt={t("menu.restaurantCover")}
|
||||
className={styles.cover}
|
||||
width={"100%"}
|
||||
height={xs ? 182 : isTablet ? 200 : 220}
|
||||
height={isMobile ? 182 : isTablet ? 200 : 220}
|
||||
preview={false}
|
||||
loadingContainerStyle={{
|
||||
width: "100vw",
|
||||
@@ -122,23 +121,8 @@ function MenuPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`${styles.pageContainer}`}
|
||||
// style={{
|
||||
// maxWidth: isDesktop ? "1200px" : "100%",
|
||||
// margin: isDesktop ? "0 auto" : "0",
|
||||
// }}
|
||||
>
|
||||
<Space
|
||||
direction="vertical"
|
||||
// size={isMobile ? "middle" : isTablet ? "large" : "large"}
|
||||
style={{ width: "100%", gap: 16 }}
|
||||
>
|
||||
{/* Placeholder to prevent content jumping when categories become sticky */}
|
||||
{/* {isCategoriesSticky && (
|
||||
<div style={{ height: xs ? 95 : md ? 160 : 180 }} />
|
||||
)} */}
|
||||
|
||||
<div className={`${styles.pageContainer}`}>
|
||||
<Space direction="vertical" style={{ width: "100%", gap: 16 }}>
|
||||
<div>
|
||||
<LoyaltyCard />
|
||||
<CategoriesList categories={menuData?.categories || []} />
|
||||
@@ -156,6 +140,7 @@ function MenuPage() {
|
||||
|
||||
<ScrollEventHandler />
|
||||
<FloatingButton />
|
||||
{isDesktop && <CartButton />}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
|
||||
Reference in New Issue
Block a user