This commit is contained in:
hamid zarghami
2026-07-04 09:45:24 +03:30
parent bcf03887f1
commit eb9973678c
18 changed files with 762 additions and 20 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
VITE_TOKEN_NAME = 'dmnu_a_t' VITE_TOKEN_NAME = 'dmnu_a_t'
VITE_REFRESH_TOKEN_NAME = 'dmnu-a-rt' VITE_REFRESH_TOKEN_NAME = 'dmnu-a-rt'
VITE_BASE_URL = 'https://dmenu-api.danakcorp.com' # VITE_BASE_URL = 'https://dmenu-api.danakcorp.com'
# VITE_BASE_URL = 'http://192.168.99.131:2000' VITE_BASE_URL = 'http://192.168.99.131:2000'
VITE_SOCKET_URL = 'https://dmenu-api.danakcorp.com' VITE_SOCKET_URL = 'https://dmenu-api.danakcorp.com'
+5
View File
@@ -83,6 +83,11 @@ export const Pages = {
notifications: { notifications: {
list: "/notifications/list", list: "/notifications/list",
}, },
sliders: {
list: "/sliders/list",
add: "/sliders/create",
update: "/sliders/update/",
},
statistics: { statistics: {
list: "/statistics", list: "/statistics",
}, },
+1
View File
@@ -22,6 +22,7 @@ export const MENU_PREVIEW_RESERVED_SEGMENTS = new Set([
"reviews", "reviews",
"pagers", "pagers",
"notifications", "notifications",
"sliders",
"assets", "assets",
"menu-preview", "menu-preview",
]); ]);
+2 -1
View File
@@ -68,7 +68,8 @@
"reviews": "نظرات", "reviews": "نظرات",
"pagers": "پیجرها", "pagers": "پیجرها",
"notifications": "تنظیمات اعلانات", "notifications": "تنظیمات اعلانات",
"statistics": "گزارشات" "statistics": "گزارشات",
"sliders": "اسلایدرها"
}, },
"shipment": { "shipment": {
"dineIn": "سرو در رستوران", "dineIn": "سرو در رستوران",
+2 -2
View File
@@ -208,9 +208,9 @@ export const useCreateOrderForm = () => {
}) })
} }
const registerNewCustomer = async (): Promise<string | null> => { const registerNewCustomer = async (): Promise<string | undefined> => {
if (!isNewCustomer) { if (!isNewCustomer) {
return customerUserId return customerUserId ?? undefined
} }
const response = await createUser({ const response = await createUser({
+1
View File
@@ -26,4 +26,5 @@ export const enum PermissionEnum {
MANAGE_SCHEDULES = "manage_schedules", MANAGE_SCHEDULES = "manage_schedules",
MANAGE_REPORTS = "manage_reports", MANAGE_REPORTS = "manage_reports",
MANAGE_CONTACTS = "manage_contacts", MANAGE_CONTACTS = "manage_contacts",
MANAGE_SLIDERS = "manage_sliders",
} }
+163
View File
@@ -0,0 +1,163 @@
import { type FC, useState } from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import { TickCircle } from "iconsax-react";
import { toast } from "react-toastify";
import { useNavigate } from "react-router-dom";
import Button from "@/components/Button";
import Input from "@/components/Input";
import { Pages } from "@/config/Pages";
import type { ErrorType } from "@/helpers/types";
import { extractErrorMessage } from "@/config/func";
import { useCreateSlider } from "./hooks/useSliderData";
import { useSingleUpload } from "../uploader/hooks/useUploaderData";
import type { CreateSliderType } from "./types/Types";
import SliderSidebar from "./components/SliderSidebar";
const CreateSlider: FC = () => {
const navigate = useNavigate();
const { mutate: createSlider, isPending } = useCreateSlider();
const { mutate: singleUpload, isPending: isUploading } = useSingleUpload();
const [imageFiles, setImageFiles] = useState<File[]>([]);
const formik = useFormik<CreateSliderType>({
initialValues: {
imageUrl: "",
title: "",
link: "",
order: 0,
isActive: true,
},
validationSchema: Yup.object().shape({
title: Yup.string().required("عنوان الزامی است"),
link: Yup.string()
.transform((value) => (value?.trim() === "" ? undefined : value))
.url("لینک معتبر نیست")
.notRequired(),
order: Yup.number().required("ترتیب الزامی است").min(0, "ترتیب باید مثبت باشد"),
isActive: Yup.boolean(),
}),
onSubmit: (values) => {
if (imageFiles.length === 0) {
toast.error("تصویر اسلایدر الزامی است");
return;
}
const submitSlider = (imageUrl: string) => {
createSlider(
{
...values,
imageUrl,
},
{
onSuccess: () => {
toast.success("اسلایدر با موفقیت ایجاد شد");
navigate(Pages.sliders.list);
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error));
},
}
);
};
singleUpload(imageFiles[0], {
onSuccess: (response) => {
const uploadedImageUrl = response?.data?.url || "";
if (!uploadedImageUrl) {
toast.error("آدرس تصویر آپلود شده دریافت نشد");
return;
}
submitSlider(uploadedImageUrl);
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error, "خطا در آپلود تصویر"));
},
});
},
});
return (
<div className="mt-5">
<div className="flex flex-col sm:flex-row w-full justify-between items-start sm:items-center gap-4">
<div className="text-lg font-light">افزودن اسلایدر</div>
<Button
className="px-5 w-full sm:w-auto"
onClick={async () => {
const errors = await formik.validateForm();
formik.setTouched({
title: true,
link: true,
order: true,
});
if (Object.keys(errors).length > 0) {
const firstError = Object.values(errors).find((error) => typeof error === "string");
if (firstError) toast.error(firstError);
return;
}
if (imageFiles.length === 0) {
toast.error("تصویر اسلایدر الزامی است");
return;
}
formik.handleSubmit();
}}
isloading={isPending || isUploading}
>
<div className="flex gap-2 items-center">
<TickCircle className="size-5" color="white" />
<div>ثبت اسلایدر</div>
</div>
</Button>
</div>
<div className="flex flex-col lg:flex-row gap-6 mt-6">
<div className="flex-1">
<div className="bg-white py-6 sm:py-8 xl:px-10 px-4 rounded-3xl">
<Input
label="عنوان"
name="title"
value={formik.values.title}
onChange={formik.handleChange}
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ""}
/>
<div className="mt-5">
<Input
label="لینک"
name="link"
value={formik.values.link}
onChange={formik.handleChange}
error_text={formik.touched.link && formik.errors.link ? formik.errors.link : ""}
/>
</div>
<div className="mt-5">
<Input
label="ترتیب"
name="order"
type="number"
value={formik.values.order ?? ""}
onChange={(e) => {
const value = e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("order", value);
}}
error_text={formik.touched.order && formik.errors.order ? formik.errors.order : ""}
/>
</div>
</div>
</div>
<div className="w-full lg:w-auto">
<SliderSidebar
isActive={formik.values.isActive}
onChangeActive={(value) => formik.setFieldValue("isActive", value)}
onChangeImage={setImageFiles}
/>
</div>
</div>
</div>
);
};
export default CreateSlider;
+71
View File
@@ -0,0 +1,71 @@
import { type FC } from "react";
import Table from "@/components/Table";
import Filters from "@/components/Filters";
import { Add } from "iconsax-react";
import Button from "@/components/Button";
import { Link } from "react-router-dom";
import { Pages } from "@/config/Pages";
import { useGetSliders, useDeleteSlider } from "./hooks/useSliderData";
import { useSliderFilters } from "./hooks/useSliderFilters";
import { getSliderTableColumns } from "./components/SliderTableColumns";
import { useSliderFiltersFields } from "./components/SliderFiltersFields";
const SlidersList: FC = () => {
const {
filters,
currentPage,
apiParams,
handleFiltersChange,
handlePageChange,
limit,
} = useSliderFilters();
const { data: slidersData, isLoading } = useGetSliders(apiParams);
const { mutate: deleteSlider, isPending: isDeleting } = useDeleteSlider();
const sliders = slidersData?.data || [];
const columns = getSliderTableColumns({
onDelete: (id: string) => deleteSlider(id),
isDeleting,
});
const filterFields = useSliderFiltersFields();
const totalPages = Math.ceil(sliders.length / limit) || 1;
return (
<div className="mt-5">
<div className="flex justify-between items-center">
<h1 className="text-lg font-light">لیست اسلایدرها</h1>
<Link to={Pages.sliders.add}>
<Button className="w-fit px-6">
<div className="flex gap-2 items-center">
<Add color="#fff" size={20} />
<span>افزودن اسلایدر</span>
</div>
</Button>
</Link>
</div>
<div className="mt-8">
<Filters
fields={filterFields}
onChange={handleFiltersChange}
initialValues={filters}
searchField="search"
/>
</div>
<Table
columns={columns}
data={sliders}
isloading={isLoading}
pagination={{
currentPage,
totalPages,
onPageChange: handlePageChange,
}}
/>
</div>
);
};
export default SlidersList;
+199
View File
@@ -0,0 +1,199 @@
import { type FC, useMemo, useState } from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import { TickCircle } from "iconsax-react";
import { toast } from "react-toastify";
import { useNavigate, useParams } from "react-router-dom";
import Button from "@/components/Button";
import Input from "@/components/Input";
import { Pages } from "@/config/Pages";
import type { ErrorType } from "@/helpers/types";
import { extractErrorMessage } from "@/config/func";
import { useGetSlider, useUpdateSlider } from "./hooks/useSliderData";
import { useSingleUpload } from "../uploader/hooks/useUploaderData";
import type { CreateSliderType } from "./types/Types";
import SliderSidebar from "./components/SliderSidebar";
const UpdateSlider: FC = () => {
const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
const { mutate: updateSlider, isPending } = useUpdateSlider();
const { mutate: singleUpload, isPending: isUploading } = useSingleUpload();
const { data: sliderData, isLoading } = useGetSlider(id || "");
const [imageFiles, setImageFiles] = useState<File[]>([]);
const initialValues = useMemo<CreateSliderType>(() => {
if (sliderData?.data) {
return {
imageUrl: sliderData.data.imageUrl || "",
title: sliderData.data.title || "",
link: sliderData.data.link || "",
order: sliderData.data.order ?? 0,
isActive: sliderData.data.isActive ?? true,
};
}
return {
imageUrl: "",
title: "",
link: "",
order: 0,
isActive: true,
};
}, [sliderData]);
const formik = useFormik<CreateSliderType>({
initialValues,
enableReinitialize: true,
validationSchema: Yup.object().shape({
title: Yup.string().required("عنوان الزامی است"),
link: Yup.string()
.transform((value) => (value?.trim() === "" ? undefined : value))
.url("لینک معتبر نیست")
.notRequired(),
order: Yup.number().required("ترتیب الزامی است").min(0, "ترتیب باید مثبت باشد"),
isActive: Yup.boolean(),
}),
onSubmit: (values) => {
if (!id) return;
if (imageFiles.length === 0 && !values.imageUrl) {
toast.error("تصویر اسلایدر الزامی است");
return;
}
const submitSlider = (imageUrl: string) => {
updateSlider(
{
id,
params: {
...values,
imageUrl,
},
},
{
onSuccess: () => {
toast.success("اسلایدر با موفقیت ویرایش شد");
navigate(Pages.sliders.list);
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error));
},
}
);
};
if (imageFiles.length > 0) {
singleUpload(imageFiles[0], {
onSuccess: (response) => {
const uploadedImageUrl = response?.data?.url || "";
if (!uploadedImageUrl) {
toast.error("آدرس تصویر آپلود شده دریافت نشد");
return;
}
submitSlider(uploadedImageUrl);
},
onError: (error: ErrorType) => {
toast.error(extractErrorMessage(error, "خطا در آپلود تصویر"));
},
});
return;
}
submitSlider(values.imageUrl);
},
});
if (isLoading) {
return (
<div className="mt-5">
<div className="text-lg font-light">در حال بارگذاری...</div>
</div>
);
}
return (
<div className="mt-5">
<div className="flex flex-col sm:flex-row w-full justify-between items-start sm:items-center gap-4">
<div className="text-lg font-light">ویرایش اسلایدر</div>
<Button
className="px-5 w-full sm:w-auto"
onClick={async () => {
const errors = await formik.validateForm();
formik.setTouched({
title: true,
link: true,
order: true,
});
if (Object.keys(errors).length > 0) {
const firstError = Object.values(errors).find((error) => typeof error === "string");
if (firstError) toast.error(firstError);
return;
}
if (imageFiles.length === 0 && !formik.values.imageUrl) {
toast.error("تصویر اسلایدر الزامی است");
return;
}
formik.handleSubmit();
}}
isloading={isPending || isUploading}
>
<div className="flex gap-2 items-center">
<TickCircle className="size-5" color="white" />
<div>ثبت تغییرات</div>
</div>
</Button>
</div>
<div className="flex flex-col lg:flex-row gap-6 mt-6">
<div className="flex-1">
<div className="bg-white py-6 sm:py-8 xl:px-10 px-4 rounded-3xl">
<Input
label="عنوان"
name="title"
value={formik.values.title}
onChange={formik.handleChange}
error_text={formik.touched.title && formik.errors.title ? formik.errors.title : ""}
/>
<div className="mt-5">
<Input
label="لینک"
name="link"
value={formik.values.link}
onChange={formik.handleChange}
error_text={formik.touched.link && formik.errors.link ? formik.errors.link : ""}
/>
</div>
<div className="mt-5">
<Input
label="ترتیب"
name="order"
type="number"
value={formik.values.order ?? ""}
onChange={(e) => {
const value = e.target.value === "" ? 0 : Number(e.target.value);
formik.setFieldValue("order", value);
}}
error_text={formik.touched.order && formik.errors.order ? formik.errors.order : ""}
/>
</div>
</div>
</div>
<div className="w-full lg:w-auto">
<SliderSidebar
isActive={formik.values.isActive}
onChangeActive={(value) => formik.setFieldValue("isActive", value)}
onChangeImage={setImageFiles}
preview={formik.values.imageUrl ? [formik.values.imageUrl] : []}
/>
</div>
</div>
</div>
);
};
export default UpdateSlider;
@@ -0,0 +1,15 @@
import { useMemo } from "react";
import type { FieldType } from "@/components/Filters";
export const useSliderFiltersFields = (): FieldType[] => {
return useMemo(
() => [
{
type: "input",
name: "search",
placeholder: "جستجو",
},
],
[]
);
};
@@ -0,0 +1,36 @@
import { type FC } from "react";
import UploadBoxDraggble from "@/components/UploadBoxDraggble";
import Switch from "@/components/Switch";
type Props = {
isActive: boolean;
onChangeActive: (value: boolean) => void;
onChangeImage: (files: File[]) => void;
preview?: string[];
};
const SliderSidebar: FC<Props> = (props) => {
return (
<div className="bg-white w-full lg:w-[300px] text-xs h-fit px-5 py-7 rounded-3xl">
<div className="flex items-center justify-between">
<div>وضعیت اسلایدر</div>
<Switch
active={props.isActive}
onChange={(value) => props.onChangeActive(value)}
/>
</div>
<div className="mt-8">
<div className="text-sm mb-2">تصویر اسلایدر</div>
<UploadBoxDraggble
label="تصویر اسلایدر را آپلود کنید"
onChange={(files) => props.onChangeImage(files)}
preview={props.preview}
imageSize="large"
/>
</div>
</div>
);
};
export default SliderSidebar;
@@ -0,0 +1,73 @@
import type { ColumnType } from "@/components/types/TableTypes";
import type { Slider } from "../types/Types";
import TrashWithConfrim from "@/components/TrashWithConfrim";
import { Eye } from "iconsax-react";
import { Link } from "react-router-dom";
import { Pages } from "@/config/Pages";
import Status from "@/components/Status";
interface GetSliderTableColumnsParams {
onDelete?: (id: string) => void;
isDeleting?: boolean;
}
export const getSliderTableColumns = ({
onDelete,
isDeleting,
}: GetSliderTableColumnsParams = {}): ColumnType<Slider>[] => {
return [
{
key: "title",
title: "عنوان",
render: (item: Slider) => item.title || "-",
},
{
key: "imageUrl",
title: "تصویر",
render: (item: Slider) => (
<img
src={item.imageUrl}
alt={item.title}
className="w-16 h-10 rounded object-cover"
/>
),
},
{
key: "link",
title: "لینک",
render: (item: Slider) => item.link || "-",
},
{
key: "order",
title: "ترتیب",
render: (item: Slider) => item.order,
},
{
key: "isActive",
title: "وضعیت",
render: (item: Slider) => (
<Status
variant={item.isActive ? "success" : "error"}
label={item.isActive ? "فعال" : "غیرفعال"}
/>
),
},
{
key: "actions",
title: "",
render: (item: Slider) => (
<div className="flex gap-2 items-center">
<Link to={Pages.sliders.update + item.id}>
<Eye size={20} color="#8C90A3" className="cursor-pointer" />
</Link>
{onDelete && (
<TrashWithConfrim
onDelete={() => onDelete(item.id)}
isloading={isDeleting}
/>
)}
</div>
),
},
];
};
+55
View File
@@ -0,0 +1,55 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import * as api from "../service/SliderService";
import type { CreateSliderType, GetSlidersParams } from "../types/Types";
export const useGetSliders = (params?: GetSlidersParams) => {
return useQuery({
queryKey: ["sliders", params],
queryFn: () => api.getSliders(params),
});
};
export const useCreateSlider = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: api.createSlider,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["sliders"],
});
},
});
};
export const useDeleteSlider = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: api.deleteSlider,
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["sliders"],
});
},
});
};
export const useGetSlider = (id: string) => {
return useQuery({
queryKey: ["slider", id],
queryFn: () => api.getSlider(id),
enabled: !!id,
});
};
export const useUpdateSlider = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: ({ id, params }: { id: string; params: CreateSliderType }) =>
api.updateSlider(id, params),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ["sliders"],
});
},
});
};
@@ -0,0 +1,43 @@
import { useMemo, useState } from "react";
import type { FilterValues } from "@/components/Filters";
import type { GetSlidersParams } from "../types/Types";
const DEFAULT_PAGE = 1;
const DEFAULT_LIMIT = 10;
export const useSliderFilters = () => {
const [filters, setFilters] = useState<FilterValues>({});
const [currentPage, setCurrentPage] = useState(DEFAULT_PAGE);
const [limit] = useState(DEFAULT_LIMIT);
const apiParams = useMemo<GetSlidersParams>(() => {
const params: GetSlidersParams = {
page: currentPage,
limit,
};
if (filters.search) {
params.search = filters.search as string;
}
return params;
}, [filters, currentPage, limit]);
const handleFiltersChange = (newFilters: FilterValues) => {
setFilters(newFilters);
setCurrentPage(DEFAULT_PAGE);
};
const handlePageChange = (page: number) => {
setCurrentPage(page);
};
return {
filters,
currentPage,
apiParams,
handleFiltersChange,
handlePageChange,
limit,
};
};
@@ -0,0 +1,34 @@
import axios from "@/config/axios";
import type {
CreateSliderType,
GetSlidersParams,
SliderResponse,
SlidersResponse,
} from "../types/Types";
export const getSliders = async (
params?: GetSlidersParams
): Promise<SlidersResponse> => {
const { data } = await axios.get<SlidersResponse>("/admin/sliders", { params });
return data;
};
export const createSlider = async (params: CreateSliderType) => {
const { data } = await axios.post("/admin/sliders", params);
return data;
};
export const deleteSlider = async (id: string) => {
const { data } = await axios.delete(`/admin/sliders/${id}`);
return data;
};
export const getSlider = async (id: string): Promise<SliderResponse> => {
const { data } = await axios.get<SliderResponse>(`/admin/sliders/${id}`);
return data;
};
export const updateSlider = async (id: string, params: CreateSliderType) => {
const { data } = await axios.patch(`/admin/sliders/${id}`, params);
return data;
};
+30
View File
@@ -0,0 +1,30 @@
import type { IResponse } from "@/types/response.types";
export type Slider = {
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
imageUrl: string;
title: string;
link: string;
order: number;
isActive: boolean;
};
export type SlidersResponse = IResponse<Slider[]>;
export type SliderResponse = IResponse<Slider>;
export type CreateSliderType = {
imageUrl: string;
title: string;
link?: string;
order: number;
isActive: boolean;
};
export type GetSlidersParams = {
page?: number;
limit?: number;
search?: string;
};
+6
View File
@@ -47,6 +47,9 @@ import NotificationsList from '@/pages/notifications/List'
import Notification from '@/components/Notification' import Notification from '@/components/Notification'
import ReportsList from '@/pages/report/List' import ReportsList from '@/pages/report/List'
import Statistics from '@/pages/statistics/Statistics' import Statistics from '@/pages/statistics/Statistics'
import SlidersList from '@/pages/sliders/List'
import CreateSlider from '@/pages/sliders/Create'
import UpdateSlider from '@/pages/sliders/Update'
const MainRouter: FC = () => { const MainRouter: FC = () => {
const { hasSubMenu } = useSharedStore() const { hasSubMenu } = useSharedStore()
@@ -112,6 +115,9 @@ const MainRouter: FC = () => {
<Route path={Pages.pagers.list} element={<PagersList />} /> <Route path={Pages.pagers.list} element={<PagersList />} />
<Route path={Pages.notifications.list} element={<NotificationsList />} /> <Route path={Pages.notifications.list} element={<NotificationsList />} />
<Route path={Pages.sliders.list} element={<SlidersList />} />
<Route path={Pages.sliders.add} element={<CreateSlider />} />
<Route path={Pages.sliders.update + ':id'} element={<UpdateSlider />} />
<Route path={Pages.reports.list} element={<ReportsList />} /> <Route path={Pages.reports.list} element={<ReportsList />} />
+24 -15
View File
@@ -1,21 +1,21 @@
import { type FC, useEffect } from 'react'
import LogoImage from '../assets/images/logo.png'
import LogoSmall from '../assets/images/logo-small.png'
import { useTranslation } from 'react-i18next'
import { DocumentText, Home2, Logout, People, Setting2, TicketDiscount, Calendar, Security, Card, SecurityUser, TruckFast, Element3, Star1, NotificationBing, SmsEdit } from 'iconsax-react'
import SideBarItem from './SideBarItem'
import { useLocation } from 'react-router-dom'
import { Pages } from '../config/Pages'
import { useSharedStore } from './store/sharedStore'
import { clx } from '../helpers/utils'
import FoodsSubMenu from './components/FoodsSubMenu'
import OrdersSubMenu from './components/OrdersSubMenu'
import CustomersSubMenu from './components/CustomersSubMenu'
import DiscountSubMenu from './components/DiscountSubMenu'
import { SideBarItemHasSubMenu } from '../config/SideBarSubMenu'
import { usePermissions } from '@/hooks/usePermissions' import { usePermissions } from '@/hooks/usePermissions'
import { PermissionEnum } from '@/pages/roles/enum/Enum' import { PermissionEnum } from '@/pages/roles/enum/Enum'
import { Calendar, Card, DocumentText, Element3, Gallery, Home2, Logout, NotificationBing, People, Security, SecurityUser, Setting2, SmsEdit, Star1, TicketDiscount, TruckFast } from 'iconsax-react'
import { type FC, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import Skeleton from 'react-loading-skeleton' import Skeleton from 'react-loading-skeleton'
import { useLocation } from 'react-router-dom'
import LogoSmall from '../assets/images/logo-small.png'
import LogoImage from '../assets/images/logo.png'
import { Pages } from '../config/Pages'
import { SideBarItemHasSubMenu } from '../config/SideBarSubMenu'
import { clx } from '../helpers/utils'
import CustomersSubMenu from './components/CustomersSubMenu'
import DiscountSubMenu from './components/DiscountSubMenu'
import FoodsSubMenu from './components/FoodsSubMenu'
import OrdersSubMenu from './components/OrdersSubMenu'
import SideBarItem from './SideBarItem'
import { useSharedStore } from './store/sharedStore'
const SideBar: FC = () => { const SideBar: FC = () => {
@@ -289,6 +289,15 @@ const SideBar: FC = () => {
activeName='reports' activeName='reports'
/> />
)} )}
{checkPermission(PermissionEnum.MANAGE_SLIDERS) && (
<SideBarItem
icon={<Gallery variant={isActive('sliders') ? 'Bold' : 'Outline'} color={isActive('sliders') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
title={t('sidebar.sliders')}
isActive={isActive('sliders')}
link={Pages.sliders.list}
activeName='sliders'
/>
)}
</div> </div>
)} )}