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 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
- ### Basic Example (Minimal Configuration)
34
+ ### Plug-and-Play (Zero Configuration)
35
35
 
36
- The package includes sensible defaults for logo and routes. Minimal setup:
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)
@@ -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;AAe9B,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,cAAc,CAyhBvC,CAAC;AAEF,eAAe,SAAS,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 = ({ user: userProp, isOnline = true, logo, notificationCount = 0, messageCount, onDrawerToggle, routes, onSettingsClick, onProfileClick, onSignOutClick, className, isDrawerOpen: isDrawerOpenProp, }) => {
125
- // Use provided logo or default
126
- const finalLogo = logo ?? DEFAULT_LOGO;
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: "Shiva Kumar",
141
- email: "shivam@redcliffelabs.com",
142
- role: "Lab Technician",
143
- initials: "SK",
187
+ name: "Naveen",
188
+ email: "naveen@varminer.com",
189
+ role: "Account Owner",
144
190
  };
145
191
  });
146
- // Sync context with prop if provided (for initial state and external control)
147
- const prevPropRef = React__default.useRef(isDrawerOpenProp);
148
- React__default.useEffect(() => {
149
- if (isDrawerOpenProp !== undefined && prevPropRef.current !== isDrawerOpenProp) {
150
- if (isDrawerOpenProp) {
151
- openDrawer();
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
- if (userProp) {
166
- setUser(userProp);
200
+ const storedUser = getUserDataFromStorage();
201
+ if (storedUser && storedUser.name && storedUser.email) {
202
+ setUser(storedUser);
167
203
  }
168
204
  else {
169
- const storedUser = getUserDataFromStorage();
170
- if (storedUser && storedUser.name && storedUser.email) {
171
- setUser(storedUser);
172
- }
205
+ setUser({
206
+ name: "User",
207
+ email: "user@example.com",
208
+ role: "User",
209
+ });
173
210
  }
174
- }, [userProp]);
175
- // Merge provided routes with defaults - all routes are absolute from root
176
- const finalRoutes = {
177
- settings: routes?.settings ?? DEFAULT_ROUTES.settings,
178
- profile: routes?.profile ?? DEFAULT_ROUTES.profile,
179
- logout: routes?.logout ?? DEFAULT_ROUTES.logout,
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
- const OfflineBadge = styled(Badge)(({ theme }) => ({
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
- if (onSettingsClick) {
221
- onSettingsClick();
222
- }
223
- else {
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
- if (onProfileClick) {
234
- onProfileClick();
235
- }
236
- else {
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
- if (onSignOutClick) {
247
- onSignOutClick();
248
- }
249
- else {
250
- localStorage.clear();
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: isOnline ? (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(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: { 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] })] }) })] }) }));
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" })] })), notificationCount > 0 && (jsxs(MenuItem, { children: [jsx(IconButton, { size: "large", "aria-label": `show ${notificationCount} 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: isOnline ? (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(OfflineBadge, { overlap: "circular", anchorOrigin: { vertical: "bottom", horizontal: "right" }, variant: "dot", title: "Offline", "aria-label": "Offline status badge", "data-testid": "offline-badge", children: jsx(AccountCircle, { titleAccess: user.name, "aria-label": "User avatar" }) })) }), jsx("p", { children: "Profile" })] })] }));
310
- return (jsxs(Box, { sx: { flexGrow: 1 }, className: `app-header ${className || ""}`, children: [jsx(AppBar, { sx: {
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: [notificationCount > 0 && (jsx(IconButton, { size: "large", "aria-label": `show ${notificationCount} new notifications`, sx: {
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: notificationCount, 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: {
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: isOnline ? (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: {
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() }) })) })] }), 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: {
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)',