NotificationMenu
DomainBell icon button with unread count badge. Opens a dropdown panel showing notification items grouped by read/unread state with variant color dots, timestamps, and mark-all-read / view-all actions.
Notifications
3
<%- include('modules/domain/common/notification/NotificationMenu', {
items: notifications,
align: 'right',
onMarkAllRead: 'markAllRead',
viewAllHref: '/notifications'
}) %>
Notifications
No notifications
<%- include('modules/domain/common/notification/NotificationMenu', {
items: [],
align: 'right'
}) %>
<%
var _id = locals.id || 'notif-menu-' + Math.random().toString(36).substr(2, 9);
var _items = locals.items || [];
var _align = locals.align || 'right';
var _onMarkAllRead = locals.onMarkAllRead || ''; // optional href or JS handler string
var _onViewAll = locals.onViewAll || '';
var _markAllHref = locals.markAllHref || '';
var _viewAllHref = locals.viewAllHref || '';
var _className = locals.className || '';
var unreadCount = 0;
_items.forEach(function (n) { if (!n.read) unreadCount++; });
var variantDot = {
info: 'bg-info',
success: 'bg-success',
warning: 'bg-warning',
error: 'bg-error',
};
var alignClass = _align === 'right' ? 'right-0' : 'left-0';
%>
Notifications
<% if (unreadCount > 0) { %>
<%= unreadCount %>
<% } %>
<% if (unreadCount > 0 && (_onMarkAllRead || _markAllHref)) { %>
<% if (_markAllHref) { %>
Mark all read
<% } else { %>
<% } %>
<% } %>
<% if (_items.length === 0) { %>
No notifications
<% } else { %>
<% _items.forEach(function (item) { %>
<% var dotCls = item.read ? 'bg-transparent' : (variantDot[item.variant || 'info'] || variantDot.info); %>
<% var titleCls = item.read ? 'text-text-secondary' : 'text-text-primary font-medium'; %>
<% var btnExtra = !item.read ? ' bg-primary-subtle/40' : ''; %>
<% }); %>
<% } %>
<% if (_onViewAll || _viewAllHref) { %>
<% if (_viewAllHref) { %>
View all notifications
<% } else { %>
<% } %>
<% } %>