merge and resolve conflict

This commit is contained in:
2024-07-11 10:47:01 +03:30
42 changed files with 1243 additions and 338 deletions

View File

@@ -1,19 +1,18 @@
import { Collapse, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import WifiIcon from "@mui/icons-material/Wifi";
import SidebarSubitems from "@/core/components/SidebarSubitems";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
import Link from "next/link";
const SidebarListItems = ({ menuItem, dispatch }) => {
return (
<>
<ListItem disablePadding sx={{ p: 0 }}>
<ListItem disablePadding divider>
<ListItemButton
sx={{
"&.Mui-selected": {
backgroundColor: "rgba(0, 0, 0, 0.2)",
},
}}
sx={{ py: 1, px: 0.5 }}
disableGutters
selected={menuItem.selected}
component={menuItem.type === "page" ? Link : null}
href={menuItem.type === "page" ? menuItem.route : null}
onClick={() => {
dispatch({ type: "COLLAPSE_MENU", id: menuItem.id });
}}
@@ -25,21 +24,28 @@ const SidebarListItems = ({ menuItem, dispatch }) => {
color: "primary.main",
width: 40,
height: 24,
pr: 2,
}}
>
{menuItem.icon}
</ListItemIcon>
<ListItemText primary={menuItem.id} />
<ListItemText primary={menuItem.label} />
{menuItem.hasSubitems ? menuItem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
</ListItemButton>
</ListItem>
<Collapse in={menuItem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
{menuItem.hasSubitems
? menuItem.Subitems.map((subitem, index) => {
return <SidebarSubitems dispatch={dispatch} key={index} subitem={subitem} />;
})
: null}
{menuItem.hasSubitems ? (
<List
disablePadding
dense
sx={{
background: "#00000008",
}}
>
{menuItem.Subitems.map((subitem, index) => {
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subitem} />;
})}
</List>
) : null}
</Collapse>
</>
);

View File

@@ -1,221 +1,86 @@
"use client";
import { List } from "@mui/material";
import SidebarListItems from "@/core/components/SidebarListItems";
import { useEffect, useReducer, useState } from "react";
import { usePermissions } from "@/lib/hooks/usePermissions";
import { List } from "@mui/material";
import { usePathname } from "next/navigation";
import SecurityIcon from "@mui/icons-material/Security";
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
import AssessmentIcon from "@mui/icons-material/Assessment";
import AirlineSeatReclineNormalIcon from "@mui/icons-material/AirlineSeatReclineNormal";
import RepartitionIcon from "@mui/icons-material/Repartition";
import { useEffect, useReducer, useState } from "react";
import { filterMenuItems } from "../utils/filterMenuItems";
import { pageMenu } from "../utils/pageMenu";
const data = [
{
id: "hello",
type: "menu",
route: "/hello",
icon: <SecurityIcon sx={{ width: "inherit", height: "inherit" }} />,
selected: false,
Subitems: [
{
id: "amin",
route: "/s",
icon: <SpaceDashboardIcon sx={{ width: "inherit", height: "inherit" }} />,
firstName: "amin",
lastName: "ali",
Subitems: [
{
id: "shahrokh",
shahrokh: "shahrokh",
type: "page",
selected: false,
route: "/dashbssoard",
icon: <AssessmentIcon sx={{ width: "inherit", height: "inherit" }} />,
},
{
id: "shasdasdsahrokh",
shahrokh: "shahroasdasdkh",
type: "page",
selected: false,
route: "/dashboardsd",
icon: <AirlineSeatReclineNormalIcon sx={{ width: "inherit", height: "inherit" }} />,
},
],
hasSubitems: true,
showSubitems: false,
type: "menu",
selected: false,
},
{
id: "amir",
route: "/dashboarsad",
icon: <RepartitionIcon sx={{ width: "inherit", height: "inherit" }} />,
firstName: "amir",
lastName: "akbar",
hasSubitems: false,
showSubitems: false,
selected: false,
type: "page",
},
],
hasSubitems: true,
showSubitems: false,
},
{
id: "hi",
type: "menu",
icon: <SecurityIcon sx={{ width: "inherit", height: "inherit" }} />,
route: "/hi",
selected: false,
Subitems: [
{
id: "ali",
route: "/dashboardss",
firstName: "ali",
lastName: "ali",
icon: <SecurityIcon sx={{ width: "inherit", height: "inherit" }} />,
hasSubitems: false,
showSubitems: false,
type: "page",
selected: false,
},
{
id: "akbar",
route: "/akbar",
firstName: "akbar",
icon: <SecurityIcon sx={{ width: "inherit", height: "inherit" }} />,
lastName: "akbar",
hasSubitems: false,
showSubitems: false,
type: "page",
selected: false,
},
],
hasSubitems: true,
showSubitems: false,
},
{
id: "hoo",
type: "page",
route: "/dashboard",
icon: <SecurityIcon sx={{ width: "inherit", height: "inherit" }} />,
selected: false,
hasSubitems: false,
showSubitems: false,
},
];
function selectPage(item, route) {
if (item.type === "page") {
return {
...item,
selected: item.route === route,
showSubitems: item.route === route,
};
} else if (item.Subitems && Array.isArray(item.Subitems)) {
const updatedSubitems = item.Subitems.map(subitem => selectPage(subitem, route));
return {
...item,
Subitems: updatedSubitems,
showSubitems: updatedSubitems.some(subitem => subitem.showSubitems || subitem.route === route),
};
}
return item;
}
function reducer(state, action) {
switch (action.type) {
case "UPDATE_MENU":
const _permissions = action.permissions || []
const filteredPageMenu = filterMenuItems(state, ['all', ..._permissions])
return filteredPageMenu
case "COLLAPSE_MENU":
return state.map((item) =>
action.id == item.id
? {
...item,
showSubitems: !item.showSubitems,
}
...item,
showSubitems: !item.showSubitems,
}
: item
);
case "COLLAPSE_SUB_ITEMS":
return state.map((item) => {
return item.hasSubitems
? {
...item,
Subitems: item.Subitems.map((subitem) =>
action.id === subitem.id
? {
...subitem,
showSubitems: !subitem.showSubitems,
}
: subitem
),
}
...item,
Subitems: item.Subitems.map((subitem) =>
action.id === subitem.id
? {
...subitem,
showSubitems: !subitem.showSubitems,
}
: subitem
),
}
: item;
});
case "COLLAPSE_SUB_SECOND_ITEMS":
return state.map((item) => {
return item.hasSubitems
? {
...item,
Subitems: item.Subitems.map((subitem) => {
return subitem.hasSubitems
? {
...subitem,
Subitems: subitem.Subitems.map((secondSubitem) =>
action.id === secondSubitem.id
? {
...secondSubitem,
showSubitems: !secondSubitem.showSubitems,
}
: secondSubitem
),
}
: subitem;
}),
}
...item,
Subitems: item.Subitems.map((subitem) => {
return subitem.hasSubitems
? {
...subitem,
Subitems: subitem.Subitems.map((secondSubitem) =>
action.id === secondSubitem.id
? {
...secondSubitem,
showSubitems: !secondSubitem.showSubitems,
}
: secondSubitem
),
}
: subitem;
}),
}
: item;
});
case "SELECTED":
return state.map((item) => {
return item.type === "page"
? {
...item,
selected: action.route === item.route,
showSubitems: item.route === action.route,
}
: item.Subitems && Array.isArray(item.Subitems)
? {
...item,
Subitems: item.Subitems.map((subitem) => {
return subitem.type === "page"
? {
...subitem,
selected: action.route === subitem.route,
showSubitems: subitem.route === action.route,
}
: subitem.Subitems && Array.isArray(subitem.Subitems)
? {
...subitem,
Subitems: subitem.Subitems.map((secondSubItem) => ({
...secondSubItem,
selected: secondSubItem.route === action.route,
})),
showSubitems: subitem.Subitems.some(
(secondSubItem) => secondSubItem.route === action.route
),
}
: subitem;
}),
showSubitems: item.Subitems.some((subitem) => subitem.showSubitems),
}
: item;
});
// case "SELECTED":
// return state.map((item) => {
// return item.type === "page" ? {
// ...item,
// selected: action.route === item.route
// } : item.Subitems && Array.isArray(item.Subitems) ? {
// ...item,
// Subitems: item.Subitems.map((subitem) => {
// const updatedSubitem = subitem.type === "page" ? {
// ...subitem,
// selected: action.route === subitem.route
// } : subitem.Subitems && Array.isArray(subitem.Subitems) ? {
// ...subitem,
// Subitems: subitem.Subitems.map((secondSubItem) => ({
// ...secondSubItem,
// selected: secondSubItem.route === action.route
// })),
// showSubitems: subitem.Subitems.some((secondSubItem) => secondSubItem.route === action.route),
// } : subitem;
//
// console.log("Updated subitem:", updatedSubitem); // Log the updated subitem
// return updatedSubitem;
// }),
// showSubitems: item.Subitems.some((subitem) => subitem.showSubitems),
// } : item
// });
return state.map(item => selectPage(item, action.route));
default:
throw new Error();
@@ -223,13 +88,21 @@ function reducer(state, action) {
}
const SidebarMenu = () => {
const [menuItems, dispatch] = useReducer(reducer, data);
const { data: userPermissions } = usePermissions()
const [menuItems, dispatch] = useReducer(reducer, pageMenu);
const pathname = usePathname();
const [selectedKey, setSelectedKey] = useState(null);
useEffect(() => {
dispatch({ type: "SELECTED", route: pathname });
setSelectedKey(pathname);
}, [pathname]);
}, [userPermissions, pathname]);
useEffect(() => {
if (!userPermissions) return
dispatch({ type: 'UPDATE_MENU', permissions: userPermissions });
}, [userPermissions])
useEffect(() => {
selectedKey &&
@@ -240,11 +113,13 @@ const SidebarMenu = () => {
}, [selectedKey]);
return (
<List disablePadding>
{menuItems.map((menuItem) => {
return <SidebarListItems dispatch={dispatch} key={menuItem.id} menuItem={menuItem} />;
})}
</List>
userPermissions && (
<List disablePadding dense>
{menuItems.map((menuItem) => {
return <SidebarListItems dispatch={dispatch} key={menuItem.id} menuItem={menuItem} />;
})}
</List>
)
);
};
export default SidebarMenu;

