diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 98bd3cd..92b1d1d 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -85,6 +85,7 @@ import { OutboxComponent } from './admin-view/notifications/outbox/outbox.compon
import { ToolbarComponent } from './admin-view/toolbar/toolbar.component';
import { MessageComponent } from './admin-view/notifications/outbox/message/message.component';
import { NotifDialogComponent } from './app-view/notif-dialog/notif-dialog.component';
+import { UserSearchComponent } from './commonComponents/user-search/user-search.component';
import { StartAdminComponent } from './admin-view/start/start.component';
@NgModule({
@@ -135,6 +136,7 @@ import { StartAdminComponent } from './admin-view/start/start.component';
ToolbarComponent,
MessageComponent,
NotifDialogComponent,
+ UserSearchComponent,
StartAdminComponent,
],
imports: [
diff --git a/src/app/commonComponents/user-search/user-search.component.html b/src/app/commonComponents/user-search/user-search.component.html
new file mode 100644
index 0000000..5a738d6
--- /dev/null
+++ b/src/app/commonComponents/user-search/user-search.component.html
@@ -0,0 +1,16 @@
+
+ {{label}}
+
+
+
+
+ @for (item of list; track $index) {
+
+ @if (item.fname) {
+ {{item.fname}} {{item.surname}} ({{item.room}})
+ } @else {
+ {{item.uname}}
+ }
+
+ }
+
\ No newline at end of file
diff --git a/src/app/commonComponents/user-search/user-search.component.scss b/src/app/commonComponents/user-search/user-search.component.scss
new file mode 100644
index 0000000..f06ba3a
--- /dev/null
+++ b/src/app/commonComponents/user-search/user-search.component.scss
@@ -0,0 +1,9 @@
+:host {
+ display: flex;
+ align-items: center;
+ gap: 1ch;
+}
+
+.room {
+ color: gray;
+}
\ No newline at end of file
diff --git a/src/app/commonComponents/user-search/user-search.component.spec.ts b/src/app/commonComponents/user-search/user-search.component.spec.ts
new file mode 100644
index 0000000..6cb2c16
--- /dev/null
+++ b/src/app/commonComponents/user-search/user-search.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UserSearchComponent } from './user-search.component';
+
+describe('UserSearchComponent', () => {
+ let component: UserSearchComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [UserSearchComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(UserSearchComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/commonComponents/user-search/user-search.component.ts b/src/app/commonComponents/user-search/user-search.component.ts
new file mode 100644
index 0000000..eaa9dcc
--- /dev/null
+++ b/src/app/commonComponents/user-search/user-search.component.ts
@@ -0,0 +1,76 @@
+import { Component, EventEmitter, forwardRef, Input, Output, ViewChild } from '@angular/core';
+import { ControlValueAccessor, FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete';
+import { MatInput } from '@angular/material/input';
+import { AdminCommService } from 'src/app/admin-view/admin-comm.service';
+
+interface UserSearchResult {
+ _id: string;
+ fname: string;
+ surname: string;
+ uname: string;
+ room: string;
+}
+
+@Component({
+ selector: 'app-user-search',
+ templateUrl: './user-search.component.html',
+ styleUrl: './user-search.component.scss',
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => UserSearchComponent),
+ multi: true
+ }
+ ],
+ host: {
+ '(blur)': '_onTouched()'
+ }
+})
+export class UserSearchComponent implements ControlValueAccessor {
+ protected loading: boolean = false
+ @Input() label?: boolean
+ control: FormControl = new FormControl();
+ protected list: UserSearchResult[] = []
+ private timeout?: NodeJS.Timeout
+ private _onChange!: (_: UserSearchResult) => void
+ private _onTouched!: any
+
+ constructor(readonly acu: AdminCommService) {
+ this.control.valueChanges.subscribe(() => {
+ this.loading = true
+ if (this.timeout) clearTimeout(this.timeout)
+ this.timeout = setTimeout(() => {
+ this.acu.userFilter(this.control.value).subscribe(v => {
+ this.list = v
+ this.loading = false
+ })
+ }, 500)
+ })
+ }
+
+ writeValue(obj: string): void {
+ this.control.setValue(obj)
+ }
+
+ registerOnChange(fn: (_: UserSearchResult) => void): void {
+ this._onChange = fn
+ }
+
+ registerOnTouched(fn: any): void {
+ this._onTouched = fn
+ }
+
+ setDisabledState?(isDisabled: boolean): void {
+ isDisabled ? this.control.disable() : this.control.enable()
+ }
+
+ protected displayFn(u: UserSearchResult): string {
+ if (!u) return ''
+ return u.fname ? `${u.fname} ${u.surname}` : u.uname
+ }
+
+ protected saveValue(e: MatAutocompleteSelectedEvent) {
+ this._onChange(this.control.value)
+ }
+}