import { Component, DestroyRef, OnInit, inject, signal } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { ActivatedRoute, Router } from '@angular/router'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; import { MatListModule } from '@angular/material/list'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { NotificationItem } from '../../../models/notification.model'; import { NotificationsApi } from '../../../core/notifications/notifications-api'; import { NotificationsStore } from '../../../core/notifications/notifications-store'; import { notificationIcon, notificationLabel, notificationTarget, } from '../../../core/notifications/notification-presentation'; const PAGE_SIZE = 20; @Component({ selector: 'app-notifications', imports: [MatButtonModule, MatIconModule, MatListModule, MatProgressSpinnerModule], templateUrl: './notifications.html', styleUrl: './notifications.scss', }) export class Notifications implements OnInit { private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); private readonly api = inject(NotificationsApi); private readonly notificationsStore = inject(NotificationsStore); private readonly destroyRef = inject(DestroyRef); protected readonly items = signal([]); protected readonly loading = signal(false); protected readonly hasNextPage = signal(false); private teamId: number | null = null; private page = 1; ngOnInit(): void { const parentRoute = this.route.parent; if (!parentRoute) return; parentRoute.paramMap.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((params) => { const raw = params.get('id'); const id = raw === null ? Number.NaN : Number(raw); if (Number.isInteger(id) && id > 0 && id !== this.teamId) { this.teamId = id; this.page = 1; this.items.set([]); this.hasNextPage.set(false); this.loadPage(); } }); } protected notificationLabel(item: NotificationItem): string { return notificationLabel(item); } protected notificationIcon(item: NotificationItem): string { return notificationIcon(item.event); } protected loadMore(): void { this.page += 1; this.loadPage(); } protected onItemClick(item: NotificationItem): void { if (this.teamId === null) return; const teamId = this.teamId; this.notificationsStore.markRead(teamId, item.id); this.items.update((current) => current.map((entry) => (entry.id === item.id ? { ...entry, read: true } : entry)), ); void this.router.navigate(notificationTarget(item, teamId)); } private loadPage(): void { if (this.teamId === null) return; const teamId = this.teamId; this.loading.set(true); this.api.loadNotifications(teamId, { page: this.page, limit: PAGE_SIZE }).subscribe({ next: (result) => { this.items.update((current) => [...current, ...result.data]); this.hasNextPage.set(result.hasNextPage); this.loading.set(false); }, error: () => this.loading.set(false), }); } }