From ad256ae6600796643034976e8e2dde17fab563bf Mon Sep 17 00:00:00 2001 From: AmirHossein Mahmoodi Date: Mon, 6 Nov 2023 14:17:54 +0330 Subject: [PATCH] LFFE-17 Implementation of loading for navigation pages dashboard --- public/locales/fa/app.json | 1 + .../layouts/Dashboard/Content/index.jsx | 65 +++++++++++++++++++ .../layouts/Dashboard/Sidebar/SidebarList.jsx | 40 ++++++++++-- .../Dashboard/Sidebar/SidebarListItem.jsx | 22 +++++-- .../Dashboard/Sidebar/SidebarListSubItem.jsx | 4 +- .../layouts/Dashboard/Sidebar/index.jsx | 37 ++++++----- src/components/layouts/Dashboard/index.jsx | 11 +--- src/core/components/LoadingHardPage.jsx | 31 +++++---- src/core/data/sidebarMenu.jsx | 32 ++++----- 9 files changed, 181 insertions(+), 62 deletions(-) create mode 100644 src/components/layouts/Dashboard/Content/index.jsx diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json index 9fd2984..7960a14 100644 --- a/public/locales/fa/app.json +++ b/public/locales/fa/app.json @@ -16,6 +16,7 @@ "between": "میان", "online_message": "شما به اینترنت وصل هستید", "offline_message": "اتصال شما به اینترنت قطع شده است", + "routing_to": "در حال انتقال به صفحه", "header": { "open_profile": "پروفایل", "edit_profile": " پروفایل", diff --git a/src/components/layouts/Dashboard/Content/index.jsx b/src/components/layouts/Dashboard/Content/index.jsx new file mode 100644 index 0000000..e3f39db --- /dev/null +++ b/src/components/layouts/Dashboard/Content/index.jsx @@ -0,0 +1,65 @@ +import LoadingHardPage from "@/core/components/LoadingHardPage"; +import RolePermissionMiddleware from "@/middlewares/RolePermission"; +import BreadCrumbs from "@/components/layouts/Dashboard/Breadcrumbs"; +import FullPageLayout from "@/layouts/FullPageLayout"; +import {useEffect, useMemo, useState} from "react"; +import sidebarMenu from "@/core/data/sidebarMenu"; +import {useRouter} from "next/router"; +import {useTranslations} from "next-intl"; + +const Content = (props) => { + const t = useTranslations() + const router = useRouter() + const [routing, setRouting] = useState(false) + const [routingItem, setRoutingItem] = useState({}) + const pageList = useMemo(() => { + const list = [] + for (const menu of sidebarMenu) { + for (const item of menu) { + if (item.type === 'menu') { + for (const subItem of item.subItem) { + list.push(subItem) + } + } else { + list.push(item) + } + } + } + + return list + }, []) + + useEffect(() => { + const handlerStartRoute = (url) => { + setRoutingItem(pageList.find(page => page.route === url)) + setRouting(true) + } + const handlerCompleteRoute = () => { + setRouting(false) + } + + router.events.on('routeChangeStart', handlerStartRoute) + router.events.on('routeChangeComplete', handlerCompleteRoute) + + return () => { + router.events.off('routeChangeStart', handlerStartRoute) + router.events.off('routeChangeComplete', handlerCompleteRoute) + } + }, [router]); + + return ( + + + + + {props.children} + + + + ) +} + +export default Content \ No newline at end of file diff --git a/src/components/layouts/Dashboard/Sidebar/SidebarList.jsx b/src/components/layouts/Dashboard/Sidebar/SidebarList.jsx index 265da6c..3a2eb44 100644 --- a/src/components/layouts/Dashboard/Sidebar/SidebarList.jsx +++ b/src/components/layouts/Dashboard/Sidebar/SidebarList.jsx @@ -1,5 +1,5 @@ import {Divider, List} from "@mui/material"; -import {Fragment, useEffect, useReducer, useRef, useState} from "react"; +import {Fragment, useEffect, useReducer, useState} from "react"; import SidebarListItem from "./SidebarListItem"; import sidebarMenu from "@/core/data/sidebarMenu"; import {useRouter} from "next/router"; @@ -10,20 +10,41 @@ function reducer(state, action) { case "COLLAPSE_MENU": return state.map((itemsArr) => itemsArr.map((item) => - action.key === item.key ? { ...item, showSubItem: !item.showSubItem } : item + action.key === item.key ? {...item, showSubItem: !item.showSubItem} : item ) ); case "SELECTED": return state.map((itemsArr) => itemsArr.map((item) => { return item.type === "page" - ? { ...item, selected: action.route === item.route } + ? {...item, selected: action.route === item.route, routing: false} : item.subItem && Array.isArray(item.subItem) ? { ...item, subItem: item.subItem.map((subitem) => ({ ...subitem, selected: subitem.route === action.route, + routing: false + })), + showSubItem: item.subItem.some( + (subitem) => subitem.selected + ), + } + : item; + }) + ); + case "SELECTING": + return state.map((itemsArr) => + itemsArr.map((item) => { + return item.type === "page" + ? {...item, selected: action.route === item.route, routing: action.route === item.route} + : item.subItem && Array.isArray(item.subItem) + ? { + ...item, + subItem: item.subItem.map((subitem) => ({ + ...subitem, + selected: subitem.route === action.route, + routing: subitem.route === action.route })), showSubItem: item.subItem.some( (subitem) => subitem.selected @@ -46,7 +67,16 @@ export default function SidebarList({handleDrawerToggle}) { useEffect(() => { dispatch({type: "SELECTED", route: router.pathname}); setSelectedKey(router.pathname); - }, [router.pathname]); + const handlerStartRoute = (url) => { + dispatch({type: "SELECTING", route: url}); + } + + router.events.on('routeChangeStart', handlerStartRoute) + + return () => { + router.events.off('routeChangeStart', handlerStartRoute) + } + }, [router]); useEffect(() => { @@ -57,7 +87,7 @@ export default function SidebarList({handleDrawerToggle}) { }, [selectedKey]); return ( - + {itemMenu.map((itemArr, index) => ( {itemArr.map((item) => diff --git a/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx b/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx index e9657a9..81fd444 100644 --- a/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx +++ b/src/components/layouts/Dashboard/Sidebar/SidebarListItem.jsx @@ -1,7 +1,16 @@ import {NextLinkComposed} from "@/core/components/LinkRouting"; import ExpandLess from "@mui/icons-material/ExpandLess"; import ExpandMore from "@mui/icons-material/ExpandMore"; -import {Badge, IconButton, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material"; +import { + Badge, + CircularProgress, + IconButton, + ListItem, + ListItemButton, + ListItemIcon, + ListItemText, + Typography, +} from "@mui/material"; import {useTranslations} from "next-intl"; import {Fragment} from "react"; import SidebarListSubItem from "./SidebarListSubItem"; @@ -9,7 +18,7 @@ import useNotification from "@/lib/app/hooks/useNotification"; const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => { const t = useTranslations(); - const { notification_count } = useNotification(); + const {notification_count} = useNotification(); const hasSubItems = item.type === "menu" && item.subItem && item.subItem.length > 0; const renderBadge = () => { return !hasSubItems ? ( @@ -40,7 +49,7 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => { })} onClick={() => { if (hasSubItems) { - dispatch({ type: "COLLAPSE_MENU", key: item.key }); + dispatch({type: "COLLAPSE_MENU", key: item.key}); } }} sx={{ @@ -53,10 +62,13 @@ const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => { minWidth: 0, justifyContent: "center", color: "primary.main", + width: 40, + height: 24, pr: 2, }} > - {item.icon} + {item.routing ? + : item.icon} { } /> - {hasSubItems && (item.showSubItem ? : )} + {hasSubItems && (item.showSubItem ? : )} {item.subItem && ( diff --git a/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx b/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx index d663d2c..0543d8c 100644 --- a/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx +++ b/src/components/layouts/Dashboard/Sidebar/SidebarListSubItem.jsx @@ -13,7 +13,7 @@ import { import {useTranslations} from "next-intl"; import useNotification from "@/lib/app/hooks/useNotification"; -const SidebarListSubItem = ({item, handleDrawerToggle }) => { +const SidebarListSubItem = ({item, handleDrawerToggle}) => { const t = useTranslations(); const {notification_count} = useNotification(); const renderBadge = (subitem) => ( @@ -50,6 +50,8 @@ const SidebarListSubItem = ({item, handleDrawerToggle }) => { sx={{ minWidth: 0, justifyContent: "center", + width: 40, + height: 24, pr: 2, }} > diff --git a/src/components/layouts/Dashboard/Sidebar/index.jsx b/src/components/layouts/Dashboard/Sidebar/index.jsx index bdab3a2..27f2d0d 100644 --- a/src/components/layouts/Dashboard/Sidebar/index.jsx +++ b/src/components/layouts/Dashboard/Sidebar/index.jsx @@ -1,13 +1,31 @@ -import {Box, Drawer} from "@mui/material"; +import {Box, Drawer, useMediaQuery} from "@mui/material"; import SidebarDrawer from "./SidebarDrawer"; +import {useTheme} from "@mui/material/styles"; const Sidebar = (props) => { + const theme = useTheme(); + const isUpSm = useMediaQuery((theme.breakpoints.up('sm'))) return ( + > {isUpSm ? ( + + + + ) : ( { > - - - + )} ); }; diff --git a/src/components/layouts/Dashboard/index.jsx b/src/components/layouts/Dashboard/index.jsx index 953dd3c..ef3f3bd 100644 --- a/src/components/layouts/Dashboard/index.jsx +++ b/src/components/layouts/Dashboard/index.jsx @@ -1,10 +1,9 @@ import {useState} from "react"; import {Toolbar} from "@mui/material"; import FullPageLayout from "@/layouts/FullPageLayout"; -import RolePermissionMiddleware from "@/middlewares/RolePermission"; import Header from "@/components/layouts/Dashboard/Header"; import Sidebar from "@/components/layouts/Dashboard/Sidebar"; -import BreadCrumbs from "@/components/layouts/Dashboard/Breadcrumbs"; +import Content from "@/components/layouts/Dashboard/Content"; const drawerWidth = 240; @@ -17,6 +16,7 @@ const DashboardLayouts = (props) => { const handleDrawerToggle = () => { setMobileOpen(!mobileOpen); }; + return (
{ sx={{flexGrow: 1, width: {sm: `calc(100% - ${drawerWidth}px)`}}} > - - - - {props.children} - - + ); diff --git a/src/core/components/LoadingHardPage.jsx b/src/core/components/LoadingHardPage.jsx index c3b24d6..59e4a02 100644 --- a/src/core/components/LoadingHardPage.jsx +++ b/src/core/components/LoadingHardPage.jsx @@ -1,4 +1,4 @@ -import {Backdrop, Box, styled} from "@mui/material"; +import {Backdrop, Box, Stack, styled, Typography} from "@mui/material"; import SvgLoading from "@/core/components/svgs/SvgLoading"; const LoadingImage = styled(Box)({ @@ -9,7 +9,7 @@ const LoadingImage = styled(Box)({ }, "50%": { // opacity: 1, - transform: "scale(2)", + transform: "scale(.5)", }, "100%": { // opacity: 0, @@ -19,20 +19,29 @@ const LoadingImage = styled(Box)({ animation: "load 2s infinite", }); -const LoadingHardPage = ({children, loading}) => { +const LoadingHardPage = ({children, loading, sx = {}, icon = null, width = 200, height = 200, label = ''}) => { return ( <> theme.zIndex.drawer + 1}} + sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1, ...sx}} open={loading} > - - - + + + {icon ? ( + + {icon} + + ) : ( + + )} + + {label} + {children} diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx index db8e0b8..c54bbca 100644 --- a/src/core/data/sidebarMenu.jsx +++ b/src/core/data/sidebarMenu.jsx @@ -20,7 +20,7 @@ const sidebarMenu = [ key: "sidebar.dashboard", type: "page", route: "/dashboard", - icon: , + icon: , selected: false, permission: "all", }, @@ -30,7 +30,7 @@ const sidebarMenu = [ name: "passenger_office_chief", type: "page", route: "/dashboard/passenger-office-chief", - icon: , + icon: , selected: false, permission: "manage_passenger_office_navgan", }, @@ -39,7 +39,7 @@ const sidebarMenu = [ name: "machinery_expert", type: "page", route: "/dashboard/machinery-expert", - icon: , + icon: , selected: false, permission: "manage_machinery_navgan", }, @@ -49,7 +49,7 @@ const sidebarMenu = [ name: "province_working_group", type: "page", route: "/dashboard/passenger-boss", - icon: , + icon: , selected: false, permission: "manage_province_working_group_navgan", }, @@ -59,7 +59,7 @@ const sidebarMenu = [ name: "transportation_assistant", type: "page", route: "/dashboard/transportation-assistant", - icon: , + icon: , selected: false, permission: "manage_transportation_navgan", }, @@ -69,7 +69,7 @@ const sidebarMenu = [ name: "province_manager_navgan", type: "page", route: "/dashboard/navgan-province-manager", - icon: , + icon: , selected: false, permission: "manage_province_affairs_navgan", }, @@ -78,7 +78,7 @@ const sidebarMenu = [ name: "province_head_expert", type: "page", route: "/dashboard/province-head-expert", - icon: , + icon: , selected: false, permission: "manage_province_headquarter_refahi", }, @@ -87,7 +87,7 @@ const sidebarMenu = [ name: "inspector_expert", type: "page", route: "/dashboard/inspector-expert", - icon: , + icon: , selected: false, permission: "manage_inspector_refahi", }, @@ -96,7 +96,7 @@ const sidebarMenu = [ name: "commercial_chief", type: "page", route: "/dashboard/commercial-chief", - icon: , + icon: , selected: false, permission: "manage_commercial_refahi", }, @@ -105,7 +105,7 @@ const sidebarMenu = [ name: "development_assistant", type: "page", route: "/dashboard/development-assistant", - icon: , + icon: , selected: false, permission: "manage_development_refahi", }, @@ -115,7 +115,7 @@ const sidebarMenu = [ name: "province_manager_refahi", type: "page", route: "/dashboard/refahi-province-manager", - icon: , + icon: , selected: false, permission: "manage_province_affairs_refahi", }, @@ -125,7 +125,7 @@ const sidebarMenu = [ name: "refahi_loan_management", type: "page", route: "/dashboard/refahi-loan-management", - icon: , + icon: , selected: false, permission: "manage_refahi_loan", }, @@ -135,7 +135,7 @@ const sidebarMenu = [ name: "navgan_loan_management", type: "page", route: "/dashboard/navgan-loan-management", - icon: , + icon: , selected: false, permission: "manage_navgan_loan", }, @@ -144,7 +144,7 @@ const sidebarMenu = [ name: "expert_management", type: "page", route: "/dashboard/expert-management", - icon: , + icon: , selected: false, permission: "manage_navgan_loan", }, @@ -153,7 +153,7 @@ const sidebarMenu = [ name: "user_management", type: "page", route: "/dashboard/user-management", - icon: , + icon: , selected: false, permission: "manage_users", }, @@ -162,7 +162,7 @@ const sidebarMenu = [ name: "role_management", type: "page", route: "/dashboard/role-management", - icon: , + icon: , selected: false, permission: "manage_roles", },