From 5ed49368989f827590e75e42fe94af30e6b733ae Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sat, 15 Aug 2026 03:47:46 +0400 Subject: [PATCH] feat: UserNotificationService supports click-to-navigate toasts --- .../floating-notifications.component.html | 9 +++++-- .../floating-notifications.component.ts | 11 +++++++- .../user-notification.service.spec.ts | 26 +++++++++++++++++++ .../services/user-notification.service.ts | 7 +++-- 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 src/app/features/website/user-experience/services/user-notification.service.spec.ts diff --git a/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.html b/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.html index 899418e..5d47d7d 100644 --- a/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.html +++ b/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.html @@ -1,9 +1,14 @@ @if (notifications().length > 0) { diff --git a/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.ts b/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.ts index 822de70..39a4fe0 100644 --- a/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.ts +++ b/src/app/features/website/user-experience/components/floating-notifications/floating-notifications.component.ts @@ -1,5 +1,6 @@ import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; -import { UserNotificationService } from '../../services/user-notification.service'; +import { Router } from '@angular/router'; +import { UserNotification, UserNotificationService } from '../../services/user-notification.service'; import { TranslatePipe } from '../../../../../i18n/translate.pipe'; @Component({ @@ -12,10 +13,18 @@ import { TranslatePipe } from '../../../../../i18n/translate.pipe'; }) export class FloatingNotificationsComponent { private readonly notificationsService = inject(UserNotificationService); + private readonly router = inject(Router); readonly notifications = this.notificationsService.notifications; dismiss(id: string): void { this.notificationsService.dismiss(id); } + + navigate(note: UserNotification): void { + if (note.route) { + void this.router.navigate(note.route); + } + this.dismiss(note.id); + } } diff --git a/src/app/features/website/user-experience/services/user-notification.service.spec.ts b/src/app/features/website/user-experience/services/user-notification.service.spec.ts new file mode 100644 index 0000000..f58cdac --- /dev/null +++ b/src/app/features/website/user-experience/services/user-notification.service.spec.ts @@ -0,0 +1,26 @@ +import { TestBed } from '@angular/core/testing'; +import { UserNotificationService } from './user-notification.service'; + +describe('UserNotificationService', () => { + let service: UserNotificationService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(UserNotificationService); + }); + + it('stores the route on the notification when provided', () => { + service.show('New order #1042', 'info', 4000, ['en', 'backoffice', 'orders', 'ord_1']); + + const [note] = service.notifications(); + expect(note.message).toBe('New order #1042'); + expect(note.route).toEqual(['en', 'backoffice', 'orders', 'ord_1']); + }); + + it('leaves route undefined when not provided', () => { + service.show('Saved'); + + const [note] = service.notifications(); + expect(note.route).toBeUndefined(); + }); +}); diff --git a/src/app/features/website/user-experience/services/user-notification.service.ts b/src/app/features/website/user-experience/services/user-notification.service.ts index 05a9728..2b0ca04 100644 --- a/src/app/features/website/user-experience/services/user-notification.service.ts +++ b/src/app/features/website/user-experience/services/user-notification.service.ts @@ -6,6 +6,8 @@ export interface UserNotification { id: string; message: string; type: UserNotificationType; + /** Route to navigate to when the notification is clicked. Absent means not clickable. */ + route?: string[]; } @Injectable({ providedIn: 'root' }) @@ -14,11 +16,12 @@ export class UserNotificationService { readonly notifications = this.state.asReadonly(); - show(message: string, type: UserNotificationType = 'info', durationMs: number = 2500): void { + show(message: string, type: UserNotificationType = 'info', durationMs: number = 2500, route?: string[]): void { const next: UserNotification = { id: `note-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, message, - type + type, + ...(route ? { route } : {}), }; this.state.update(items => [next, ...items].slice(0, 4));