View File

@@ -1,82 +1,50 @@
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
import { ExpandLess, ExpandMore } from "@mui/icons-material";
import { Collapse, List, ListItem, ListItemButton, ListItemIcon, ListItemText } from "@mui/material";
import Link from "next/link";
const SidebarSubitems = ({ subitem, dispatch }) => {
return (
<>
<List disablePadding>
<ListItem disablePadding>
<ListItemButton
<ListItem disablePadding divider>
<ListItemButton
disableGutters
sx={{ py: 1, px: 0.5, pl: 1 }}
selected={subitem.selected}
component={subitem.type === "page" ? Link : null}
href={subitem.type === "page" ? subitem.route : null}
onClick={() => {
dispatch({ type: "COLLAPSE_SUB_ITEMS", id: subitem.id });
}}
>
<ListItemIcon
sx={{
"&.Mui-selected": {
backgroundColor: "rgba(0, 0, 0, 0.1)",
},
}}
selected={subitem.selected}
onClick={() => {
dispatch({ type: "COLLAPSE_SUB_ITEMS", id: subitem.id });
minWidth: 0,
justifyContent: "center",
width: 40,
height: 24,
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
color: "primary.main",
width: 40,
height: 24,
pr: 2,
}}
>
{subitem.icon}
</ListItemIcon>
<ListItemText primary={subitem.firstName} />
{subitem.hasSubitems ? subitem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
</ListItemButton>
</ListItem>
</List>
{subitem.hasSubitems
? subitem.Subitems.map((subSubitem, index) => {
return (
<Collapse
key={index}
in={subitem.showSubitems}
timeout="auto"
mountOnEnter={true}
unmountOnExit={true}
>
<List disablePadding>
<ListItem disablePadding>
<ListItemButton
onClick={() => {
dispatch({ type: "COLLAPSE_SUB_SECOND_ITEMS", id: subSubitem.id });
}}
selected={subSubitem.selected}
sx={{
"&.Mui-selected": {
backgroundColor: "rgba(0, 0, 0, 0.05)",
},
}}
>
<ListItemIcon
sx={{
minWidth: 0,
justifyContent: "center",
color: "primary.main",
width: 40,
height: 24,
pr: 2,
}}
>
{subSubitem.icon}
</ListItemIcon>
<ListItemText primary={subSubitem.shahrokh} />
</ListItemButton>
</ListItem>
</List>
</Collapse>
);
})
: null}
{subitem.icon}
</ListItemIcon>
<ListItemText primary={subitem.label} />
{subitem.hasSubitems ? subitem.showSubitems ? <ExpandLess /> : <ExpandMore /> : null}
</ListItemButton>
</ListItem>
<Collapse in={subitem.showSubitems} timeout="auto" mountOnEnter={true} unmountOnExit={true}>
{subitem.hasSubitems ? (
<List
disablePadding
dense
sx={{
background: "#00000008",
}}
>
{subitem.Subitems.map((subSubitem, index) => {
return <SidebarSubitems key={index} dispatch={dispatch} subitem={subSubitem} />;
})}
</List>
) : null}
</Collapse>
</>
);
};

View File

@@ -0,0 +1,187 @@
import { toast } from "react-toastify";
import { Box, Typography } from "@mui/material";
import { Dangerous } from "@mui/icons-material";
export const errorServerToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"The request failed due to an internal error."}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 5000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
export const errorUnauthorizedToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"The user is not authorized to make the request."}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
export const errorLogicToast = (message, toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorValidationToast = (message, toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorTooManyToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"Too many requests have been sent within a given time span."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorClientToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{
"The API request is invalid or improperly formed. Consequently, the API server could not understand the request."
}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);

View File

@@ -0,0 +1,33 @@
import { toast } from "react-toastify";
import { Box, Typography } from "@mui/material";
import { Beenhere } from "@mui/icons-material";
export const successToast = (toastContainer) =>
toast.success(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Beenhere color="success" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"Your operation was successful"}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);