varminer-app-header 1.0.4 → 1.0.6
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/README.md +17 -11
- package/dist/AppHeader.d.ts.map +1 -1
- package/dist/index.d.ts +0 -74
- package/dist/index.esm.js +120 -106
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +120 -106
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +0 -74
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/localStorage.d.ts +2 -7
- package/dist/utils/localStorage.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,9 +31,9 @@ npm install react react-dom react-router-dom @mui/material @mui/icons-material @
|
|
|
31
31
|
|
|
32
32
|
## Usage
|
|
33
33
|
|
|
34
|
-
###
|
|
34
|
+
### Plug-and-Play (Zero Configuration)
|
|
35
35
|
|
|
36
|
-
The package
|
|
36
|
+
The package is **100% plug-and-play** - no props needed! It automatically loads everything from localStorage and handles all interactions internally:
|
|
37
37
|
|
|
38
38
|
```tsx
|
|
39
39
|
import React from 'react';
|
|
@@ -43,20 +43,26 @@ import 'varminer-app-header/dist/index.css'; // Don't forget the CSS!
|
|
|
43
43
|
function App() {
|
|
44
44
|
return (
|
|
45
45
|
<DrawerProvider>
|
|
46
|
-
<AppHeader
|
|
47
|
-
user={{
|
|
48
|
-
name: "John Doe",
|
|
49
|
-
email: "john@example.com",
|
|
50
|
-
role: "Administrator",
|
|
51
|
-
initials: "JD"
|
|
52
|
-
}}
|
|
53
|
-
notificationCount={5}
|
|
54
|
-
/>
|
|
46
|
+
<AppHeader />
|
|
55
47
|
</DrawerProvider>
|
|
56
48
|
);
|
|
57
49
|
}
|
|
58
50
|
```
|
|
59
51
|
|
|
52
|
+
**That's it!** The component automatically:
|
|
53
|
+
- ✅ Loads user data from `localStorage` (`persist:userdb`)
|
|
54
|
+
- ✅ Loads notification count from `localStorage`
|
|
55
|
+
- ✅ Loads message count from `localStorage`
|
|
56
|
+
- ✅ Handles hamburger menu toggle internally
|
|
57
|
+
- ✅ Uses default logo ("VAR" and "MINER")
|
|
58
|
+
- ✅ Uses default routes: `/account/overview`, `/profile`, `/logout`
|
|
59
|
+
- ✅ Handles all navigation internally
|
|
60
|
+
- ✅ Shows online status badge
|
|
61
|
+
|
|
62
|
+
### Zero Configuration
|
|
63
|
+
|
|
64
|
+
The component requires **no props at all** - it's completely plug-and-play!
|
|
65
|
+
|
|
60
66
|
**Defaults:**
|
|
61
67
|
- Logo: "VAR" and "MINER"
|
|
62
68
|
- Routes: `/account/overview` (settings), `/profile` (profile), `/logout` (logout)
|
package/dist/AppHeader.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../src/AppHeader.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAe,MAAM,SAAS,CAAC;AAEtD,OAAO,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../src/AppHeader.tsx"],"names":[],"mappings":"AA4BA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAe,MAAM,SAAS,CAAC;AAEtD,OAAO,sBAAsB,CAAC;AAa9B,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAmfvC,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -10,80 +10,6 @@ interface UserProfile {
|
|
|
10
10
|
initials?: string;
|
|
11
11
|
}
|
|
12
12
|
interface AppHeaderProps {
|
|
13
|
-
/**
|
|
14
|
-
* User profile information
|
|
15
|
-
*/
|
|
16
|
-
user?: UserProfile;
|
|
17
|
-
/**
|
|
18
|
-
* Whether the user is online
|
|
19
|
-
* @default true
|
|
20
|
-
*/
|
|
21
|
-
isOnline?: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* App logo/brand name (optional - defaults to "VAR" and "MINER")
|
|
24
|
-
*/
|
|
25
|
-
logo?: {
|
|
26
|
-
first: string;
|
|
27
|
-
second: string;
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Notification count (shown in desktop and mobile menu)
|
|
31
|
-
* @default 0
|
|
32
|
-
*/
|
|
33
|
-
notificationCount?: number;
|
|
34
|
-
/**
|
|
35
|
-
* Message count (shown only in mobile menu, optional)
|
|
36
|
-
* @default undefined (not shown if not provided)
|
|
37
|
-
*/
|
|
38
|
-
messageCount?: number;
|
|
39
|
-
/**
|
|
40
|
-
* Callback when drawer toggle is clicked
|
|
41
|
-
*/
|
|
42
|
-
onDrawerToggle?: () => void;
|
|
43
|
-
/**
|
|
44
|
-
* Whether drawer is open
|
|
45
|
-
* @default false
|
|
46
|
-
*/
|
|
47
|
-
isDrawerOpen?: boolean;
|
|
48
|
-
/**
|
|
49
|
-
* Route paths for navigation (optional - defaults are used if not provided)
|
|
50
|
-
* All routes are absolute paths from root (e.g., "/account/overview")
|
|
51
|
-
* @default "/account/overview", "/profile", "/logout"
|
|
52
|
-
*/
|
|
53
|
-
routes?: {
|
|
54
|
-
/**
|
|
55
|
-
* Settings route path
|
|
56
|
-
* @default "/account/overview"
|
|
57
|
-
*/
|
|
58
|
-
settings?: string;
|
|
59
|
-
/**
|
|
60
|
-
* Profile route path
|
|
61
|
-
* @default "/profile"
|
|
62
|
-
*/
|
|
63
|
-
profile?: string;
|
|
64
|
-
/**
|
|
65
|
-
* Logout route path
|
|
66
|
-
* @default "/logout"
|
|
67
|
-
*/
|
|
68
|
-
logout?: string;
|
|
69
|
-
};
|
|
70
|
-
/**
|
|
71
|
-
* Callback when settings is clicked (overrides default navigation)
|
|
72
|
-
*/
|
|
73
|
-
onSettingsClick?: () => void;
|
|
74
|
-
/**
|
|
75
|
-
* Callback when profile is clicked (overrides default navigation)
|
|
76
|
-
*/
|
|
77
|
-
onProfileClick?: () => void;
|
|
78
|
-
/**
|
|
79
|
-
* Callback when sign out is clicked (overrides default navigation)
|
|
80
|
-
* If not provided, will clear localStorage and navigate to logout route
|
|
81
|
-
*/
|
|
82
|
-
onSignOutClick?: () => void;
|
|
83
|
-
/**
|
|
84
|
-
* Custom CSS class name
|
|
85
|
-
*/
|
|
86
|
-
className?: string;
|
|
87
13
|
}
|
|
88
14
|
|
|
89
15
|
declare const AppHeader: React__default.FC<AppHeaderProps>;
|
package/dist/index.esm.js
CHANGED
|
@@ -34,19 +34,11 @@ const DrawerProvider = ({ children }) => {
|
|
|
34
34
|
};
|
|
35
35
|
const useDrawer = () => React.useContext(DrawerContext);
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Utility functions to get user data from localStorage
|
|
39
|
-
*/
|
|
40
|
-
/**
|
|
41
|
-
* Gets user profile data from localStorage
|
|
42
|
-
* Returns user info including name, email, role, etc.
|
|
43
|
-
*/
|
|
44
37
|
const getUserDataFromStorage = () => {
|
|
45
38
|
const userDbString = localStorage.getItem("persist:userdb");
|
|
46
39
|
if (userDbString) {
|
|
47
40
|
try {
|
|
48
41
|
const parsedOuter = JSON.parse(userDbString);
|
|
49
|
-
// Helper function to parse nested JSON strings
|
|
50
42
|
const parseNested = (value) => {
|
|
51
43
|
if (typeof value === 'string') {
|
|
52
44
|
try {
|
|
@@ -58,37 +50,29 @@ const getUserDataFromStorage = () => {
|
|
|
58
50
|
}
|
|
59
51
|
return value;
|
|
60
52
|
};
|
|
61
|
-
// Try to get user data from different possible locations
|
|
62
53
|
let userData = null;
|
|
63
|
-
// Check for userDetails
|
|
64
54
|
if (parsedOuter.userDetails) {
|
|
65
55
|
const parsedUserDetails = parseNested(parsedOuter.userDetails);
|
|
66
56
|
userData = parsedUserDetails.user || parsedUserDetails.data || parsedUserDetails;
|
|
67
57
|
}
|
|
68
|
-
// Check for user reducer/state
|
|
69
58
|
if (!userData && parsedOuter.user) {
|
|
70
59
|
const parsedUser = parseNested(parsedOuter.user);
|
|
71
60
|
userData = parsedUser.user || parsedUser.data || parsedUser.currentUser || parsedUser;
|
|
72
61
|
}
|
|
73
|
-
// Check for authDetails for user info
|
|
74
62
|
if (!userData && parsedOuter.authDetails) {
|
|
75
63
|
const parsedAuthDetails = parseNested(parsedOuter.authDetails);
|
|
76
|
-
// Check auth object
|
|
77
64
|
if (parsedAuthDetails.auth) {
|
|
78
65
|
userData = parsedAuthDetails.auth.user || parsedAuthDetails.auth.userData;
|
|
79
66
|
}
|
|
80
|
-
// Check root of authDetails
|
|
81
67
|
if (!userData) {
|
|
82
68
|
userData = parsedAuthDetails.user || parsedAuthDetails.userData || parsedAuthDetails.currentUser;
|
|
83
69
|
}
|
|
84
70
|
}
|
|
85
|
-
// Check for profile
|
|
86
71
|
if (!userData && parsedOuter.profile) {
|
|
87
72
|
const parsedProfile = parseNested(parsedOuter.profile);
|
|
88
73
|
userData = parsedProfile.user || parsedProfile.data || parsedProfile;
|
|
89
74
|
}
|
|
90
75
|
if (userData) {
|
|
91
|
-
// Build name from various possible fields
|
|
92
76
|
let name = userData.name || userData.fullName || userData.userName || "";
|
|
93
77
|
if (!name && (userData.firstName || userData.lastName)) {
|
|
94
78
|
name = [userData.firstName, userData.lastName].filter(Boolean).join(' ');
|
|
@@ -109,75 +93,129 @@ const getUserDataFromStorage = () => {
|
|
|
109
93
|
}
|
|
110
94
|
return null;
|
|
111
95
|
};
|
|
96
|
+
const getNotificationCountFromStorage = () => {
|
|
97
|
+
const userDbString = localStorage.getItem("persist:userdb");
|
|
98
|
+
if (userDbString) {
|
|
99
|
+
try {
|
|
100
|
+
const parsedOuter = JSON.parse(userDbString);
|
|
101
|
+
const parseNested = (value) => {
|
|
102
|
+
if (typeof value === 'string') {
|
|
103
|
+
try {
|
|
104
|
+
return JSON.parse(value);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return value;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return value;
|
|
111
|
+
};
|
|
112
|
+
if (parsedOuter.notifications) {
|
|
113
|
+
const parsedNotifications = parseNested(parsedOuter.notifications);
|
|
114
|
+
const count = parsedNotifications.count || parsedNotifications.unreadCount || parsedNotifications.total;
|
|
115
|
+
if (typeof count === 'number')
|
|
116
|
+
return count;
|
|
117
|
+
}
|
|
118
|
+
if (parsedOuter.app) {
|
|
119
|
+
const parsedApp = parseNested(parsedOuter.app);
|
|
120
|
+
if (parsedApp.notificationCount !== undefined) {
|
|
121
|
+
return parsedApp.notificationCount;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
console.error("Error parsing notification count from localStorage:", err);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return 0;
|
|
130
|
+
};
|
|
131
|
+
const getMessageCountFromStorage = () => {
|
|
132
|
+
const userDbString = localStorage.getItem("persist:userdb");
|
|
133
|
+
if (userDbString) {
|
|
134
|
+
try {
|
|
135
|
+
const parsedOuter = JSON.parse(userDbString);
|
|
136
|
+
const parseNested = (value) => {
|
|
137
|
+
if (typeof value === 'string') {
|
|
138
|
+
try {
|
|
139
|
+
return JSON.parse(value);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return value;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return value;
|
|
146
|
+
};
|
|
147
|
+
if (parsedOuter.messages) {
|
|
148
|
+
const parsedMessages = parseNested(parsedOuter.messages);
|
|
149
|
+
const count = parsedMessages.count || parsedMessages.unreadCount || parsedMessages.total;
|
|
150
|
+
if (typeof count === 'number')
|
|
151
|
+
return count;
|
|
152
|
+
}
|
|
153
|
+
if (parsedOuter.app) {
|
|
154
|
+
const parsedApp = parseNested(parsedOuter.app);
|
|
155
|
+
if (parsedApp.messageCount !== undefined) {
|
|
156
|
+
return parsedApp.messageCount;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
console.error("Error parsing message count from localStorage:", err);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return undefined;
|
|
165
|
+
};
|
|
112
166
|
|
|
113
|
-
// Default routes - absolute paths from root
|
|
114
167
|
const DEFAULT_ROUTES = {
|
|
115
168
|
settings: "/account/overview",
|
|
116
169
|
profile: "/profile",
|
|
117
170
|
logout: "/logout",
|
|
118
171
|
};
|
|
119
|
-
// Default logo - can be overridden via props
|
|
120
172
|
const DEFAULT_LOGO = {
|
|
121
173
|
first: "VAR",
|
|
122
174
|
second: "MINER",
|
|
123
175
|
};
|
|
124
|
-
const AppHeader = (
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
const { isDrawerOpen: isDrawerOpenContext, toggleDrawer, openDrawer, closeDrawer } = useDrawer();
|
|
176
|
+
const AppHeader = () => {
|
|
177
|
+
const finalLogo = DEFAULT_LOGO;
|
|
178
|
+
const { isDrawerOpen, toggleDrawer } = useDrawer();
|
|
128
179
|
const [anchorEl, setAnchorEl] = React__default.useState(null);
|
|
129
180
|
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React__default.useState(null);
|
|
130
181
|
const [user, setUser] = React__default.useState(() => {
|
|
131
|
-
// Initialize with prop if provided, otherwise try localStorage, otherwise default
|
|
132
|
-
if (userProp) {
|
|
133
|
-
return userProp;
|
|
134
|
-
}
|
|
135
182
|
const storedUser = getUserDataFromStorage();
|
|
136
183
|
if (storedUser && storedUser.name && storedUser.email) {
|
|
137
184
|
return storedUser;
|
|
138
185
|
}
|
|
139
186
|
return {
|
|
140
|
-
name: "
|
|
141
|
-
email: "
|
|
142
|
-
role: "
|
|
143
|
-
initials: "SK",
|
|
187
|
+
name: "Naveen",
|
|
188
|
+
email: "naveen@varminer.com",
|
|
189
|
+
role: "Account Owner",
|
|
144
190
|
};
|
|
145
191
|
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
else {
|
|
154
|
-
closeDrawer();
|
|
155
|
-
}
|
|
156
|
-
prevPropRef.current = isDrawerOpenProp;
|
|
157
|
-
}
|
|
158
|
-
}, [isDrawerOpenProp, openDrawer, closeDrawer]);
|
|
159
|
-
// Always use context state for icon display (since that's what actually changes on click)
|
|
160
|
-
// This ensures the icon updates immediately when user clicks, regardless of prop
|
|
161
|
-
const isDrawerOpen = isDrawerOpenContext;
|
|
162
|
-
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
|
|
163
|
-
// Update user state when prop changes or fetch from localStorage
|
|
192
|
+
const [notificationCount, setNotificationCount] = React__default.useState(() => {
|
|
193
|
+
const count = getNotificationCountFromStorage();
|
|
194
|
+
return count !== null && count !== undefined ? count : 0;
|
|
195
|
+
});
|
|
196
|
+
const [messageCount, setMessageCount] = React__default.useState(() => {
|
|
197
|
+
return getMessageCountFromStorage() ?? undefined;
|
|
198
|
+
});
|
|
164
199
|
React__default.useEffect(() => {
|
|
165
|
-
|
|
166
|
-
|
|
200
|
+
const storedUser = getUserDataFromStorage();
|
|
201
|
+
if (storedUser && storedUser.name && storedUser.email) {
|
|
202
|
+
setUser(storedUser);
|
|
167
203
|
}
|
|
168
204
|
else {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
205
|
+
setUser({
|
|
206
|
+
name: "User",
|
|
207
|
+
email: "user@example.com",
|
|
208
|
+
role: "User",
|
|
209
|
+
});
|
|
173
210
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
211
|
+
const notifCount = getNotificationCountFromStorage();
|
|
212
|
+
setNotificationCount(notifCount !== null && notifCount !== undefined ? notifCount : 0);
|
|
213
|
+
const msgCount = getMessageCountFromStorage();
|
|
214
|
+
setMessageCount(msgCount ?? undefined);
|
|
215
|
+
}, []);
|
|
216
|
+
const finalRoutes = DEFAULT_ROUTES;
|
|
217
|
+
const notificationCountValue = notificationCount;
|
|
218
|
+
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
|
|
181
219
|
const OnlineBadge = styled(Badge)(({ theme }) => ({
|
|
182
220
|
"& .MuiBadge-badge": {
|
|
183
221
|
backgroundColor: "#44b700",
|
|
@@ -188,7 +226,7 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
188
226
|
borderRadius: "50%",
|
|
189
227
|
},
|
|
190
228
|
}));
|
|
191
|
-
|
|
229
|
+
styled(Badge)(({ theme }) => ({
|
|
192
230
|
"& .MuiBadge-badge": {
|
|
193
231
|
backgroundColor: "gray",
|
|
194
232
|
color: "gray",
|
|
@@ -200,7 +238,6 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
200
238
|
}));
|
|
201
239
|
const handleDrawerToggle = () => {
|
|
202
240
|
toggleDrawer();
|
|
203
|
-
onDrawerToggle?.();
|
|
204
241
|
};
|
|
205
242
|
const handleProfileMenuOpen = (event) => {
|
|
206
243
|
setAnchorEl(event.currentTarget);
|
|
@@ -217,43 +254,25 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
217
254
|
};
|
|
218
255
|
const handleSettingsClick = () => {
|
|
219
256
|
handleClose();
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
// Use window.location to navigate to absolute path, bypassing React Router basename
|
|
225
|
-
const path = finalRoutes.settings.startsWith('/')
|
|
226
|
-
? finalRoutes.settings
|
|
227
|
-
: `/${finalRoutes.settings}`;
|
|
228
|
-
window.location.href = path;
|
|
229
|
-
}
|
|
257
|
+
const path = finalRoutes.settings.startsWith('/')
|
|
258
|
+
? finalRoutes.settings
|
|
259
|
+
: `/${finalRoutes.settings}`;
|
|
260
|
+
window.location.href = path;
|
|
230
261
|
};
|
|
231
262
|
const handleProfileClick = () => {
|
|
232
263
|
handleClose();
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// Use window.location to navigate to absolute path, bypassing React Router basename
|
|
238
|
-
const path = finalRoutes.profile.startsWith('/')
|
|
239
|
-
? finalRoutes.profile
|
|
240
|
-
: `/${finalRoutes.profile}`;
|
|
241
|
-
window.location.href = path;
|
|
242
|
-
}
|
|
264
|
+
const path = finalRoutes.profile.startsWith('/')
|
|
265
|
+
? finalRoutes.profile
|
|
266
|
+
: `/${finalRoutes.profile}`;
|
|
267
|
+
window.location.href = path;
|
|
243
268
|
};
|
|
244
269
|
const handleSignOutClick = () => {
|
|
245
270
|
handleClose();
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
// Use window.location to navigate to absolute path, bypassing React Router basename
|
|
252
|
-
const path = finalRoutes.logout.startsWith('/')
|
|
253
|
-
? finalRoutes.logout
|
|
254
|
-
: `/${finalRoutes.logout}`;
|
|
255
|
-
window.location.href = path;
|
|
256
|
-
}
|
|
271
|
+
localStorage.clear();
|
|
272
|
+
const path = finalRoutes.logout.startsWith('/')
|
|
273
|
+
? finalRoutes.logout
|
|
274
|
+
: `/${finalRoutes.logout}`;
|
|
275
|
+
window.location.href = path;
|
|
257
276
|
};
|
|
258
277
|
const menuId = "primary-account-menu";
|
|
259
278
|
const getInitials = () => {
|
|
@@ -270,7 +289,7 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
270
289
|
width: "100%",
|
|
271
290
|
maxWidth: 360,
|
|
272
291
|
pointerEvents: "none",
|
|
273
|
-
}, component: "div", "aria-hidden": "true", tabIndex: -1, children: jsxs(ListItem, { alignItems: "flex-start", className: "profile-menu-item", children: [jsx(ListItemAvatar, { children:
|
|
292
|
+
}, component: "div", "aria-hidden": "true", tabIndex: -1, children: jsxs(ListItem, { alignItems: "flex-start", className: "profile-menu-item", children: [jsx(ListItemAvatar, { children: (jsx(OnlineBadge, { overlap: "circular", anchorOrigin: { vertical: "bottom", horizontal: "right" }, variant: "dot", title: "Online", "aria-label": "Online status badge", "data-testid": "online-badge", children: jsx(Avatar, { sx: { bgcolor: deepOrange[500] }, alt: user.name, title: user.name, src: user.avatar, children: getInitials() }) })) }), jsx(ListItemText, { secondary: jsxs(React__default.Fragment, { children: [jsx(Typography, { className: "profile-name", component: "p", children: user.name }), jsx(Typography, { className: "profile-email", component: "p", children: user.email }), jsxs(Typography, { className: "profile-role", component: "p", children: ["Role: ", user.role] })] }) })] }) }));
|
|
274
293
|
const renderMenu = (jsxs(Menu, { anchorEl: anchorEl, id: "account-menu", open: open, onClose: handleClose, onClick: handleClose, slotProps: {
|
|
275
294
|
paper: {
|
|
276
295
|
elevation: 0,
|
|
@@ -306,8 +325,8 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
306
325
|
}, id: mobileMenuId, keepMounted: true, transformOrigin: {
|
|
307
326
|
vertical: "top",
|
|
308
327
|
horizontal: "right",
|
|
309
|
-
}, open: isMobileMenuOpen, onClose: handleMobileMenuClose, children: [messageCount !== undefined && (jsxs(MenuItem, { children: [jsx(IconButton, { size: "large", "aria-label": `show ${messageCount} new mails`, sx: { color: '#1e2f97' }, children: jsx(Badge, { badgeContent: messageCount, color: "error", children: jsx(MailIcon, {}) }) }), jsx("p", { children: "Messages" })] })),
|
|
310
|
-
return (jsxs(Box, { sx: { flexGrow: 1 }, className:
|
|
328
|
+
}, open: isMobileMenuOpen, onClose: handleMobileMenuClose, children: [messageCount !== undefined && (jsxs(MenuItem, { children: [jsx(IconButton, { size: "large", "aria-label": `show ${messageCount} new mails`, sx: { color: '#1e2f97' }, children: jsx(Badge, { badgeContent: messageCount, color: "error", children: jsx(MailIcon, {}) }) }), jsx("p", { children: "Messages" })] })), notificationCountValue > 0 && (jsxs(MenuItem, { children: [jsx(IconButton, { size: "large", "aria-label": `show ${notificationCountValue} new notifications`, sx: { color: '#1e2f97' }, children: jsx(Badge, { badgeContent: notificationCount, color: "error", children: jsx(NotificationsActiveOutlined, {}) }) }), jsx("p", { children: "Notifications" })] })), jsxs(MenuItem, { onClick: handleProfileMenuOpen, children: [jsx(IconButton, { size: "large", "aria-label": "account of current user", "aria-controls": "primary-account-menu", "aria-haspopup": "true", sx: { color: '#1e2f97' }, children: (jsx(OnlineBadge, { overlap: "circular", anchorOrigin: { vertical: "bottom", horizontal: "right" }, variant: "dot", title: "Online", "aria-label": "Online status badge", "data-testid": "online-badge", children: jsx(AccountCircle, { titleAccess: user.name, "aria-label": "User avatar" }) })) }), jsx("p", { children: "Profile" })] })] }));
|
|
329
|
+
return (jsxs(Box, { sx: { flexGrow: 1 }, className: "app-header", children: [jsx(AppBar, { sx: {
|
|
311
330
|
position: "fixed",
|
|
312
331
|
top: 0,
|
|
313
332
|
backgroundColor: "#ffffff",
|
|
@@ -317,27 +336,22 @@ const AppHeader = ({ user: userProp, isOnline = true, logo, notificationCount =
|
|
|
317
336
|
'&:hover': {
|
|
318
337
|
backgroundColor: 'rgba(30, 47, 151, 0.04)',
|
|
319
338
|
}
|
|
320
|
-
}, onClick: handleDrawerToggle, children: isDrawerOpen ? (jsx(MenuOpenIcon, { fontSize: "large" })) : (jsx(MenuIcon, { fontSize: "large" })) }), jsxs(Typography, { variant: "h6", noWrap: true, component: "div", sx: { display: { xs: "none", sm: "block" } }, "data-testid": "var-miner-wrapper", children: [jsx("span", { className: "var", children: finalLogo.first }), jsx("span", { className: "miner", children: finalLogo.second })] }), jsx(Box, { sx: { flexGrow: 1 } }), jsxs(Box, { sx: { display: { xs: "none", md: "flex" } }, children: [
|
|
339
|
+
}, onClick: handleDrawerToggle, children: isDrawerOpen ? (jsx(MenuOpenIcon, { fontSize: "large" })) : (jsx(MenuIcon, { fontSize: "large" })) }), jsxs(Typography, { variant: "h6", noWrap: true, component: "div", sx: { display: { xs: "none", sm: "block" } }, "data-testid": "var-miner-wrapper", children: [jsx("span", { className: "var", children: finalLogo.first }), jsx("span", { className: "miner", children: finalLogo.second })] }), jsx(Box, { sx: { flexGrow: 1 } }), jsxs(Box, { sx: { display: { xs: "none", md: "flex" } }, children: [notificationCountValue > 0 && (jsx(IconButton, { size: "large", "aria-label": `show ${notificationCountValue} new notifications`, sx: {
|
|
321
340
|
color: '#1e2f97',
|
|
322
341
|
'&:hover': {
|
|
323
342
|
backgroundColor: 'rgba(30, 47, 151, 0.04)',
|
|
324
343
|
}
|
|
325
|
-
}, children: jsx(Badge, { badgeContent:
|
|
344
|
+
}, children: jsx(Badge, { badgeContent: notificationCountValue, color: "error", children: jsx(NotificationsActiveOutlined, {}) }) })), jsx(IconButton, { size: "large", edge: "end", "aria-label": "account of current user", "aria-controls": menuId, "aria-haspopup": "true", onClick: handleProfileMenuOpen, sx: {
|
|
326
345
|
color: '#1e2f97',
|
|
327
346
|
'&:hover': {
|
|
328
347
|
backgroundColor: 'rgba(30, 47, 151, 0.04)',
|
|
329
348
|
}
|
|
330
|
-
}, children:
|
|
331
|
-
bgcolor: deepOrange[500],
|
|
332
|
-
width: 20,
|
|
333
|
-
height: 20,
|
|
334
|
-
p: 1,
|
|
335
|
-
}, alt: user.name, title: user.name, src: user.avatar, sizes: "large", children: getInitials() }) })) : (jsx(OfflineBadge, { overlap: "circular", anchorOrigin: { vertical: "bottom", horizontal: "right" }, variant: "dot", title: "Offline", "aria-label": "Offline status badge", "data-testid": "offline-badge", children: jsx(Avatar, { sx: {
|
|
349
|
+
}, children: (jsx(OnlineBadge, { overlap: "circular", anchorOrigin: { vertical: "bottom", horizontal: "right" }, variant: "dot", title: "Online", "aria-label": "Online status badge", "data-testid": "online-badge", children: jsx(Avatar, { sx: {
|
|
336
350
|
bgcolor: deepOrange[500],
|
|
337
351
|
width: 20,
|
|
338
352
|
height: 20,
|
|
339
353
|
p: 1,
|
|
340
|
-
}, alt: user.name, title: user.name, src: user.avatar, children: getInitials() }) }))
|
|
354
|
+
}, alt: user.name, title: user.name, src: user.avatar, sizes: "large", children: getInitials() }) })) })] }), jsx(Box, { sx: { display: { xs: "flex", md: "none" } }, children: jsx(IconButton, { size: "large", "aria-label": "show more", "aria-controls": mobileMenuId, "aria-haspopup": "true", onClick: handleMobileMenuOpen, sx: {
|
|
341
355
|
color: '#1e2f97',
|
|
342
356
|
'&:hover': {
|
|
343
357
|
backgroundColor: 'rgba(30, 47, 151, 0.04)',
|