add Header for cart page
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
:root {
|
:root {
|
||||||
--background: #f7f7f7;
|
--background: #f7f7f7;
|
||||||
--foreground: #181818;
|
--foreground: #181818;
|
||||||
|
--primary-light: #fff;
|
||||||
|
--primary-dark: #0a0a0a;
|
||||||
--primary: #ffb700;
|
--primary: #ffb700;
|
||||||
--primary2: #ffc600;
|
--primary2: #ffc600;
|
||||||
--secondary: #09237d;
|
--secondary: #09237d;
|
||||||
|
|||||||
@@ -1,231 +0,0 @@
|
|||||||
import {
|
|
||||||
LogoutOutlined,
|
|
||||||
QuestionOutlined,
|
|
||||||
SettingOutlined,
|
|
||||||
UserOutlined,
|
|
||||||
} from "@ant-design/icons";
|
|
||||||
import {
|
|
||||||
Dropdown,
|
|
||||||
Flex,
|
|
||||||
FloatButton,
|
|
||||||
Layout,
|
|
||||||
MenuProps,
|
|
||||||
message,
|
|
||||||
theme,
|
|
||||||
Tooltip,
|
|
||||||
Typography,
|
|
||||||
} from "antd";
|
|
||||||
import { ReactNode, useEffect, useRef, useState } from "react";
|
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
|
||||||
|
|
||||||
import dayjs from "dayjs";
|
|
||||||
import { logout } from "features/auth/authSlice.ts";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useAppDispatch } from "redux/hooks.ts";
|
|
||||||
import { PATH_AUTH } from "utils/constants.ts";
|
|
||||||
import LangSelect from "./components/langSelect/LangSelect.tsx";
|
|
||||||
import HeaderNav from "./HeaderNav.tsx";
|
|
||||||
import SideNav from "./SideNav.tsx";
|
|
||||||
import "./styles.css";
|
|
||||||
|
|
||||||
const { Content } = Layout;
|
|
||||||
const { Title } = Typography;
|
|
||||||
type AppLayoutProps = {
|
|
||||||
withSidebar?: boolean;
|
|
||||||
children: ReactNode;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AppLayout = ({ children, withSidebar = true }: AppLayoutProps) => {
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const {
|
|
||||||
token: { borderRadius },
|
|
||||||
} = theme.useToken();
|
|
||||||
const [navFill, setNavFill] = useState(false);
|
|
||||||
const navigate = useNavigate();
|
|
||||||
const nodeRef = useRef(null);
|
|
||||||
const floatBtnRef = useRef(null);
|
|
||||||
const location = useLocation();
|
|
||||||
const isMenu = location.pathname === "/menu";
|
|
||||||
|
|
||||||
const items: MenuProps["items"] = [
|
|
||||||
{
|
|
||||||
key: "user-profile-link",
|
|
||||||
label: t("profile"),
|
|
||||||
icon: <UserOutlined />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "user-settings-link",
|
|
||||||
label: t("settings"),
|
|
||||||
icon: <SettingOutlined />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "user-help-link",
|
|
||||||
label: t("help center"),
|
|
||||||
icon: <QuestionOutlined />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: "divider",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "user-logout-link",
|
|
||||||
label: t("logout"),
|
|
||||||
icon: <LogoutOutlined />,
|
|
||||||
danger: true,
|
|
||||||
onClick: () => {
|
|
||||||
message.open({
|
|
||||||
type: "loading",
|
|
||||||
content: t("msg-success-logout"),
|
|
||||||
});
|
|
||||||
|
|
||||||
dispatch(logout());
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
navigate(PATH_AUTH.signin);
|
|
||||||
}, 1000);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
window.addEventListener("scroll", () => {
|
|
||||||
if (window.scrollY > 5) {
|
|
||||||
setNavFill(true);
|
|
||||||
} else {
|
|
||||||
setNavFill(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Layout
|
|
||||||
style={{
|
|
||||||
minHeight: "100vh",
|
|
||||||
// backgroundColor: 'white',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{withSidebar && (
|
|
||||||
<SideNav
|
|
||||||
trigger={null}
|
|
||||||
style={{
|
|
||||||
overflow: "auto",
|
|
||||||
background: "none",
|
|
||||||
border: "none",
|
|
||||||
transition: "all .2s",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<HeaderNav
|
|
||||||
style={{
|
|
||||||
padding: "0px 20px 0px 20px",
|
|
||||||
background: navFill ? "rgba(255, 255, 255, .5)" : "none",
|
|
||||||
backdropFilter: navFill ? "blur(8px)" : "none",
|
|
||||||
boxShadow: navFill ? "0 0 8px 2px rgba(0, 0, 0, 0.05)" : "none",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
height: "7vh",
|
|
||||||
zIndex: 10,
|
|
||||||
transition: "all .25s",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Flex gap="middle" align="start" style={{ gap: 25 }}>
|
|
||||||
<Tooltip title={dayjs().format("DD/MM/YYYY")}>
|
|
||||||
<Title level={3} style={{ position: "relative", top: -2 }}>
|
|
||||||
{dayjs().format("DD/MM/YYYY")}{" "}
|
|
||||||
</Title>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip title={t("language")}>
|
|
||||||
<LangSelect />
|
|
||||||
</Tooltip>
|
|
||||||
</Flex>
|
|
||||||
{/* <Flex align="center">
|
|
||||||
<Input.Search
|
|
||||||
placeholder="search"
|
|
||||||
style={{
|
|
||||||
width: isMobile ? "100%" : "400px",
|
|
||||||
marginLeft: isMobile ? 0 : ".5rem",
|
|
||||||
}}
|
|
||||||
size="middle"
|
|
||||||
/>
|
|
||||||
</Flex> */}
|
|
||||||
|
|
||||||
<Flex align="end" gap="small">
|
|
||||||
{/* <Tooltip title="Apps">
|
|
||||||
<Button icon={<AppstoreOutlined />} type="text" size="large" />
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip title="Messages">
|
|
||||||
<Button icon={<MessageOutlined />} type="text" size="large" />
|
|
||||||
</Tooltip> */}
|
|
||||||
{/* <Tooltip title="Theme">
|
|
||||||
<Switch
|
|
||||||
className=" hidden sm:inline py-1"
|
|
||||||
checkedChildren={<MoonOutlined />}
|
|
||||||
unCheckedChildren={<SunOutlined />}
|
|
||||||
checked={mytheme === "light" ? true : false}
|
|
||||||
onClick={() => dispatch(toggleTheme())}
|
|
||||||
/>
|
|
||||||
</Tooltip> */}
|
|
||||||
|
|
||||||
{/* <Badge
|
|
||||||
count={2}
|
|
||||||
size="small"
|
|
||||||
style={{
|
|
||||||
top: 15,
|
|
||||||
right: 5,
|
|
||||||
left: 5,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BellOutlined
|
|
||||||
style={{
|
|
||||||
fontSize: 20,
|
|
||||||
marginTop: 15,
|
|
||||||
marginLeft: 15,
|
|
||||||
marginRight: 15,
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={() => setNotificationsDrawerOpen(true)}
|
|
||||||
/>
|
|
||||||
</Badge> */}
|
|
||||||
<Dropdown menu={isMenu ? {} : { items }} trigger={["click"]}>
|
|
||||||
<Flex>
|
|
||||||
{!isMenu && (
|
|
||||||
<img
|
|
||||||
src={"/avatar.png"}
|
|
||||||
alt="user profile photo"
|
|
||||||
height={36}
|
|
||||||
width={36}
|
|
||||||
style={{
|
|
||||||
borderRadius,
|
|
||||||
objectFit: "cover",
|
|
||||||
position: "relative",
|
|
||||||
top: 5,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</Dropdown>
|
|
||||||
</Flex>
|
|
||||||
</HeaderNav>
|
|
||||||
<Content>
|
|
||||||
<div ref={nodeRef} style={{ background: "none" }}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
<div ref={floatBtnRef}>
|
|
||||||
<FloatButton.BackTop />
|
|
||||||
</div>
|
|
||||||
</Content>
|
|
||||||
{/* <FooterNav
|
|
||||||
style={{
|
|
||||||
textAlign: "center",
|
|
||||||
marginLeft: collapsed ? 0 : "200px",
|
|
||||||
background: "none",
|
|
||||||
}}
|
|
||||||
/> */}
|
|
||||||
</Layout>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
80
src/layouts/app/AppLayout.tsx
Normal file
80
src/layouts/app/AppLayout.tsx
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { MoonOutlined, SunOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
|
import { Button, Flex, Image, Layout, Switch, Tooltip } from "antd";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
import { toggleTheme } from "features/theme/themeSlice.ts";
|
||||||
|
import useBreakPoint from "hooks/useBreakPoint.ts";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useAppDispatch, useAppSelector } from "redux/hooks.ts";
|
||||||
|
import { colors, ProBlack2 } from "ThemeConstants.ts";
|
||||||
|
import LangSelect from "./components/langSelect/LangSelect.tsx";
|
||||||
|
import HeaderNav from "./HeaderNav.tsx";
|
||||||
|
import "./styles.css";
|
||||||
|
|
||||||
|
const { Content } = Layout;
|
||||||
|
type AppLayoutProps = {
|
||||||
|
children: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AppLayout = ({ children }: AppLayoutProps) => {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { themeName } = useAppSelector((state) => state.theme);
|
||||||
|
const { isDesktop } = useBreakPoint();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Layout
|
||||||
|
style={{
|
||||||
|
minHeight: "100vh",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isDesktop && (
|
||||||
|
<HeaderNav className="header-nav">
|
||||||
|
<Flex align="center" gap="middle">
|
||||||
|
<Tooltip>
|
||||||
|
<Button
|
||||||
|
type="text"
|
||||||
|
icon={<UserOutlined />}
|
||||||
|
className="user-icon"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Flex align="center" gap="middle">
|
||||||
|
<Tooltip title={t("language")}>
|
||||||
|
<div style={{ position: "relative", top: -26 }}>
|
||||||
|
<LangSelect />
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Tooltip title="Theme">
|
||||||
|
<Switch
|
||||||
|
checkedChildren={<MoonOutlined />}
|
||||||
|
unCheckedChildren={<SunOutlined />}
|
||||||
|
checked={themeName === "light" ? true : false}
|
||||||
|
onClick={() => dispatch(toggleTheme())}
|
||||||
|
style={{
|
||||||
|
background:
|
||||||
|
themeName === "dark" ? colors.primary : ProBlack2,
|
||||||
|
borderRadius: "12px",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
|
<Image
|
||||||
|
src="/me.png"
|
||||||
|
alt="user profile photo"
|
||||||
|
height={40}
|
||||||
|
width={40}
|
||||||
|
className="user-profile-image"
|
||||||
|
preview={false}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
</HeaderNav>
|
||||||
|
)}
|
||||||
|
<Content>{children}</Content>
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1 +1,2 @@
|
|||||||
export { AppLayout } from './App.tsx';
|
export { AppLayout } from './AppLayout.tsx';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,44 @@
|
|||||||
|
.header-nav {
|
||||||
|
padding: 0 1rem;
|
||||||
|
background: #fff;
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
display: flex;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
gap: 4px;
|
||||||
|
transition: all 0.25s;
|
||||||
|
height: 8vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border-radius: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--primary-light);
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-profile-image {
|
||||||
|
border-radius: 12px;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
position: relative;
|
||||||
|
top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
:where(.darkApp) .user-profile-image {
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.trigger {
|
.trigger {
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
@@ -64,3 +105,11 @@
|
|||||||
right: 30px !important;
|
right: 30px !important;
|
||||||
width: 32px;
|
width: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:where(.darkApp) .header-nav {
|
||||||
|
background: var(--primary-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
:where(.darkApp) .user-icon {
|
||||||
|
background: var(--primary-dark);
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1025px) {
|
@media (min-width: 1025px) {
|
||||||
.menuSections{
|
.menuSections {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,28 +630,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skeleton Loading Styles */
|
|
||||||
.skeletonContainer {
|
|
||||||
animation: skeletonPulse 1.5s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-image {
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-input {
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-button {
|
|
||||||
border-radius: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes skeletonPulse {
|
@keyframes skeletonPulse {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
@@ -673,72 +651,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-active .ant-skeleton-input,
|
|
||||||
.skeletonContainer .ant-skeleton-active .ant-skeleton-image,
|
|
||||||
.skeletonContainer .ant-skeleton-active .ant-skeleton-button {
|
|
||||||
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
|
|
||||||
background-size: 200px 100%;
|
|
||||||
animation: skeletonShimmer 1.5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile-specific skeleton styles */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.skeletonContainer .ant-skeleton {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-image {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-input {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-button {
|
|
||||||
border-radius: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark theme skeleton styles */
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-active .ant-skeleton-input,
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-active .ant-skeleton-image,
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-active .ant-skeleton-button {
|
|
||||||
background: linear-gradient(90deg, #181818 25%, #363636 50%, #181818 75%);
|
|
||||||
background-size: 200px 100%;
|
|
||||||
animation: skeletonShimmer 1.5s infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-input,
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-image,
|
|
||||||
:global(.darkApp) .skeletonContainer .ant-skeleton-button {
|
|
||||||
background-color: #181818;
|
|
||||||
border-color: #363636;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tablet-specific skeleton styles */
|
|
||||||
@media (min-width: 769px) and (max-width: 1024px) {
|
|
||||||
.skeletonContainer {
|
|
||||||
padding: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-image {
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-input {
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.skeletonContainer .ant-skeleton-button {
|
|
||||||
border-radius: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuItemsGridSticky {
|
.menuItemsGridSticky {
|
||||||
height: 60;
|
height: 60;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,13 +48,16 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Group products by category
|
// Group products by category
|
||||||
const productsByCategory = products?.reduce((acc, product) => {
|
const productsByCategory = products?.reduce(
|
||||||
|
(acc, product) => {
|
||||||
if (product.categoryId && !acc[product?.categoryId]) {
|
if (product.categoryId && !acc[product?.categoryId]) {
|
||||||
acc[product?.categoryId] = [];
|
acc[product?.categoryId] = [];
|
||||||
}
|
}
|
||||||
acc[product?.categoryId || 0].push(product);
|
acc[product?.categoryId || 0].push(product);
|
||||||
return acc;
|
return acc;
|
||||||
}, {} as Record<number, Product[]>);
|
},
|
||||||
|
{} as Record<number, Product[]>,
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -170,14 +173,14 @@ export function MenuList({ data, categoryRefs }: MenuListProps) {
|
|||||||
style={{
|
style={{
|
||||||
display: "-webkit-box",
|
display: "-webkit-box",
|
||||||
WebkitBoxOrient: "vertical",
|
WebkitBoxOrient: "vertical",
|
||||||
WebkitLineClamp: xs ? 2 : 4,
|
WebkitLineClamp: 2,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
textOverflow: "ellipsis",
|
textOverflow: "ellipsis",
|
||||||
wordWrap: "break-word",
|
wordWrap: "break-word",
|
||||||
overflowWrap: "break-word",
|
overflowWrap: "break-word",
|
||||||
lineHeight: "1.5rem",
|
lineHeight: "1.5rem",
|
||||||
maxHeight: xs ? "3em" : "6.6em",
|
maxHeight: "3em",
|
||||||
fontSize: xs ? "1rem" : 18,
|
fontSize: "1rem",
|
||||||
letterSpacing: "0.01em",
|
letterSpacing: "0.01em",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function MenuPage() {
|
|||||||
restaurantDetails?.restaurant.id,
|
restaurantDetails?.restaurant.id,
|
||||||
{
|
{
|
||||||
skip: !restaurantDetails?.restaurant.id,
|
skip: !restaurantDetails?.restaurant.id,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
const { categoryRefs } = useScrollHandler();
|
const { categoryRefs } = useScrollHandler();
|
||||||
const { xs, md } = useBreakpoint();
|
const { xs, md } = useBreakpoint();
|
||||||
@@ -58,7 +58,7 @@ function MenuPage() {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<MenuSkeleton categoryCount={6} itemCount={8} variant="default" />
|
<MenuSkeleton categoryCount={10} itemCount={8} variant="default" />
|
||||||
) : (
|
) : (
|
||||||
<div className={styles.menuContainer}>
|
<div className={styles.menuContainer}>
|
||||||
<div className={styles.restaurantHeader}>
|
<div className={styles.restaurantHeader}>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Grid } from "antd";
|
import { Grid } from "antd";
|
||||||
import { Loader } from "components/Loader/Loader";
|
import { Loader } from "components/Loader/Loader";
|
||||||
import { PrivateRoute } from "components/privateRoute/PrivateRoute";
|
import { PrivateRoute } from "components/privateRoute/PrivateRoute";
|
||||||
|
import { AppLayout } from "layouts";
|
||||||
import HeaderMenuDrawer from "layouts/app/HeaderMenuDrawer";
|
import HeaderMenuDrawer from "layouts/app/HeaderMenuDrawer";
|
||||||
import AddressPage from "pages/address/page";
|
import AddressPage from "pages/address/page";
|
||||||
import CartPage from "pages/cart/page";
|
import CartPage from "pages/cart/page";
|
||||||
@@ -73,7 +74,15 @@ export const router = createHashRouter([
|
|||||||
|
|
||||||
{
|
{
|
||||||
path: "/:id/cart",
|
path: "/:id/cart",
|
||||||
element: <PageWrapper children={<CartPage />} />,
|
element: (
|
||||||
|
<PageWrapper
|
||||||
|
children={
|
||||||
|
<AppLayout>
|
||||||
|
<CartPage />
|
||||||
|
</AppLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
),
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user