@campxdev/react-blueprint 2.3.7 → 2.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/AmenitiesIcon.d.ts +2 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/BoardingPointsIcon.d.ts +3 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/BusesIcon.d.ts +3 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/GatePassIcon.d.ts +2 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/RouteBusAssignmentIcon.d.ts +3 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/TransportRegistrationsIcon.d.ts +3 -0
- package/dist/cjs/types/src/components/Assets/Icons/IconComponents/TransportRoutesIcon.d.ts +3 -0
- package/dist/cjs/types/src/components/Assets/Icons/Icons.d.ts +7 -0
- package/dist/cjs/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
- package/dist/cjs/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
- package/dist/cjs/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
- package/dist/cjs/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
- package/dist/cjs/types/src/components/Layout/AppLayout/types.d.ts +7 -0
- package/dist/esm/index.js +2 -2
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/AmenitiesIcon.d.ts +2 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/BoardingPointsIcon.d.ts +3 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/BusesIcon.d.ts +3 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/GatePassIcon.d.ts +2 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/RouteBusAssignmentIcon.d.ts +3 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/TransportRegistrationsIcon.d.ts +3 -0
- package/dist/esm/types/src/components/Assets/Icons/IconComponents/TransportRoutesIcon.d.ts +3 -0
- package/dist/esm/types/src/components/Assets/Icons/Icons.d.ts +7 -0
- package/dist/esm/types/src/components/Layout/AppLayout/components/AppBar.d.ts +4 -3
- package/dist/esm/types/src/components/Layout/AppLayout/components/PersistentSidebar.d.ts +14 -0
- package/dist/esm/types/src/components/Layout/AppLayout/components/Sidebar/interfaces.d.ts +2 -0
- package/dist/esm/types/src/components/Layout/AppLayout/components/UserProfilePopup.d.ts +3 -2
- package/dist/esm/types/src/components/Layout/AppLayout/types.d.ts +7 -0
- package/dist/index.d.ts +55 -40
- package/package.json +1 -1
- package/src/App.tsx +9 -37
- package/src/components/Assets/Icons/IconComponents/AmenitiesIcon.tsx +50 -0
- package/src/components/Assets/Icons/IconComponents/BoardingPointsIcon.tsx +65 -0
- package/src/components/Assets/Icons/IconComponents/BusesIcon.tsx +58 -0
- package/src/components/Assets/Icons/IconComponents/GatePassIcon.tsx +50 -0
- package/src/components/Assets/Icons/IconComponents/RouteBusAssignmentIcon.tsx +65 -0
- package/src/components/Assets/Icons/IconComponents/TransportRegistrationsIcon.tsx +65 -0
- package/src/components/Assets/Icons/IconComponents/TransportRoutesIcon.tsx +65 -0
- package/src/components/Assets/Icons/Icons.tsx +21 -0
- package/src/components/Layout/AppLayout/AppLayout.tsx +61 -20
- package/src/components/Layout/AppLayout/components/AppBar.tsx +35 -49
- package/src/components/Layout/AppLayout/components/PersistentSidebar.tsx +171 -0
- package/src/components/Layout/AppLayout/components/Sidebar/MenuBar.tsx +8 -4
- package/src/components/Layout/AppLayout/components/Sidebar/MenuItem.tsx +123 -46
- package/src/components/Layout/AppLayout/components/Sidebar/interfaces.ts +2 -0
- package/src/components/Layout/AppLayout/components/Sidebar/styles.ts +0 -2
- package/src/components/Layout/AppLayout/components/UserProfilePopup.tsx +42 -12
- package/src/components/Layout/AppLayout/types.ts +9 -0
- package/src/components/Layout/PageHeader/components/Views/Views.tsx +3 -2
- package/src/components/Navigation/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/components/Navigation/Sidebar/SidebarV2.tsx +1 -1
- package/src/themes/colorTokens/darkColorTokens.tsx +1 -1
- package/src/themes/colorTokens/lightColorTokens.ts +1 -1
- package/src/themes/commonTheme.ts +1 -1
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Box,
|
|
3
|
+
IconButton,
|
|
4
|
+
Stack,
|
|
5
|
+
styled,
|
|
6
|
+
useMediaQuery,
|
|
7
|
+
useTheme,
|
|
8
|
+
} from '@mui/material';
|
|
9
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
10
|
+
import React, { useState } from 'react';
|
|
11
|
+
import { CampxFullLogoIconV2 } from '../../../Assets/Icons/IconComponents/CampxFullLogoIconV2';
|
|
12
|
+
import { CampxIconV2 } from '../../../Assets/Icons/IconComponents/CampxIconV2';
|
|
13
|
+
import { Icons } from '../../../export';
|
|
14
|
+
import { MenuBar } from './Sidebar/MenuBar';
|
|
15
|
+
import { SideMenuItemProps } from './Sidebar/interfaces';
|
|
16
|
+
import { useSidebarNavigation } from './Sidebar/useSidebarNavigation';
|
|
17
|
+
import { UserProfilePopup, UserProfilePopupProps } from './UserProfilePopup';
|
|
18
|
+
|
|
19
|
+
interface PersistentSidebarProps {
|
|
20
|
+
/** Menu items for navigation */
|
|
21
|
+
menu: SideMenuItemProps[];
|
|
22
|
+
|
|
23
|
+
userProfileParams: UserProfilePopupProps;
|
|
24
|
+
/** Whether the sidebar is collapsed */
|
|
25
|
+
collapsed: boolean;
|
|
26
|
+
/** Function to toggle sidebar collapse state */
|
|
27
|
+
onToggle: () => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const PersistentSidebar: React.FC<PersistentSidebarProps> = ({
|
|
31
|
+
menu,
|
|
32
|
+
userProfileParams,
|
|
33
|
+
collapsed,
|
|
34
|
+
onToggle,
|
|
35
|
+
}) => {
|
|
36
|
+
const theme = useTheme();
|
|
37
|
+
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
|
38
|
+
const [hovered, setHovered] = useState(false);
|
|
39
|
+
// Use the navigation hook
|
|
40
|
+
const navigation = useSidebarNavigation(menu);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<>
|
|
44
|
+
{/* Mobile overlay backdrop */}
|
|
45
|
+
<AnimatePresence>
|
|
46
|
+
{!collapsed && isSmallScreen && (
|
|
47
|
+
<motion.div
|
|
48
|
+
initial={{ opacity: 0 }}
|
|
49
|
+
animate={{ opacity: 1 }}
|
|
50
|
+
exit={{ opacity: 0 }}
|
|
51
|
+
transition={{ duration: 0.2 }}
|
|
52
|
+
style={{
|
|
53
|
+
position: 'fixed',
|
|
54
|
+
top: 0,
|
|
55
|
+
left: 0,
|
|
56
|
+
right: 0,
|
|
57
|
+
bottom: 0,
|
|
58
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
59
|
+
zIndex: 1299,
|
|
60
|
+
}}
|
|
61
|
+
onClick={onToggle}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</AnimatePresence>
|
|
65
|
+
|
|
66
|
+
{/* Persistent Sidebar */}
|
|
67
|
+
<motion.div
|
|
68
|
+
animate={{
|
|
69
|
+
width: collapsed ? '64px' : '250px',
|
|
70
|
+
x: isSmallScreen && collapsed ? '-100%' : '0%',
|
|
71
|
+
}}
|
|
72
|
+
transition={{ duration: 0.3, ease: [0.32, 0.72, 0, 1] }}
|
|
73
|
+
style={{
|
|
74
|
+
position: isSmallScreen ? 'fixed' : 'relative',
|
|
75
|
+
zIndex: isSmallScreen ? 1300 : 1,
|
|
76
|
+
height: '100vh',
|
|
77
|
+
flexShrink: 0,
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<SidebarContainer>
|
|
81
|
+
{/* Sidebar Header */}
|
|
82
|
+
<Stack
|
|
83
|
+
direction="row"
|
|
84
|
+
justifyContent="space-between"
|
|
85
|
+
alignItems="center"
|
|
86
|
+
sx={{
|
|
87
|
+
height: '64px',
|
|
88
|
+
padding: collapsed ? '0' : '0 16px',
|
|
89
|
+
[theme.breakpoints.down('md')]: {
|
|
90
|
+
height: '54px',
|
|
91
|
+
},
|
|
92
|
+
}}
|
|
93
|
+
>
|
|
94
|
+
{/* Logo - Show icon when collapsed, full logo when expanded */}
|
|
95
|
+
{collapsed ? (
|
|
96
|
+
<IconButton
|
|
97
|
+
onClick={() => {
|
|
98
|
+
setHovered(false);
|
|
99
|
+
onToggle();
|
|
100
|
+
}}
|
|
101
|
+
onMouseEnter={() => setHovered(true)}
|
|
102
|
+
onMouseLeave={() => setHovered(false)}
|
|
103
|
+
sx={{
|
|
104
|
+
width: '64px',
|
|
105
|
+
height: '64px',
|
|
106
|
+
borderRadius: 0,
|
|
107
|
+
[theme.breakpoints.down('md')]: {
|
|
108
|
+
height: '54px',
|
|
109
|
+
width: '54px',
|
|
110
|
+
},
|
|
111
|
+
':hover': { cursor: 'e-resize' },
|
|
112
|
+
}}
|
|
113
|
+
>
|
|
114
|
+
{hovered ? <Icons.RightIcon size={24} /> : <CampxIconV2 />}
|
|
115
|
+
</IconButton>
|
|
116
|
+
) : (
|
|
117
|
+
<>
|
|
118
|
+
<CampxFullLogoIconV2 />
|
|
119
|
+
<IconButton onClick={onToggle}>
|
|
120
|
+
<Icons.LeftIcon size={20} />
|
|
121
|
+
</IconButton>
|
|
122
|
+
</>
|
|
123
|
+
)}
|
|
124
|
+
</Stack>
|
|
125
|
+
|
|
126
|
+
{/* Menu Content */}
|
|
127
|
+
<motion.div
|
|
128
|
+
key={`sidebar-${navigation.currentMenuState.title || 'main'}`}
|
|
129
|
+
initial={{ x: navigation.menuPosition }}
|
|
130
|
+
animate={{ x: 0 }}
|
|
131
|
+
transition={{
|
|
132
|
+
duration: 0.3,
|
|
133
|
+
ease: navigation.menuPosition ? 'circOut' : 'circIn',
|
|
134
|
+
}}
|
|
135
|
+
style={{
|
|
136
|
+
height: `calc(100% - 116px)`,
|
|
137
|
+
width: '100%',
|
|
138
|
+
}}
|
|
139
|
+
>
|
|
140
|
+
<MenuBar
|
|
141
|
+
currentMenuState={navigation.currentMenuState}
|
|
142
|
+
menuPosition={navigation.menuPosition}
|
|
143
|
+
internalMenuClickHandler={navigation.internalMenuClickHandler}
|
|
144
|
+
previousMenuClickHandler={navigation.previousMenuClickHandler}
|
|
145
|
+
onClose={isSmallScreen ? onToggle : undefined}
|
|
146
|
+
collapsed={collapsed}
|
|
147
|
+
/>
|
|
148
|
+
</motion.div>
|
|
149
|
+
<Box sx={{ position: 'fixed', bottom: 0, left: 0 }}>
|
|
150
|
+
<UserProfilePopup
|
|
151
|
+
userFullName={userProfileParams?.userFullName}
|
|
152
|
+
designation={userProfileParams?.designation}
|
|
153
|
+
onLogout={userProfileParams?.onLogout}
|
|
154
|
+
onAccountClick={userProfileParams?.onAccountClick}
|
|
155
|
+
profileActions={userProfileParams?.profileActions}
|
|
156
|
+
collapsed={collapsed}
|
|
157
|
+
/>
|
|
158
|
+
</Box>
|
|
159
|
+
</SidebarContainer>
|
|
160
|
+
</motion.div>
|
|
161
|
+
</>
|
|
162
|
+
);
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const SidebarContainer = styled(Stack)(({ theme }: { theme?: any }) => ({
|
|
166
|
+
height: '100%',
|
|
167
|
+
backgroundColor: theme.palette.surface.paperBackground,
|
|
168
|
+
flexDirection: 'column',
|
|
169
|
+
overflow: 'hidden',
|
|
170
|
+
borderRight: `1px solid ${theme.palette.divider}`,
|
|
171
|
+
}));
|
|
@@ -23,19 +23,22 @@ export const MenuBar: React.FC<MenuBarProps> = ({
|
|
|
23
23
|
internalMenuClickHandler,
|
|
24
24
|
previousMenuClickHandler,
|
|
25
25
|
onClose,
|
|
26
|
+
collapsed,
|
|
26
27
|
}) => {
|
|
27
28
|
return (
|
|
28
29
|
<MenuBarContainer>
|
|
29
30
|
{currentMenuState.title && (
|
|
30
31
|
<MenuHeaderContainer
|
|
31
32
|
direction="row"
|
|
32
|
-
justifyContent=
|
|
33
|
+
justifyContent={collapsed ? 'center' : 'flex-start'}
|
|
33
34
|
onClick={previousMenuClickHandler}
|
|
34
35
|
>
|
|
35
36
|
<Icons.ArrowBackIcon size={20} />
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
37
|
+
{!collapsed && (
|
|
38
|
+
<Typography variant="button1" sx={{ ml: 1 }}>
|
|
39
|
+
{currentMenuState.title}
|
|
40
|
+
</Typography>
|
|
41
|
+
)}
|
|
39
42
|
</MenuHeaderContainer>
|
|
40
43
|
)}
|
|
41
44
|
|
|
@@ -53,6 +56,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({
|
|
|
53
56
|
currentMenuPath={currentMenuState.path}
|
|
54
57
|
internalMenuClickHandler={internalMenuClickHandler}
|
|
55
58
|
onClose={onClose}
|
|
59
|
+
collapsed={collapsed}
|
|
56
60
|
/>
|
|
57
61
|
))}
|
|
58
62
|
</motion.div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Stack, Typography } from '@mui/material';
|
|
1
|
+
import { Stack, Tooltip, Typography } from '@mui/material';
|
|
2
2
|
import { motion } from 'framer-motion';
|
|
3
3
|
import { useState } from 'react';
|
|
4
4
|
import { useMatch, useResolvedPath } from 'react-router-dom';
|
|
@@ -21,6 +21,7 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
21
21
|
currentMenuPath,
|
|
22
22
|
internalMenuClickHandler,
|
|
23
23
|
onClose,
|
|
24
|
+
collapsed,
|
|
24
25
|
}) => {
|
|
25
26
|
const { name, path, icon, menu: internalMenu, subMenu } = menuItem;
|
|
26
27
|
const newPath = currentMenuPath ? `${currentMenuPath}${path}` : path;
|
|
@@ -41,9 +42,6 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
41
42
|
|
|
42
43
|
// Smart drawer closing logic
|
|
43
44
|
const shouldCloseDrawer = (item: typeof menuItem) => {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
45
|
// For desktop, only close if it's a leaf node (no children)
|
|
48
46
|
return !item.menu && !item.subMenu;
|
|
49
47
|
};
|
|
@@ -56,16 +54,22 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
56
54
|
|
|
57
55
|
// Internal menu item (has nested menu)
|
|
58
56
|
if (internalMenu && internalMenu.length > 0) {
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
const content = (
|
|
58
|
+
<MenuItemContainer disablePadding>
|
|
59
|
+
<SubMenuContainer
|
|
60
|
+
match={!!match}
|
|
61
|
+
onClick={handleInternalMenuClick}
|
|
62
|
+
sx={{ width: collapsed ? 'max-content' : '100%' }}
|
|
63
|
+
>
|
|
64
|
+
<MenuItemButton
|
|
65
|
+
sx={{
|
|
66
|
+
justifyContent: collapsed ? 'center' : 'flex-start',
|
|
67
|
+
padding: collapsed ? '8px' : '5px 8px',
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
{collapsed ? (
|
|
71
|
+
<MenuItemIcon sx={{ margin: 0 }}>{icon}</MenuItemIcon>
|
|
72
|
+
) : (
|
|
69
73
|
<Stack direction="row" alignItems="center" width="100%">
|
|
70
74
|
<Stack direction="row" alignItems="center" flex={1}>
|
|
71
75
|
<MenuItemIcon>{icon}</MenuItemIcon>
|
|
@@ -75,15 +79,12 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
75
79
|
<Icons.RedoIcon size={18} />
|
|
76
80
|
</HoverIcon>
|
|
77
81
|
</Stack>
|
|
78
|
-
|
|
79
|
-
</
|
|
80
|
-
</
|
|
81
|
-
</
|
|
82
|
+
)}
|
|
83
|
+
</MenuItemButton>
|
|
84
|
+
</SubMenuContainer>
|
|
85
|
+
</MenuItemContainer>
|
|
82
86
|
);
|
|
83
|
-
}
|
|
84
87
|
|
|
85
|
-
// Sub menu item (has expandable sub items)
|
|
86
|
-
if (subMenu && subMenu.length > 0) {
|
|
87
88
|
return (
|
|
88
89
|
<motion.div
|
|
89
90
|
key={`submenu-${index}`}
|
|
@@ -91,28 +92,56 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
91
92
|
animate={{ opacity: 1 }}
|
|
92
93
|
transition={{ duration: 1 }}
|
|
93
94
|
>
|
|
95
|
+
{collapsed ? (
|
|
96
|
+
<Tooltip title={name} placement="right">
|
|
97
|
+
{content}
|
|
98
|
+
</Tooltip>
|
|
99
|
+
) : (
|
|
100
|
+
content
|
|
101
|
+
)}
|
|
102
|
+
</motion.div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Sub menu item (has expandable sub items)
|
|
107
|
+
if (subMenu && subMenu.length > 0) {
|
|
108
|
+
const content = (
|
|
109
|
+
<>
|
|
94
110
|
<MenuItemContainer disablePadding>
|
|
95
|
-
<SubMenuContainer
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
<
|
|
108
|
-
|
|
111
|
+
<SubMenuContainer
|
|
112
|
+
match={!!match}
|
|
113
|
+
onClick={handleSubMenuToggle}
|
|
114
|
+
sx={{ width: collapsed ? 'max-content' : '100%' }}
|
|
115
|
+
>
|
|
116
|
+
<MenuItemButton
|
|
117
|
+
sx={{
|
|
118
|
+
justifyContent: collapsed ? 'center' : 'flex-start',
|
|
119
|
+
padding: collapsed ? '8px' : '5px 8px',
|
|
120
|
+
}}
|
|
121
|
+
>
|
|
122
|
+
{collapsed ? (
|
|
123
|
+
<MenuItemIcon sx={{ margin: 0 }}>{icon}</MenuItemIcon>
|
|
124
|
+
) : (
|
|
125
|
+
<Stack
|
|
126
|
+
direction="row"
|
|
127
|
+
alignItems="center"
|
|
128
|
+
width="100%"
|
|
129
|
+
justifyContent="space-between"
|
|
130
|
+
>
|
|
131
|
+
<Stack direction="row" alignItems="center">
|
|
132
|
+
<MenuItemIcon>{icon}</MenuItemIcon>
|
|
133
|
+
<Typography variant="button1">{name}</Typography>
|
|
134
|
+
</Stack>
|
|
135
|
+
<Stack>
|
|
136
|
+
{expanded ? <Icons.CollapseIcon /> : <Icons.ExpandIcon />}
|
|
137
|
+
</Stack>
|
|
109
138
|
</Stack>
|
|
110
|
-
|
|
139
|
+
)}
|
|
111
140
|
</MenuItemButton>
|
|
112
141
|
</SubMenuContainer>
|
|
113
142
|
</MenuItemContainer>
|
|
114
143
|
|
|
115
|
-
{expanded && (
|
|
144
|
+
{expanded && !collapsed && (
|
|
116
145
|
<motion.div
|
|
117
146
|
initial={{ height: 0, opacity: 0 }}
|
|
118
147
|
animate={{ height: 'auto', opacity: 1 }}
|
|
@@ -132,11 +161,55 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
132
161
|
</SubMenuItemContainer>
|
|
133
162
|
</motion.div>
|
|
134
163
|
)}
|
|
164
|
+
</>
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<motion.div
|
|
169
|
+
key={`submenu-${index}`}
|
|
170
|
+
initial={{ opacity: 0 }}
|
|
171
|
+
animate={{ opacity: 1 }}
|
|
172
|
+
transition={{ duration: 1 }}
|
|
173
|
+
>
|
|
174
|
+
{collapsed ? (
|
|
175
|
+
<Tooltip title={name} placement="right">
|
|
176
|
+
<div>{content}</div>
|
|
177
|
+
</Tooltip>
|
|
178
|
+
) : (
|
|
179
|
+
content
|
|
180
|
+
)}
|
|
135
181
|
</motion.div>
|
|
136
182
|
);
|
|
137
183
|
}
|
|
138
184
|
|
|
139
185
|
// Regular menu item (direct link)
|
|
186
|
+
const regularContent = (
|
|
187
|
+
<MenuItemContainer disablePadding>
|
|
188
|
+
<MenuLink
|
|
189
|
+
to={newPath}
|
|
190
|
+
match={match}
|
|
191
|
+
onClick={handleNavigationClick}
|
|
192
|
+
sx={{ width: collapsed ? 'max-content' : '100%' }}
|
|
193
|
+
>
|
|
194
|
+
<MenuItemButton
|
|
195
|
+
sx={{
|
|
196
|
+
justifyContent: collapsed ? 'center' : 'flex-start',
|
|
197
|
+
padding: collapsed ? '8px' : '5px 8px',
|
|
198
|
+
}}
|
|
199
|
+
>
|
|
200
|
+
{collapsed ? (
|
|
201
|
+
<MenuItemIcon sx={{ margin: 0 }}>{icon}</MenuItemIcon>
|
|
202
|
+
) : (
|
|
203
|
+
<>
|
|
204
|
+
<MenuItemIcon>{icon}</MenuItemIcon>
|
|
205
|
+
<Typography variant="button1">{name}</Typography>
|
|
206
|
+
</>
|
|
207
|
+
)}
|
|
208
|
+
</MenuItemButton>
|
|
209
|
+
</MenuLink>
|
|
210
|
+
</MenuItemContainer>
|
|
211
|
+
);
|
|
212
|
+
|
|
140
213
|
return (
|
|
141
214
|
<motion.div
|
|
142
215
|
key={`regular-${index}`}
|
|
@@ -144,14 +217,13 @@ export const MenuItem: React.FC<MenuItemProps> = ({
|
|
|
144
217
|
animate={{ opacity: 1 }}
|
|
145
218
|
transition={{ duration: 1 }}
|
|
146
219
|
>
|
|
147
|
-
|
|
148
|
-
<
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
</MenuItemContainer>
|
|
220
|
+
{collapsed ? (
|
|
221
|
+
<Tooltip title={name} placement="right">
|
|
222
|
+
{regularContent}
|
|
223
|
+
</Tooltip>
|
|
224
|
+
) : (
|
|
225
|
+
regularContent
|
|
226
|
+
)}
|
|
155
227
|
</motion.div>
|
|
156
228
|
);
|
|
157
229
|
};
|
|
@@ -178,7 +250,12 @@ const SubMenuItem: React.FC<{
|
|
|
178
250
|
|
|
179
251
|
return (
|
|
180
252
|
<MenuItemContainer key={index} disablePadding>
|
|
181
|
-
<MenuLink
|
|
253
|
+
<MenuLink
|
|
254
|
+
to={newPath}
|
|
255
|
+
match={match}
|
|
256
|
+
sx={{ margin: '5px 8px 5px 16px' }}
|
|
257
|
+
onClick={handleSubMenuNavigationClick}
|
|
258
|
+
>
|
|
182
259
|
<MenuItemButton>
|
|
183
260
|
<Typography variant="button1">{name}</Typography>
|
|
184
261
|
</MenuItemButton>
|
|
@@ -48,6 +48,7 @@ export interface MenuItemProps {
|
|
|
48
48
|
currentMenuPath: string | null;
|
|
49
49
|
internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
|
|
50
50
|
onClose?: () => void; // Optional callback to close the drawer
|
|
51
|
+
collapsed?: boolean; // Whether sidebar is collapsed
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
export interface SubMenuItemProps {
|
|
@@ -62,4 +63,5 @@ export interface MenuBarProps {
|
|
|
62
63
|
internalMenuClickHandler: (params: InternalMenuClickHandlerProps) => void;
|
|
63
64
|
previousMenuClickHandler: () => void;
|
|
64
65
|
onClose?: () => void; // Optional callback to close the drawer
|
|
66
|
+
collapsed?: boolean; // Whether sidebar is collapsed
|
|
65
67
|
}
|
|
@@ -30,7 +30,6 @@ export const SidebarContainer = styled(Stack)(({ theme }) => ({
|
|
|
30
30
|
export const MenuBarContainer = styled(Box)(({ theme }) => ({
|
|
31
31
|
flex: 1,
|
|
32
32
|
height: '100%',
|
|
33
|
-
borderRadius: '8px',
|
|
34
33
|
backgroundColor: theme.palette.surface.paperBackground,
|
|
35
34
|
overflowY: 'auto',
|
|
36
35
|
overflowX: 'hidden',
|
|
@@ -64,7 +63,6 @@ export const MenuHeaderContainer = styled(Stack)(({ theme }) => ({
|
|
|
64
63
|
padding: '12px 16px',
|
|
65
64
|
backgroundColor: theme.palette.surface.grey,
|
|
66
65
|
cursor: 'pointer',
|
|
67
|
-
borderRadius: '8px 8px 0px 0px',
|
|
68
66
|
}));
|
|
69
67
|
|
|
70
68
|
// Menu item containers
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Avatar, Stack, Typography, useTheme } from '@mui/material';
|
|
1
|
+
import { Avatar, Box, Stack, Typography, useTheme } from '@mui/material';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { Icons } from '../../../Assets/Icons/Icons';
|
|
4
4
|
import { DropdownMenu } from '../../../Navigation/DropDownMenu/DropDownMenu';
|
|
5
5
|
import { DropdownMenuItem } from '../../../Navigation/DropDownMenu/DropdownMenuItem';
|
|
6
6
|
|
|
7
|
-
interface UserProfilePopupProps {
|
|
7
|
+
export interface UserProfilePopupProps {
|
|
8
8
|
/** User's full name */
|
|
9
9
|
userFullName: string;
|
|
10
10
|
/** User's designation/role */
|
|
@@ -23,6 +23,8 @@ interface UserProfilePopupProps {
|
|
|
23
23
|
onActiveDevicesClick?: () => void;
|
|
24
24
|
/** Account section click handler */
|
|
25
25
|
onAccountClick?: () => void;
|
|
26
|
+
/**Persistant Side bar collapsed - boolean */
|
|
27
|
+
collapsed?: boolean;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
const getStartingLetters = (text: string) => {
|
|
@@ -52,6 +54,7 @@ const getStartingLetters = (text: string) => {
|
|
|
52
54
|
* />
|
|
53
55
|
*/
|
|
54
56
|
export const UserProfilePopup: React.FC<UserProfilePopupProps> = ({
|
|
57
|
+
collapsed,
|
|
55
58
|
userFullName,
|
|
56
59
|
designation = '',
|
|
57
60
|
profileActions = [],
|
|
@@ -89,19 +92,46 @@ export const UserProfilePopup: React.FC<UserProfilePopupProps> = ({
|
|
|
89
92
|
return (
|
|
90
93
|
<DropdownMenu
|
|
91
94
|
anchor={({ open }) => (
|
|
92
|
-
<
|
|
93
|
-
src={profileUrl ?? ''}
|
|
94
|
-
onClick={open}
|
|
95
|
+
<Box
|
|
95
96
|
sx={{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
display: 'flex',
|
|
98
|
+
justifyContent: collapsed ? 'center' : 'space-between',
|
|
99
|
+
borderTop: `1px solid ${theme.palette.border.primary}`,
|
|
100
|
+
padding: 1,
|
|
101
|
+
alignItems: 'center',
|
|
102
|
+
width: collapsed ? '64px' : '250px',
|
|
103
|
+
':hover': {
|
|
104
|
+
background: theme.palette.surface.grey,
|
|
105
|
+
cursor: 'pointer',
|
|
106
|
+
},
|
|
101
107
|
}}
|
|
108
|
+
onClick={open}
|
|
102
109
|
>
|
|
103
|
-
|
|
104
|
-
|
|
110
|
+
<Stack
|
|
111
|
+
direction={'row'}
|
|
112
|
+
gap={1}
|
|
113
|
+
sx={{
|
|
114
|
+
alignItems: 'center',
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
<Avatar
|
|
118
|
+
src={profileUrl ?? ''}
|
|
119
|
+
sx={{
|
|
120
|
+
cursor: 'pointer',
|
|
121
|
+
width: 35,
|
|
122
|
+
height: 35,
|
|
123
|
+
fontSize: '12px',
|
|
124
|
+
background: 'transparent',
|
|
125
|
+
...avatarSx,
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
{getStartingLetters(userFullName)}
|
|
129
|
+
</Avatar>
|
|
130
|
+
{!collapsed && (
|
|
131
|
+
<Typography variant="subtitle3">{userFullName}</Typography>
|
|
132
|
+
)}
|
|
133
|
+
</Stack>
|
|
134
|
+
</Box>
|
|
105
135
|
)}
|
|
106
136
|
menuListProps={{
|
|
107
137
|
sx: {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { SideMenuItemProps } from './components/Sidebar/interfaces';
|
|
3
|
+
import { UserProfilePopupProps } from './components/UserProfilePopup';
|
|
3
4
|
|
|
4
5
|
export interface HelpDocsAction {
|
|
5
6
|
name: string;
|
|
@@ -20,6 +21,9 @@ export interface AppLayoutProps {
|
|
|
20
21
|
/** Navigation menu items */
|
|
21
22
|
menu: SideMenuItemProps[];
|
|
22
23
|
|
|
24
|
+
/**User profile parameters */
|
|
25
|
+
userProfileParams: UserProfilePopupProps;
|
|
26
|
+
|
|
23
27
|
/** AppBar customization - Primary approach */
|
|
24
28
|
rightSection?: ReactNode;
|
|
25
29
|
|
|
@@ -31,4 +35,9 @@ export interface AppLayoutProps {
|
|
|
31
35
|
|
|
32
36
|
/** Help documentation configuration for route-based contextual help */
|
|
33
37
|
helpDocsConfig?: HelpDocsConfig;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Initial collapsed state for persistent sidebar
|
|
41
|
+
*/
|
|
42
|
+
initialCollapsed?: boolean;
|
|
34
43
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
resetStateForUniqueId,
|
|
10
10
|
setViewForUniqueId,
|
|
11
11
|
} from '../../../../../redux/slices/pageHeaderSlice';
|
|
12
|
-
import {
|
|
12
|
+
import { Spinner, Typography } from '../../../../export';
|
|
13
13
|
|
|
14
14
|
export type ViewsProps = {
|
|
15
15
|
type: string;
|
|
@@ -37,7 +37,8 @@ export const ViewTab = ({
|
|
|
37
37
|
return (
|
|
38
38
|
<Stack onClick={onClick} sx={{ cursor: 'pointer' }} minWidth="80px">
|
|
39
39
|
<Stack direction="row" gap={1} alignItems="center" padding="8px 0px">
|
|
40
|
-
|
|
40
|
+
{/* There is not specifix use for this icon & it is repeated for all the views */}
|
|
41
|
+
{/* <Icons.ViewsIcon /> */}
|
|
41
42
|
<Typography variant="subtitle3">{title}</Typography>
|
|
42
43
|
</Stack>
|
|
43
44
|
|
|
@@ -68,7 +68,7 @@ const BreadcrumbContainer = styled(Stack)(({ theme }) => ({
|
|
|
68
68
|
justifyContent: 'space-between',
|
|
69
69
|
height: '52px',
|
|
70
70
|
paddingLeft: '12px',
|
|
71
|
-
backgroundColor: theme.palette.surface.
|
|
71
|
+
backgroundColor: theme.palette.surface.paperBackground,
|
|
72
72
|
[theme.breakpoints.down('md')]: {
|
|
73
73
|
paddingLeft: '0px',
|
|
74
74
|
},
|
|
@@ -158,7 +158,7 @@ export const SidebarV2 = ({
|
|
|
158
158
|
transition={{ duration: 0.3, ease: 'circOut' }}
|
|
159
159
|
style={{
|
|
160
160
|
margin: isSmallScreen ? '12px 12px 0px 12px' : '12px',
|
|
161
|
-
height:
|
|
161
|
+
height: 'calc(100vh - 116px)',
|
|
162
162
|
}}
|
|
163
163
|
>
|
|
164
164
|
<StyledSidebarContainer
|
|
@@ -22,7 +22,7 @@ export const DarkColorTokens = {
|
|
|
22
22
|
primaryContrast: ColorPalette.BlueGreyColors.BlueGrey800,
|
|
23
23
|
},
|
|
24
24
|
surface: {
|
|
25
|
-
defaultBackground: ColorPalette.BlueGreyColors.
|
|
25
|
+
defaultBackground: ColorPalette.BlueGreyColors.BlueGrey800,
|
|
26
26
|
paperBackground: ColorPalette.BlueGreyColors.BlueGrey800,
|
|
27
27
|
grey: ColorPalette.BlueGreyColors.BlueGrey400,
|
|
28
28
|
},
|
|
@@ -22,7 +22,7 @@ export const LightColorTokens = {
|
|
|
22
22
|
primaryContrast: ColorPalette.GreyColors.White,
|
|
23
23
|
},
|
|
24
24
|
surface: {
|
|
25
|
-
defaultBackground: ColorPalette.
|
|
25
|
+
defaultBackground: ColorPalette.GreyColors.White,
|
|
26
26
|
paperBackground: ColorPalette.GreyColors.White,
|
|
27
27
|
grey: ColorPalette.GreyColors.Grey100,
|
|
28
28
|
},
|