From 400dd0b6cc5dc4f5ae4b15aaba384c7c61f550f4 Mon Sep 17 00:00:00 2001 From: samindiii Date: Sun, 18 May 2025 16:52:05 +1000 Subject: [PATCH 1/3] feat: add notification component to display in-system notifications for students on the homepage --- .../notifications-button.component.css | 78 +++++++++++++++++++ .../notifications-button.component.html | 35 +++++++++ .../notifications-button.component.spec.ts | 23 ++++++ .../notifications-button.component.ts | 69 ++++++++++++++++ 4 files changed, 205 insertions(+) create mode 100644 src/app/common/header/notifications-button/notifications-button.component.css create mode 100644 src/app/common/header/notifications-button/notifications-button.component.html create mode 100644 src/app/common/header/notifications-button/notifications-button.component.spec.ts create mode 100644 src/app/common/header/notifications-button/notifications-button.component.ts diff --git a/src/app/common/header/notifications-button/notifications-button.component.css b/src/app/common/header/notifications-button/notifications-button.component.css new file mode 100644 index 0000000000..19a0edc5cb --- /dev/null +++ b/src/app/common/header/notifications-button/notifications-button.component.css @@ -0,0 +1,78 @@ +.notification-panel { + position: absolute; + top: 60px; + right: 20px; + width: 400px; + max-height: 70vh; + background: white; + border: 1px solid #ccc; + border-radius: 6px; + box-shadow: 0 6px 18px rgba(0, 0, 0, 0.15); + z-index: 1000; + overflow-y: auto; + padding: 20px 16px 16px; + scrollbar-width: thin; + scrollbar-color: #ccc transparent; +} + +.notification-panel::-webkit-scrollbar { + width: 6px; +} + +.notification-panel::-webkit-scrollbar-thumb { + background-color: #ccc; + border-radius: 10px; +} + +.notification-content { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + gap: 8px; +} + +.notification-content span { + flex: 1; + margin-right: 8px; + white-space: normal; + overflow-wrap: anywhere; + word-break: break-word; +} + +.delete-all-container { + display: flex; + justify-content: center; + margin-top: 4px; +} + +.notification-button { + position: relative; +} + +.notification-panel mat-list-item { + border-bottom: 1px solid #e0e0e0; + padding-bottom: 8px; + margin-bottom: 8px; +} + +.notification-badge { + position: absolute; + top: 4px; + right: 4px; + background: red; + color: white; + font-size: 10px; + font-weight: bold; + border-radius: 50%; + padding: 2px 6px; + line-height: 1; + min-width: 16px; + text-align: center; +} + + + + + + diff --git a/src/app/common/header/notifications-button/notifications-button.component.html b/src/app/common/header/notifications-button/notifications-button.component.html new file mode 100644 index 0000000000..0fa383c179 --- /dev/null +++ b/src/app/common/header/notifications-button/notifications-button.component.html @@ -0,0 +1,35 @@ + + + +
+ + +
+ {{ note.message }} + +
+
+ + + + No notifications + +
+ +
+ +
+ +
+ +
+
+ + + + diff --git a/src/app/common/header/notifications-button/notifications-button.component.spec.ts b/src/app/common/header/notifications-button/notifications-button.component.spec.ts new file mode 100644 index 0000000000..7dedd16e77 --- /dev/null +++ b/src/app/common/header/notifications-button/notifications-button.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { NotificationsButtonComponent } from './notifications-button.component'; + +describe('NotificationsButtonComponent', () => { + let component: NotificationsButtonComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NotificationsButtonComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(NotificationsButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/common/header/notifications-button/notifications-button.component.ts b/src/app/common/header/notifications-button/notifications-button.component.ts new file mode 100644 index 0000000000..9c19c9077f --- /dev/null +++ b/src/app/common/header/notifications-button/notifications-button.component.ts @@ -0,0 +1,69 @@ +// import { Component, ElementRef, HostListener, ViewChild } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { AppInjector } from 'src/app/app-injector'; +import { DoubtfireConstants } from 'src/app/config/constants/doubtfire-constants'; + +// Define structure of a Notification object +interface Notification { + id: number; + message: string; +} + +@Component({ + selector: 'f-notifications-button', + templateUrl: './notifications-button.component.html', + styleUrls: ['./notifications-button.component.css'] +}) +export class NotificationsButtonComponent implements OnInit { + + // Tracks whether the notifications dropdown is visible + showNotifications = false; + + // List of notifications to be displayed + notifications: Notification[] = []; + + private readonly API_URL = AppInjector.get(DoubtfireConstants).API_URL; + constructor(private http: HttpClient) {} + + ngOnInit() { + this.loadNotifications(); + } + + // Toggle the visibility of the notifications dropdown + toggleNotifications() { + this.showNotifications = !this.showNotifications; + console.log('showNotifications toggled:', this.showNotifications); + } + + // Fetch notifications from the API + loadNotifications() { + this.http.get(`${this.API_URL}/notifications`).subscribe({ + next: data => this.notifications = data, + error: err => console.error('Error loading notifications', err) + }); + } + + // Remove a specific notification by ID + dismissNotification(notificationId: number) { + console.log('Dismissed notification with ID:', notificationId); + this.http.delete(`${this.API_URL}/notifications/${notificationId}`).subscribe({ + next: () => { + this.notifications = this.notifications.filter(note => note.id !== notificationId); + }, + error: err => console.error('Error deleting notification', err) + }); + } + + // Delete all notifications + deleteAllNotifications() { + console.log('All notifications deleted'); + this.http.delete(`${this.API_URL}/notifications`).subscribe({ + next: () => { + this.notifications = []; + }, + error: err => console.error('Error deleting all notifications', err) + }); + } + +} From cb405923d892f2e19a0560462b66324105a963c6 Mon Sep 17 00:00:00 2001 From: samindiii Date: Sun, 18 May 2025 16:53:12 +1000 Subject: [PATCH 2/3] feat: update header component to include the notification panel --- src/app/common/header/header.component.html | 4 ++++ src/app/doubtfire-angular.module.ts | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/app/common/header/header.component.html b/src/app/common/header/header.component.html index bac6b77c07..d33d403c62 100644 --- a/src/app/common/header/header.component.html +++ b/src/app/common/header/header.component.html @@ -34,6 +34,10 @@ + @if (currentUser.role === 'Student') { + + } + @if (currentUser.role === 'Admin' || currentUser.role === 'Convenor') {