From 7b88bc090a7f075c5c93e6c2b71ad09a72cd92eb Mon Sep 17 00:00:00 2001 From: Constantin Simonis Date: Wed, 15 Jan 2025 13:31:19 +0100 Subject: [PATCH 1/2] add search bar --- src/app/employee/table/table.component.html | 14 +++++++---- src/app/employee/table/table.component.ts | 26 +++++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/app/employee/table/table.component.html b/src/app/employee/table/table.component.html index 7305706..a8139b4 100644 --- a/src/app/employee/table/table.component.html +++ b/src/app/employee/table/table.component.html @@ -1,4 +1,10 @@
+ + + @defer { @if (employees$ | async; as employees) {
@@ -38,14 +44,14 @@ Actions
- - -
- - @if (employees) { -
- - - - - - - - - - - - - -
Name -
-
- - {{ employee.firstName[0] }}{{ employee.lastName[0] }} - -
- -
-
Actions -
- - -
-
+ @if (employees$ | async; as employees) { +
+
+
+

Employee Directory

+ + search + +
+
- } @else { - - - people -

No employees found

-
-
- } +
+ +
+ + @if (employees) { +
+ + + + + + + + + + + + + +
Name +
+
+ + {{ employee.firstName[0] }}{{ employee.lastName[0] }} + +
+ +
+
Actions +
+ + +
+
+
+ } @else { + + + people +

No employees found

+
+
} - } @placeholder { -
-
-
-
-
-
-
-
-
- @for (i of [1, 2, 3]; track i) { -
- } -
-
-
-
- } @error { -
-
- error -
-

There was an error loading the employees.

-

Please try refreshing the page.

-
-
-
- } @loading { -
- -
+
} -
+ } @placeholder { +
+
+
+
+
+
+
+
+
+ @for (i of [1, 2, 3]; track i) { +
+ } +
+
+
+
+ } @error { +
+
+ error +
+

There was an error loading the employees.

+

Please try refreshing the page.

+
+
+
+ } @loading { +
+ +
+ } + \ No newline at end of file diff --git a/src/app/employee/table/table.component.ts b/src/app/employee/table/table.component.ts index 5927afe..7104b73 100644 --- a/src/app/employee/table/table.component.ts +++ b/src/app/employee/table/table.component.ts @@ -1,6 +1,6 @@ import {Component, inject, OnInit} from '@angular/core'; import {CommonModule} from '@angular/common'; -import {catchError, filter, map, Observable, of, retry} from 'rxjs'; +import {catchError, debounceTime, distinctUntilChanged, filter, map, Observable, of, retry, Subject} from 'rxjs'; import {HttpErrorResponse} from '@angular/common/http'; import {Employee} from '../Employee'; @@ -20,7 +20,8 @@ import EmployeeApiService from "../../services/employee-api.service"; import {CreateComponent} from "../create/create.component"; import {EditComponent} from "../edit/edit.component"; import {DetailsComponent} from "../details/details.component"; -import {MatFormField, MatInput} from "@angular/material/input"; +import {MatFormFieldModule} from "@angular/material/form-field"; +import {MatInputModule} from "@angular/material/input"; import {Qualification} from "../../qualification/Qualification"; @Component({ @@ -38,8 +39,8 @@ import {Qualification} from "../../qualification/Qualification"; MatMenuModule, MatTableModule, MatSortModule, - MatInput, - MatFormField + MatFormFieldModule, + MatInputModule, ], templateUrl: './table.component.html', styleUrl: './table.component.css' @@ -50,11 +51,40 @@ export class TableComponent implements OnInit { private readonly matDialog: MatDialog = inject(MatDialog); private static readonly MAX_RETRIES = 3; + + private allEmployees: Employee[] = []; + private searchSubject = new Subject(); public employees$: Observable = of([]); + public isSearching = false; public readonly displayedColumns: string[] = ['name', 'actions']; public ngOnInit(): void { - this.employees$ = this.fetchEmployees(); + this.loadEmployees(); + this.setupSearch(); + } + + private loadEmployees(): void { + this.fetchEmployees().subscribe(employees => { + this.allEmployees = employees; + this.employees$ = of(employees); + }); + } + + private setupSearch(): void { + this.searchSubject.pipe( + debounceTime(300), + distinctUntilChanged() + ).subscribe(searchTerm => { + this.isSearching = true; + setTimeout(() => { + const filteredEmployees = this.allEmployees.filter(employee => + employee.firstName?.toLowerCase().includes(searchTerm) || + employee.lastName?.toLowerCase().includes(searchTerm) + ); + this.employees$ = of(filteredEmployees); + this.isSearching = false; + }, 150); + }); } private fetchEmployees(): Observable { @@ -111,21 +141,8 @@ export class TableComponent implements OnInit { this.matDialog.open(DetailsComponent, {data: employee}); } - filterEmployees($event: Event) { - const input = $event.target as HTMLInputElement; - const filterValue = input.value.trim().toLowerCase(); - - this.employees$ = this.employees$.pipe( - map((employees: Employee[]) => employees.filter((employee: Employee) => { - const filterValue = input.value.trim().toLowerCase(); - return employee.firstName?.toLowerCase().includes(filterValue) - || employee.lastName?.toLowerCase().includes(filterValue) - || employee.street?.toLowerCase().includes(filterValue) - || employee.phone?.toLowerCase().includes(filterValue) - || employee.postcode?.toString().toLowerCase().includes(filterValue) - || employee.city?.toString().toLowerCase().includes(filterValue) - || employee.skillSet?.some((skill: Qualification) => skill.skill?.toLowerCase().includes(filterValue)); - })) - ); + protected filterEmployees(event: Event): void { + const searchTerm = (event.target as HTMLInputElement).value.toLowerCase(); + this.searchSubject.next(searchTerm); } } diff --git a/src/app/qualification/delete/delete.component.ts b/src/app/qualification/delete/delete.component.ts index 478cf51..eb16805 100644 --- a/src/app/qualification/delete/delete.component.ts +++ b/src/app/qualification/delete/delete.component.ts @@ -22,7 +22,6 @@ import {MatIcon} from "@angular/material/icon"; ReactiveFormsModule, MatDialogActions, MatButton, - MatError, MatIcon ], templateUrl: './delete.component.html', diff --git a/src/app/qualification/table/table.component.html b/src/app/qualification/table/table.component.html index ce358e1..f45ab0a 100644 --- a/src/app/qualification/table/table.component.html +++ b/src/app/qualification/table/table.component.html @@ -3,8 +3,23 @@ @if (qualifications$ | async; as qualifications) {
-

Qualifications

-
+