v0.12.11 new drawer menu notification feature
This commit is contained in:
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
|
||||
import { useSocket } from '../contexts/SocketContext.jsx';
|
||||
import { api } from '../utils/api.js';
|
||||
|
||||
export default function GlobalBar({ isMobile, showSidebar, onBurger }) {
|
||||
export default function GlobalBar({ isMobile, showSidebar, onBurger, hasUnread = false }) {
|
||||
const { connected } = useSocket();
|
||||
const [settings, setSettings] = useState({ app_name: 'rosterchirp', logo_url: '' });
|
||||
const [isDark, setIsDark] = useState(() => document.documentElement.getAttribute('data-theme') === 'dark');
|
||||
@@ -41,11 +41,22 @@ export default function GlobalBar({ isMobile, showSidebar, onBurger }) {
|
||||
title="Menu"
|
||||
aria-label="Open menu"
|
||||
>
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
||||
<line x1="3" y1="12" x2="21" y2="12"/>
|
||||
<line x1="3" y1="18" x2="21" y2="18"/>
|
||||
</svg>
|
||||
<div style={{ position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
|
||||
<line x1="3" y1="6" x2="21" y2="6"/>
|
||||
<line x1="3" y1="12" x2="21" y2="12"/>
|
||||
<line x1="3" y1="18" x2="21" y2="18"/>
|
||||
</svg>
|
||||
{hasUnread && (
|
||||
<span style={{
|
||||
position: 'absolute', bottom: -1, right: -1,
|
||||
width: 9, height: 9, borderRadius: '50%',
|
||||
background: 'var(--primary)',
|
||||
border: '2px solid var(--surface)',
|
||||
flexShrink: 0,
|
||||
}} />
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
<div className="global-bar-brand">
|
||||
<img src={logoUrl || '/icons/rosterchirp.png'} alt={appName} className="global-bar-logo" />
|
||||
|
||||
@@ -83,3 +83,12 @@
|
||||
color: var(--primary);
|
||||
}
|
||||
.nav-drawer-item.active:hover { background: var(--primary-light); }
|
||||
|
||||
.nav-drawer-unread-dot {
|
||||
margin-left: auto;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 50%;
|
||||
background: var(--primary);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ const NAV_ICON = {
|
||||
settings: <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><circle cx="12" cy="12" r="3"/><path d="M19.07 4.93l-1.41 1.41M5.34 18.66l-1.41 1.41M12 2v2M12 20v2M4.93 4.93l1.41 1.41M18.66 18.66l1.41 1.41M2 12h2M20 12h2"/></svg>,
|
||||
};
|
||||
|
||||
export default function NavDrawer({ open, onClose, onMessages, onGroupMessages, onSchedule, onScheduleManager, onBranding, onSettings, onUsers, onGroupManager, onHostPanel, features = {}, currentPage = 'chat', isMobile = false }) {
|
||||
export default function NavDrawer({ open, onClose, onMessages, onGroupMessages, onSchedule, onScheduleManager, onBranding, onSettings, onUsers, onGroupManager, onHostPanel, features = {}, currentPage = 'chat', isMobile = false, unreadMessages = false, unreadGroupMessages = false }) {
|
||||
const { user } = useAuth();
|
||||
const drawerRef = useRef(null);
|
||||
const isAdmin = user?.role === 'admin';
|
||||
@@ -36,7 +36,7 @@ export default function NavDrawer({ open, onClose, onMessages, onGroupMessages,
|
||||
}, [open, onClose]);
|
||||
|
||||
const item = (icon, label, onClick, opts = {}) => {
|
||||
const { active, disabled, badge } = opts;
|
||||
const { active, disabled, badge, dot } = opts;
|
||||
return (
|
||||
<button
|
||||
className={`nav-drawer-item${active ? ' active' : ''}${disabled ? ' disabled' : ''}`}
|
||||
@@ -46,6 +46,7 @@ export default function NavDrawer({ open, onClose, onMessages, onGroupMessages,
|
||||
{icon}
|
||||
<span>{label}</span>
|
||||
{badge && <span className="nav-drawer-badge">{badge}</span>}
|
||||
{dot && <span className="nav-drawer-unread-dot" />}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -64,8 +65,8 @@ export default function NavDrawer({ open, onClose, onMessages, onGroupMessages,
|
||||
</div>
|
||||
|
||||
{/* User section */}
|
||||
{item(NAV_ICON.messages, 'Messages', onMessages, { active: currentPage === 'chat' })}
|
||||
{hasUserGroups && item(NAV_ICON.groupmessages, 'Group Messages', onGroupMessages, { active: currentPage === 'groupmessages' })}
|
||||
{item(NAV_ICON.messages, 'Messages', onMessages, { active: currentPage === 'chat', dot: unreadMessages })}
|
||||
{hasUserGroups && item(NAV_ICON.groupmessages, 'Group Messages', onGroupMessages, { active: currentPage === 'groupmessages', dot: unreadGroupMessages })}
|
||||
{features.scheduleManager && item(NAV_ICON.schedules, 'Schedules', onSchedule, { active: currentPage === 'schedule' })}
|
||||
|
||||
{/* Admin section */}
|
||||
|
||||
Reference in New Issue
Block a user