Angular 19 component library for notifications & communication: - ntf-bell: notification bell with badge count and shake animation - ntf-feed / ntf-feed-item: real-time notification feed with grouping - ntf-center: full notification center with category filter tabs - ntf-inbox / ntf-inbox-item: two-column inbox with search and detail - ntf-comment / ntf-thread: comment threads with replies and reactions - ntf-mention-input: text input with @mention autocomplete - ntf-empty-state: empty state placeholder - ntf-item-def: custom template directive for notification items Includes signal-based services, SCSS design tokens with dark mode, utility functions, and full TypeScript type definitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
import { Injectable, inject, signal, computed } from '@angular/core';
|
|
import { NOTIFICATION_CONFIG } from '../providers/notification-config.provider';
|
|
import type { NtfNotification, NtfGroup } from '../types/notification.types';
|
|
import { groupByDate } from '../utils/time.utils';
|
|
|
|
@Injectable()
|
|
export class NotificationService {
|
|
private config = inject(NOTIFICATION_CONFIG);
|
|
|
|
readonly notifications = signal<NtfNotification[]>([]);
|
|
|
|
readonly unreadCount = computed(() =>
|
|
this.notifications().filter((n) => n.status === 'unread').length,
|
|
);
|
|
|
|
readonly grouped = computed<NtfGroup[]>(() => {
|
|
const items = this.notifications().filter((n) => n.status !== 'archived');
|
|
const dateGroups = groupByDate(items);
|
|
|
|
return dateGroups.map((g) => ({
|
|
id: g.label.toLowerCase().replace(/\s+/g, '-'),
|
|
label: g.label,
|
|
notifications: g.items,
|
|
}));
|
|
});
|
|
|
|
add(notification: NtfNotification): void {
|
|
this.notifications.update((list) => [notification, ...list]);
|
|
}
|
|
|
|
markRead(notificationId: string): void {
|
|
this.notifications.update((list) =>
|
|
list.map((n) => (n.id === notificationId ? { ...n, status: 'read' as const } : n)),
|
|
);
|
|
}
|
|
|
|
markAllRead(): void {
|
|
this.notifications.update((list) =>
|
|
list.map((n) => (n.status === 'unread' ? { ...n, status: 'read' as const } : n)),
|
|
);
|
|
}
|
|
|
|
archive(notificationId: string): void {
|
|
this.notifications.update((list) =>
|
|
list.map((n) => (n.id === notificationId ? { ...n, status: 'archived' as const } : n)),
|
|
);
|
|
}
|
|
|
|
remove(notificationId: string): void {
|
|
this.notifications.update((list) => list.filter((n) => n.id !== notificationId));
|
|
}
|
|
|
|
clear(): void {
|
|
this.notifications.set([]);
|
|
}
|
|
}
|