Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.html	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.html	(working copy)
@@ -1 +1,18 @@
-<p>notification works!</p>
+<div class="tab-container">
+  <mat-tab-group animationDuration="0ms">
+    <mat-tab label="Notification Channel">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-notification-channels/>
+        </div>
+      </ng-template>
+    </mat-tab>
+    <mat-tab label="Notification Settings">
+      <ng-template matTabContent>
+        <div class="tab-content">
+          <app-notification-settings/>
+        </div>
+      </ng-template>
+    </mat-tab>
+  </mat-tab-group>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.ts	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/notification/notification.ts	(working copy)
@@ -1,8 +1,15 @@
-import { Component } from '@angular/core';
+import {Component} from '@angular/core';
+import {NotificationChannels} from '../sub-components/notification-channels/notification-channels';
+import {NotificationSettings} from '../sub-components/notification-settings/notification-settings';
+import {SharedModule} from '../../shared/shared-module';
 
 @Component({
   selector: 'app-notification',
-  imports: [],
+  imports: [
+    SharedModule,
+    NotificationChannels,
+    NotificationSettings
+  ],
   templateUrl: './notification.html',
   styleUrl: './notification.scss'
 })
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/add-notification-channel.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/add-notification-channel.html	(nonexistent)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/add-notification-channel.html	(working copy)
@@ -0,0 +1,197 @@
+<h2 mat-dialog-title>Notification Channel</h2>
+
+<mat-dialog-content>
+  <form
+    (ngSubmit)="onSubmit()"
+    [formGroup]="nChannelForm"
+  >
+    <div class="form-field-wrapper">
+      <label for="name" class="form-label">Name *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <input
+          id="name"
+          formControlName="name"
+          matInput
+          placeholder="Name"
+          type="text"
+        />
+        @if (nChannelForm.get('name')?.invalid && nChannelForm.get('name')?.touched) {
+          <mat-error>
+            @if (nChannelForm.get('name')?.errors?.['required']) {
+              Name is required.
+            } @else if (nChannelForm.get('name')?.errors) {
+              Invalid name format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="type" class="form-label">Type *</label>
+      <mat-form-field appearance="outline" subscriptSizing="dynamic">
+        <mat-select formControlName="type">
+          @for (_type of ntype; track _type) {
+            <mat-option [value]="_type.value">{{ _type.displayName }}</mat-option>
+          }
+        </mat-select>
+        @if (nChannelForm.get('type')?.invalid && nChannelForm.get('type')?.touched) {
+          <mat-error>
+            @if (nChannelForm.get('type')?.errors?.['required']) {
+              Notification type is required.
+            } @else {
+              Invalid notification format.
+            }
+          </mat-error>
+        }
+      </mat-form-field>
+    </div>
+    <div class="form-field-wrapper">
+      <label for="default" class="form-label">Default</label>
+      <mat-slide-toggle formControlName="default"></mat-slide-toggle>
+      <mat-hint>Use this Notification for all alerts.</mat-hint>
+    </div>
+    @if (this.nChannelForm.value.type === 'email') {
+      <div class="form-field-wrapper">
+        <label for="singleEmail" class="form-label">Single Email</label>
+        <mat-slide-toggle formControlName="singleEmail"></mat-slide-toggle>
+        <mat-hint>Send a single email to all recipients.</mat-hint>
+      </div>
+      <div class="form-field-wrapper">
+        <label for="recipients" class="form-label">Recipients</label>
+        <mat-form-field appearance="outline" subscriptSizing="dynamic">
+          <mat-select formControlName="recipients" multiple>
+            @for (_user of adminUsers; track _user) {
+              <mat-option [value]="_user.username">{{ _user.username }}</mat-option>
+            }
+          </mat-select>
+          @if (nChannelForm.get('recipients')?.invalid && nChannelForm.get('recipients')?.touched) {
+            <mat-error>
+              @if (nChannelForm.get('recipients')?.errors?.['required']) {
+                Recipient is required.
+              } @else {
+                Invalid recipient.
+              }
+            </mat-error>
+          }
+        </mat-form-field>
+      </div>
+      <div class="button-container-center">
+        <button
+          type="button"
+          mat-raised-button
+          color="primary"
+          (click)="testEmail()">
+          Send Test Email
+        </button>
+      </div>
+    } @else {
+      <div class="form-field-wrapper">
+        <label for="url" class="form-label">URL *</label>
+        <mat-form-field appearance="outline" subscriptSizing="dynamic">
+          <input
+            id="url"
+            formControlName="url"
+            matInput
+            placeholder="URL"
+            type="text"
+          />
+          @if (nChannelForm.get('url')?.invalid && nChannelForm.get('url')?.touched) {
+            <mat-error>
+              @if (nChannelForm.get('url')?.errors?.['required']) {
+                URL is required.
+              } @else if (nChannelForm.get('url')?.errors) {
+                Invalid url format.
+              }
+            </mat-error>
+          }
+        </mat-form-field>
+      </div>
+      <div class="form-field-wrapper">
+        <label for="httpMethod" class="form-label">HTTP Method</label>
+        <mat-form-field appearance="outline" subscriptSizing="dynamic">
+          <mat-select formControlName="httpMethod">
+            @for (_method of httpMethods; track _method) {
+              <mat-option [value]="_method.value">{{ _method.displayName }}</mat-option>
+            }
+          </mat-select>
+          @if (nChannelForm.get('httpMethod')?.invalid && nChannelForm.get('httpMethod')?.touched) {
+            <mat-error>
+              @if (nChannelForm.get('httpMethod')?.errors?.['required']) {
+                HTTP Method is required.
+              } @else {
+                Invalid HTTP method.
+              }
+            </mat-error>
+          }
+        </mat-form-field>
+      </div>
+      <div class="form-field-wrapper">
+        <label for="username" class="form-label">Username</label>
+        <mat-form-field appearance="outline" subscriptSizing="dynamic">
+          <input
+            id="username"
+            formControlName="username"
+            matInput
+            placeholder="Username"
+            type="text"
+          />
+          <mat-hint>HTTP Basic Authorization</mat-hint>
+          @if (nChannelForm.get('username')?.invalid && nChannelForm.get('username')?.touched) {
+            <mat-error>
+              @if (nChannelForm.get('username')?.errors?.['required']) {
+                Username is required.
+              } @else if (nChannelForm.get('username')?.errors) {
+                Invalid username format.
+              }
+            </mat-error>
+          }
+        </mat-form-field>
+      </div>
+      <div class="form-field-wrapper">
+        <label for="password" class="form-label">Password</label>
+        <mat-form-field appearance="outline" subscriptSizing="dynamic">
+          <input
+            id="password"
+            formControlName="password"
+            matInput
+            placeholder="Password"
+            type="password"
+          />
+          <mat-hint>HTTP Basic Authorization</mat-hint>
+          @if (nChannelForm.get('password')?.invalid && nChannelForm.get('password')?.touched) {
+            <mat-error>
+              @if (nChannelForm.get('password')?.errors?.['required']) {
+                Password is required.
+              } @else if (nChannelForm.get('password')?.errors) {
+                Invalid password format.
+              }
+            </mat-error>
+          }
+        </mat-form-field>
+      </div>
+      <div class="button-container-center">
+        <button
+          type="button"
+          mat-raised-button
+          color="primary"
+          (click)="testWebHook()">
+          Send Test Webhook
+        </button>
+      </div>
+    }
+  </form>
+</mat-dialog-content>
+<mat-dialog-actions>
+  <button
+    mat-button
+    color="basic"
+    (click)="onCancel()">
+    Cancel
+  </button>
+  <button
+    mat-raised-button
+    color="primary"
+    (click)="onSubmit()">
+    Submit
+  </button>
+</mat-dialog-actions>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.html	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.html	(working copy)
@@ -1 +1,55 @@
-<p>notification-channels works!</p>
+<div>
+  <mat-card class="page-card-1" appearance="filled">
+    <mat-card-header>
+      <mat-card-title>Notification Channel</mat-card-title>
+    </mat-card-header>
+    <mat-card-content>
+      <div class="button-container">
+        <button mat-raised-button (click)="addNotificationChannel()">Add</button>
+      </div>
+      <div class="table-container">
+        <table mat-table [dataSource]="dataSource" class="mat-elevation-z1">
+          <ng-container matColumnDef="serial">
+            <th mat-header-cell *matHeaderCellDef> No.</th>
+            <td mat-cell *matCellDef="let element; let i = index;"> {{ getGlobalSerial(i) }}</td>
+          </ng-container>
+          <ng-container matColumnDef="name">
+            <th mat-header-cell *matHeaderCellDef> Channel Name</th>
+            <td mat-cell *matCellDef="let element">
+              <a class="a-link-color" (click)="addNotificationChannel(element)">{{ element.name }}</a>
+            </td>
+          </ng-container>
+          <ng-container matColumnDef="type">
+            <th mat-header-cell *matHeaderCellDef> Channel Type</th>
+            <td mat-cell *matCellDef="let element"> {{ element.type | titlecase }}</td>
+          </ng-container>
+          <ng-container matColumnDef="default">
+            <th mat-header-cell *matHeaderCellDef> Default</th>
+            <td mat-cell *matCellDef="let element">
+              @if (element.is_default) {
+                <fa-icon [icon]="['far', 'check-circle']" class="success-icon"></fa-icon>
+              } @else {
+                <fa-icon [icon]="['far', 'xmark-circle']" class="delete-icon"></fa-icon>
+              }
+            </td>
+          </ng-container>
+          <ng-container matColumnDef="action">
+            <th mat-header-cell *matHeaderCellDef class="action-header w-10"> Action</th>
+            <td mat-cell *matCellDef="let element">
+              <div class="row-action a-link">
+                <fa-icon [icon]="['far', 'trash-can']" size="lg" class="delete-icon" matTooltip="Delete Device"
+                         (click)="deleteNotificationChannel(element)"></fa-icon>
+              </div>
+            </td>
+          </ng-container>
+          <tr mat-header-row *matHeaderRowDef="nChannelColumns"></tr>
+          <tr mat-row *matRowDef="let row; columns: nChannelColumns;"></tr>
+          <tr class="mat-row table-no-data" *matNoDataRow>
+            <td class="mat-cell" colspan="4">No results found.</td>
+          </tr>
+        </table>
+        <mat-paginator [pageSizeOptions]="[10, 15, 20]" showFirstLastButtons></mat-paginator>
+      </div>
+    </mat-card-content>
+  </mat-card>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.scss	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.scss	(working copy)
@@ -0,0 +1,20 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.ts	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-channels/notification-channels.ts	(working copy)
@@ -1,11 +1,352 @@
-import { Component } from '@angular/core';
+import {ChangeDetectorRef, Component, inject, OnInit, ViewChild} from '@angular/core';
+import {SharedModule} from '../../../shared/shared-module';
+import {SystemService} from '../../../services/system-service';
+import {MatTableDataSource} from '@angular/material/table';
+import {take, takeUntil} from 'rxjs/operators';
+import {NotificationService} from '../../../services/notification';
+import {Confirmation} from '../../../services/confirmation';
+import {MAT_DIALOG_DATA, MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {Subject} from 'rxjs';
+import {MatPaginator} from '@angular/material/paginator';
 
 @Component({
   selector: 'app-notification-channels',
-  imports: [],
+  imports: [
+    SharedModule,
+  ],
   templateUrl: './notification-channels.html',
   styleUrl: './notification-channels.scss'
 })
-export class NotificationChannels {
+export class NotificationChannels implements OnInit {
 
+  nChannelColumns: string[] = ['serial', 'name', 'type', 'default', 'action'];
+  dataSource = new MatTableDataSource([]);
+
+  totalResults = 0;
+  currentPageNumber: number = -1;
+  @ViewChild(MatPaginator) paginator!: MatPaginator;
+
+  dialog = inject(MatDialog);
+  dialogConfig = new MatDialogConfig();
+
+  constructor(
+    private systemService: SystemService,
+    private notification: NotificationService,
+    private cdRef: ChangeDetectorRef,
+    private confirmationService: Confirmation
+  ) {
+  }
+
+  ngOnInit() {
+    setTimeout(() => {
+      this.getNotificationChannels(-1);
+    });
+    this.dataSource.paginator = this.paginator;
+  }
+
+  getNotificationChannels(pageSize: number = -1) {
+    this.systemService.getNotificationChannels(pageSize)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result?.data) {
+            this.totalResults = result.data.total;
+            this.dataSource = new MatTableDataSource(result.data?.data);
+            this.dataSource.paginator = this.paginator;
+          }
+          this.cdRef.detectChanges();
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  getGlobalSerial(index: number): number {
+    if (this.paginator) {
+      return this.paginator.pageIndex * this.paginator.pageSize + index + 1;
+    }
+    return index + 1;
+  }
+
+  addNotificationChannel(payload: any = {}) {
+    this.dialogConfig.position = {
+      bottom: '0px', right: '0px',
+    }
+    this.dialogConfig.disableClose = true;
+    this.dialogConfig.width = '60%';
+    this.dialogConfig.height = '80%';
+    this.dialogConfig.data = payload;
+    const dialogRef = this.dialog.open(AddNotificationChannelDialog, this.dialogConfig);
+    dialogRef.afterClosed().subscribe((isAdded: boolean) => {
+      if (isAdded) {
+        this.getNotificationChannels(this.currentPageNumber);
+      }
+    })
+  }
+
+  deleteNotificationChannel(_channel: any) {
+    let confirmMsg = `Are you sure you want to delete "${_channel?.name}"? This action cannot be undone.`
+    this.confirmationService.openConfirmDialog({
+      title: `Delete Notification Channel - ${_channel?.name}?`,
+      message: confirmMsg,
+      confirmButtonText: 'Yes, Delete It',
+      cancelButtonText: 'No, Keep It',
+      confirmButtonColor: 'warn',
+      cancelButtonColor: 'primary'
+    }).subscribe(result => {
+      if (result) {
+        this.systemService.deleteNotificationChannel(_channel?.id)
+          .pipe(take(1))
+          .subscribe({
+            next: (result: any) => {
+              if (result && (result?.code === 0)) {
+                this.getNotificationChannels(this.currentPageNumber);
+              } else {
+                this.notification.showError(result?.message);
+              }
+            },
+            error: (error: { message: string; }) => {
+              console.log(error);
+              this.notification.showError(error.message);
+            }
+          })
+      }
+    });
+  }
+
 }
+
+@Component({
+  selector: 'add-notification-channel',
+  templateUrl: './add-notification-channel.html',
+  imports: [SharedModule]
+})
+export class AddNotificationChannelDialog implements OnInit {
+
+  nChannelForm: FormGroup;
+  readonly data = inject(MAT_DIALOG_DATA);
+  readonly dialogRef = inject(MatDialogRef<AddNotificationChannelDialog>);
+
+  ntype = [
+    {value: 'email', displayName: 'Email'},
+    {value: 'webhook', displayName: 'WebHook'},
+  ]
+
+  httpMethods = [
+    {value: 'POST', displayName: 'POST'},
+    {value: 'PUT', displayName: 'PUT'},
+  ]
+  adminUsers: any = [];
+
+  private destroy$ = new Subject<void>();
+
+  constructor(
+    private systemService: SystemService,
+    private formBuilder: FormBuilder,
+    private cdRef: ChangeDetectorRef,
+    private notification: NotificationService,
+  ) {
+    this.nChannelForm = this.formBuilder.group({
+      name: ['', [Validators.required]],
+      type: ['email', [Validators.required]],
+      default: [false, [Validators.required]],
+      singleEmail: [true, [Validators.required]],
+      recipients: ['', [Validators.required]],
+      url: ['', [Validators.required]],
+      httpMethod: ["POST", [Validators.required]],
+      username: [''],
+      password: [''],
+    });
+  }
+
+  ngOnInit() {
+    setTimeout(() => {
+      this.getAdminUsers();
+    });
+    this.nChannelForm.get('type')?.valueChanges
+      .pipe(takeUntil(this.destroy$))
+      .subscribe(type => {
+        this.updateConditionalValidators(type);
+      });
+    this.updateConditionalValidators(this.nChannelForm.get('type')?.value);
+
+    this.nChannelForm.patchValue(this.data);
+    if (this.data.settings) {
+      this.nChannelForm.patchValue({
+        recipients: this.data.settings?.addresses,
+        singleEmail: this.data.settings?.singleEmail,
+        httpMethod: this.data.settings.httpMethod ?? 'POST',
+        url: this.data.settings?.url,
+        username: this.data.settings.username ?? '',
+        password: this.data.settings.password ?? '',
+      });
+    }
+  }
+
+  getAdminUsers() {
+    this.adminUsers = [];
+    this.systemService.getAdminUsers()
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          this.adminUsers = result;
+          this.cdRef.detectChanges();
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  testEmail() {
+    if (this.nChannelForm.invalid) {
+      console.log(this.nChannelForm.value);
+      this.nChannelForm.markAllAsTouched();
+      return;
+    }
+    let payload = {
+      id: this.data.id ?? 0,
+      is_default: this.nChannelForm.value.default,
+      name: this.nChannelForm.value.name,
+      type: this.nChannelForm.value.type,
+      settings: {
+        addresses: this.nChannelForm.value.recipients,
+        httpMethod: "POST",
+        singleEmail: this.nChannelForm.value.singleEmail,
+        uploadImage: true
+      }
+    };
+    this.systemService.sendTestEmail(payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && (result?.code === 0)) {
+            this.notification.showSuccess('Successfully sent the test email');
+          } else {
+            this.notification.showError(result?.message);
+          }
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  testWebHook() {
+    if (this.nChannelForm.invalid) {
+      console.log(this.nChannelForm.value);
+      this.nChannelForm.markAllAsTouched();
+      return;
+    }
+    let payload = {
+      id: this.data.id ?? 0,
+      is_default: this.nChannelForm.value.default,
+      name: this.nChannelForm.value.name,
+      type: this.nChannelForm.value.type,
+      settings: {
+        addresses: this.nChannelForm.value.recipients,
+        httpMethod: this.nChannelForm.value.httpMethod,
+        singleEmail: this.nChannelForm.value.singleEmail,
+        uploadImage: true,
+        url: this.nChannelForm.value.url,
+        username: this.nChannelForm.value.username,
+        password: this.nChannelForm.value.password,
+      }
+    };
+    this.systemService.sendTestWebhook(payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && (result?.code === 0)) {
+            this.notification.showSuccess('Successfully sent the test webhook');
+          } else {
+            this.notification.showError(result?.message);
+          }
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  onSubmit() {
+    if (this.nChannelForm.invalid) {
+      console.log(this.nChannelForm.value);
+      this.nChannelForm.markAllAsTouched();
+      return;
+    }
+    let payload = {
+      id: this.data.id ?? 0,
+      is_default: this.nChannelForm.value.default,
+      name: this.nChannelForm.value.name,
+      type: this.nChannelForm.value.type,
+      settings: {
+        addresses: this.nChannelForm.value.recipients,
+        httpMethod: this.nChannelForm.value.httpMethod,
+        singleEmail: this.nChannelForm.value.singleEmail,
+        uploadImage: true,
+        url: this.nChannelForm.value.url,
+        username: this.nChannelForm.value.username,
+        password: this.nChannelForm.value.password,
+      }
+    };
+    this.systemService.addNotificationChannel(payload)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && (result?.code === 0)) {
+            this.notification.showSuccess('Successfully updated the notification channel.');
+            this.dialogRef.close(true);
+          } else {
+            this.notification.showError(result?.message);
+          }
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  onCancel() {
+    this.dialogRef.close(false);
+  }
+
+  private updateConditionalValidators(type: string): void {
+    const singleEmailControl = this.nChannelForm.get('singleEmail');
+    const recipientsControl = this.nChannelForm.get('recipients');
+    const urlControl = this.nChannelForm.get('url');
+    const httpMethodControl = this.nChannelForm.get('httpMethod');
+
+    // Clear all conditional validators first to prevent accumulation
+    singleEmailControl?.clearValidators();
+    recipientsControl?.clearValidators();
+    urlControl?.clearValidators();
+    httpMethodControl?.clearValidators();
+
+    if (type === 'email') {
+      singleEmailControl?.setValidators(Validators.required);
+      recipientsControl?.setValidators(Validators.required);
+    } else if (type === 'webhook') {
+      urlControl?.setValidators(Validators.required);
+      httpMethodControl?.setValidators(Validators.required);
+    }
+
+    // Update validity for all controls that had their validators changed
+    singleEmailControl?.updateValueAndValidity();
+    recipientsControl?.updateValueAndValidity();
+    urlControl?.updateValueAndValidity();
+    httpMethodControl?.updateValueAndValidity();
+  }
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.html
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.html	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.html	(working copy)
@@ -1 +1,158 @@
-<p>notification-settings works!</p>
+<div>
+  <mat-card class="page-card-1" appearance="filled">
+    <mat-card-header>
+      <mat-card-title>SMTP Settings</mat-card-title>
+    </mat-card-header>
+    <mat-card-content>
+      <form
+        (ngSubmit)="onSubmit()"
+        [formGroup]="notificationForm"
+        class="common-form"
+      >
+        <div class="form-field-wrapper">
+          <label for="enabled" class="form-label">Enable SMTP</label>
+          <mat-slide-toggle formControlName="enabled"></mat-slide-toggle>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="host" class="form-label">SMTP Server *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="host"
+              formControlName="host"
+              matInput
+              placeholder="SMTP Server"
+              type="text"
+            />
+            @if (notificationForm.get('host')?.invalid && notificationForm.get('host')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('host')?.errors?.['required']) {
+                  SMTP server is required.
+                } @else if (notificationForm.get('host')?.errors) {
+                  Invalid SMTP server format.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="port" class="form-label">SMTP Port *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="port"
+              formControlName="port"
+              matInput
+              placeholder="SMTP Port"
+              type="number"
+            />
+            @if (notificationForm.get('port')?.invalid && notificationForm.get('port')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('port')?.errors?.['required']) {
+                  Port number is required.
+                } @else if (notificationForm.get('port')?.errors) {
+                  Invalid port number, should range from 0-65535.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="user" class="form-label">Username *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="user"
+              formControlName="user"
+              matInput
+              placeholder="Username"
+              type="text"
+            />
+            @if (notificationForm.get('user')?.invalid && notificationForm.get('user')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('user')?.errors?.['required']) {
+                  User is required.
+                } @else if (notificationForm.get('user')?.errors) {
+                  Invalid user format.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="password" class="form-label">Password *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="password"
+              formControlName="password"
+              matInput
+              placeholder="Password"
+              type="password"
+            />
+            @if (notificationForm.get('password')?.invalid && notificationForm.get('password')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('password')?.errors?.['required']) {
+                  Password is required.
+                } @else if (notificationForm.get('password')?.errors) {
+                  Invalid password format.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="from_address" class="form-label">Sender Email *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="from_address"
+              formControlName="from_address"
+              matInput
+              placeholder="Sender Email"
+              type="email"
+            />
+            @if (notificationForm.get('from_address')?.invalid && notificationForm.get('from_address')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('from_address')?.errors?.['required']) {
+                  Sender Email is required.
+                } @else if (notificationForm.get('from_address')?.errors) {
+                  Invalid email format.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <div class="form-field-wrapper">
+          <label for="from_name" class="form-label">Sender Name *</label>
+          <mat-form-field appearance="outline" subscriptSizing="dynamic">
+            <input
+              id="from_name"
+              formControlName="from_name"
+              matInput
+              placeholder="Sender Name"
+              type="text"
+            />
+            @if (notificationForm.get('from_name')?.invalid && notificationForm.get('from_name')?.touched) {
+              <mat-error>
+                @if (notificationForm.get('from_name')?.errors?.['required']) {
+                  Sender Name is required.
+                } @else if (notificationForm.get('from_name')?.errors) {
+                  Invalid sender name format.
+                }
+              </mat-error>
+            }
+          </mat-form-field>
+        </div>
+
+        <button
+          type="submit"
+          mat-raised-button
+          color="primary">
+          Submit
+        </button>
+      </form>
+    </mat-card-content>
+  </mat-card>
+</div>
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.scss	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.scss	(working copy)
@@ -0,0 +1,20 @@
+.page-card-1 {
+  width: 100%;
+  border-radius: 0;
+  background-color: inherit;
+  font-size: 14px !important;
+  mat-card-header {
+    color: #1170cf;
+  }
+}
+
+mat-card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 4px 10px;
+}
+
+mat-card-title {
+  font-size: medium;
+}
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.ts	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/components/sub-components/notification-settings/notification-settings.ts	(working copy)
@@ -1,11 +1,91 @@
-import { Component } from '@angular/core';
+import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
+import {SharedModule} from '../../../shared/shared-module';
+import {FormBuilder, FormGroup, Validators} from '@angular/forms';
+import {SystemService} from '../../../services/system-service';
+import {NotificationService} from '../../../services/notification';
+import {take} from 'rxjs/operators';
 
 @Component({
   selector: 'app-notification-settings',
-  imports: [],
+  imports: [
+    SharedModule
+  ],
   templateUrl: './notification-settings.html',
   styleUrl: './notification-settings.scss'
 })
-export class NotificationSettings {
+export class NotificationSettings implements OnInit {
 
+  notificationForm: FormGroup;
+
+  constructor(
+    private formBuilder: FormBuilder,
+    private cdRef: ChangeDetectorRef,
+    private systemService: SystemService,
+    private notification: NotificationService,
+  ) {
+    this.notificationForm = this.formBuilder.group({
+      "enabled": [false, [Validators.required]],
+      "host": ["127.0.0.1", [Validators.required]],
+      "port": [25, [Validators.required, Validators.min(0), Validators.max(65535)]],
+      "user": ["", [Validators.required]],
+      "password": ["", [Validators.required]],
+      "from_address": ["admin@localhost", [Validators.required, Validators.email]],
+      "from_name": ["admin", [Validators.required]],
+    })
+  }
+
+  ngOnInit() {
+    setTimeout(() => {
+      this.getNotificationSettings();
+    });
+  }
+
+  getNotificationSettings(): void {
+    this.systemService.getSMTPSettings()
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && result?.data) {
+            this.notificationForm.patchValue(result?.data);
+          }
+          this.cdRef.detectChanges();
+        },
+        error: (error: { message: string; }) => {
+          console.log(error);
+          this.notification.showError(error.message);
+          this.cdRef.detectChanges();
+        }
+      })
+  }
+
+  onSubmit(): void {
+    const {enabled} = this.notificationForm.value;
+
+    if (enabled && this.notificationForm.invalid) {
+      console.log(this.notificationForm.value);
+      this.notificationForm.markAllAsTouched();
+      return;
+    }
+
+    this.updateNotificationSettings();
+  }
+
+
+  updateNotificationSettings(): void {
+    this.systemService.updateSMTPSettings(this.notificationForm.value)
+      .pipe(take(1))
+      .subscribe({
+        next: (result: any) => {
+          if (result && (result?.code === 0)) {
+            this.notification.showSuccess(`SMTP settings updated successfully!`);
+            this.getNotificationSettings();
+          } else {
+            this.notification.showError(`Failed to update the SMTP settings.`);
+          }
+        },
+        error: () => {
+          this.notification.showError(`Failed to update the SMTP settings.`);
+        }
+      })
+  }
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts	(revision 2663)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/constants/api_urls.ts	(working copy)
@@ -62,4 +62,12 @@
   GET_TASK_AND_LOG_URL: `${PREFIX}/cm/get_task_and_log`,
   DELETE_TASK_URL: `${PREFIX}/api/cm/tasking/Tasks/_delete`,
   DELETE_ALL_TASKS_URL: `${PREFIX}/api/cm/tasking/Tasks/_perform`,
+  GET_SMTP_SETTINGS_URL: `${PREFIX}/composer/system/smtp`,
+  UPDATE_SMTP_SETTINGS_URL: `${PREFIX}/composer/system/smtp/update`,
+  GET_NOTIFICATION_CHANNELS_URL: `${PREFIX}/composer/notify/channel`,
+  DELETE_NOTIFICATION_CHANNEL_URL: `${PREFIX}/composer/notify/channel/remove/`,
+  GET_ADMIN_USERS_URL: `${PREFIX}/api/cm/system/user_mgmt/Administrator/_get_list_data`,
+  SEND_TEST_EMAIL_URL: `${PREFIX}/composer/notify/channel/test`,
+  SEND_TEST_WEBHOOK_URL: `${PREFIX}/composer/notify/channel/test`,
+  ADD_NOTIFICATION_CHANNEL_URL: `${PREFIX}/composer/notify/channel/store`,
 } as const; // Makes properties readonly
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/system-service.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/system-service.ts	(revision 2663)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/services/system-service.ts	(working copy)
@@ -271,5 +271,38 @@
       isFormData: true,
       csrfInFormData: true
     });
+  }
+
+  getSMTPSettings() {
+    return this.http.get(URLS.GET_SMTP_SETTINGS_URL);
+  }
+
+  updateSMTPSettings(payload: any) {
+    return this.http.post(URLS.UPDATE_SMTP_SETTINGS_URL, payload);
+  }
+
+  getNotificationChannels(pageSize: number = -1) {
+    return this.http.get(`${URLS.GET_NOTIFICATION_CHANNELS_URL}?page_size=${pageSize}`);
   }
+
+  deleteNotificationChannel(channelId: number) {
+    return this.http.post(`${URLS.DELETE_NOTIFICATION_CHANNEL_URL}/${channelId}`, {});
+  }
+
+  getAdminUsers() {
+    return this.http.get(URLS.GET_ADMIN_USERS_URL);
+  }
+
+  sendTestEmail(payload: any) {
+    return this.http.post(URLS.SEND_TEST_EMAIL_URL, payload);
+  }
+
+  sendTestWebhook(payload: any) {
+    return this.http.post(URLS.SEND_TEST_WEBHOOK_URL, payload);
+  }
+
+  addNotificationChannel(payload: any) {
+    return this.http.post(URLS.ADD_NOTIFICATION_CHANNEL_URL, payload);
+  }
+
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts	(revision 2663)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/app/shared/shared-module.ts	(working copy)
@@ -39,6 +39,7 @@
   faSave,
   faCalendar,
   faEdit,
+  faXmarkCircle
 } from '@fortawesome/free-regular-svg-icons';
 import {MatGridListModule} from '@angular/material/grid-list';
 import {MatFormFieldModule} from '@angular/material/form-field';
@@ -156,6 +157,7 @@
       faIdBadge,
       faCalendar,
       faEdit,
+      faXmarkCircle
     );
   }
 }
Index: /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss
===================================================================
--- /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss	(revision 2662)
+++ /branches/amp_4_0/src/webui/webui/htdocs/new/src/gui/src/styles.scss	(working copy)
@@ -268,6 +268,12 @@
   display: flex;
   justify-content: center;
   align-items: center;
+}
+
+.button-container-end {
+  display: flex;
+  justify-content: end;
+  align-items: end;
 }
 
 .warning {
