From 88e4c2acde22da78819c9ce7766792b54352a73e Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Sun, 1 Mar 2026 18:26:20 +0300 Subject: [PATCH] perf: implemented reusable component --- .../city-card/city-card.component.ts | 50 +++++++++++++++++-- .../student-card/student-card.component.ts | 25 ++++++++-- .../teacher-card/teacher-card.component.ts | 26 ++++++++-- .../src/app/data-access/city.store.ts | 2 +- .../src/app/ui/card/card.component.ts | 48 ++++++++++-------- .../app/ui/list-item/list-item.component.ts | 50 +++++++++++-------- 6 files changed, 145 insertions(+), 56 deletions(-) diff --git a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts index 8895c8c84..b8a6301d5 100644 --- a/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/1-projection/src/app/component/city-card/city-card.component.ts @@ -1,9 +1,51 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { + ChangeDetectionStrategy, + Component, + inject, + OnInit, +} from '@angular/core'; +import { CityStore } from '../../data-access/city.store'; +import { + FakeHttpService, + randomCity, +} from '../../data-access/fake-http.service'; +import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-city-card', - template: 'TODO City', - imports: [], + template: ` + + + + + {{ item.name }} + + + `, + imports: [CardComponent], + standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class CityCardComponent {} +export class CityCardComponent implements OnInit { + private http = inject(FakeHttpService); + private store = inject(CityStore); + cities = this.store.cities; + + ngOnInit() { + this.http.fetchCities$.subscribe((cityArray) => + this.store.addAll(cityArray), + ); + } + onItemDeleted(item: any) { + this.store.deleteOne(item.id); + } + addItem() { + this.store.addOne(randomCity()); + } +} diff --git a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts index bdfa4abd4..bdfda7786 100644 --- a/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts +++ b/apps/angular/1-projection/src/app/component/student-card/student-card.component.ts @@ -4,7 +4,10 @@ import { inject, OnInit, } from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; +import { + FakeHttpService, + randStudent, +} from '../../data-access/fake-http.service'; import { StudentStore } from '../../data-access/student.store'; import { CardType } from '../../model/card.model'; import { CardComponent } from '../../ui/card/card.component'; @@ -14,8 +17,18 @@ import { CardComponent } from '../../ui/card/card.component'; template: ` + [itemTemplateRef]="listItemTemplate" + (itemAdded)="addItem()" + customClass="bg-light-green"> + + + + + {{ item.firstName }} + + `, styles: [ ` @@ -37,4 +50,10 @@ export class StudentCardComponent implements OnInit { ngOnInit(): void { this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); } + onItemDeleted(item: any) { + this.store.deleteOne(item.id); + } + addItem() { + this.store.addOne(randStudent()); + } } diff --git a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts index adf0ad3c1..115f27d70 100644 --- a/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts +++ b/apps/angular/1-projection/src/app/component/teacher-card/teacher-card.component.ts @@ -1,7 +1,9 @@ import { Component, inject, OnInit } from '@angular/core'; -import { FakeHttpService } from '../../data-access/fake-http.service'; +import { + FakeHttpService, + randTeacher, +} from '../../data-access/fake-http.service'; import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; import { CardComponent } from '../../ui/card/card.component'; @Component({ @@ -9,8 +11,17 @@ import { CardComponent } from '../../ui/card/card.component'; template: ` + [itemTemplateRef]="listItemTemplate" + (itemAdded)="addItem()" + customClass="bg-light-red"> + + + + {{ item.firstName }} + + `, styles: [ ` @@ -26,9 +37,14 @@ export class TeacherCardComponent implements OnInit { private store = inject(TeacherStore); teachers = this.store.teachers; - cardType = CardType.TEACHER; ngOnInit(): void { this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); } + onItemDeleted(item: any) { + this.store.deleteOne(item.id); + } + addItem() { + this.store.addOne(randTeacher()); + } } diff --git a/apps/angular/1-projection/src/app/data-access/city.store.ts b/apps/angular/1-projection/src/app/data-access/city.store.ts index a8b523569..9fbcb346b 100644 --- a/apps/angular/1-projection/src/app/data-access/city.store.ts +++ b/apps/angular/1-projection/src/app/data-access/city.store.ts @@ -5,7 +5,7 @@ import { City } from '../model/city.model'; providedIn: 'root', }) export class CityStore { - private cities = signal([]); + public cities = signal([]); addAll(cities: City[]) { this.cities.set(cities); diff --git a/apps/angular/1-projection/src/app/ui/card/card.component.ts b/apps/angular/1-projection/src/app/ui/card/card.component.ts index 1a6c3648c..f125bce8f 100644 --- a/apps/angular/1-projection/src/app/ui/card/card.component.ts +++ b/apps/angular/1-projection/src/app/ui/card/card.component.ts @@ -1,8 +1,5 @@ import { NgOptimizedImage } from '@angular/common'; -import { Component, inject, input } from '@angular/core'; -import { randStudent, randTeacher } from '../../data-access/fake-http.service'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; +import { Component, input, output, TemplateRef } from '@angular/core'; import { CardType } from '../../model/card.model'; import { ListItemComponent } from '../list-item/list-item.component'; @@ -12,19 +9,19 @@ import { ListItemComponent } from '../list-item/list-item.component';
- @if (type() === CardType.TEACHER) { - - } - @if (type() === CardType.STUDENT) { - - } + + + + + + +
@for (item of list(); track item) { + [item]="item" + [itemTemplate]="itemTemplateRef()"> }
@@ -38,21 +35,28 @@ import { ListItemComponent } from '../list-item/list-item.component'; imports: [ListItemComponent, NgOptimizedImage], }) export class CardComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); + // private teacherStore = inject(TeacherStore); + // private studentStore = inject(StudentStore); readonly list = input(null); - readonly type = input.required(); + // readonly type = input.required(); readonly customClass = input(''); + listItemDeleted = output(); + readonly itemTemplateRef = input.required>(); + itemAdded = output(); CardType = CardType; addNewItem() { - const type = this.type(); - if (type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } + this.itemAdded.emit(); + // const type = this.type(); + // if (type === CardType.TEACHER) { + // this.teacherStore.addOne(randTeacher()); + // } else if (type === CardType.STUDENT) { + // this.studentStore.addOne(randStudent()); + // } + } + deleteListItem(item: any) { + this.listItemDeleted.emit(item); } } diff --git a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts index 5d504f372..d2ddcc5ce 100644 --- a/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts +++ b/apps/angular/1-projection/src/app/ui/list-item/list-item.component.ts @@ -1,39 +1,47 @@ +import { CommonModule } from '@angular/common'; import { ChangeDetectionStrategy, Component, - inject, input, + TemplateRef, } from '@angular/core'; -import { StudentStore } from '../../data-access/student.store'; -import { TeacherStore } from '../../data-access/teacher.store'; -import { CardType } from '../../model/card.model'; @Component({ selector: 'app-list-item', template: `
- {{ name() }} - + + + + +
`, changeDetection: ChangeDetectionStrategy.OnPush, + standalone: true, + imports: [CommonModule], }) export class ListItemComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); + // private teacherStore = inject(TeacherStore); + // private studentStore = inject(StudentStore); - readonly id = input.required(); - readonly name = input.required(); - readonly type = input.required(); + readonly item = input.required(); + readonly itemTemplate = input.required>(); + // itemDeleted=output(); + // readonly type = input.required(); + // itemDeleted=output(); - delete(id: number) { - const type = this.type(); - if (type === CardType.TEACHER) { - this.teacherStore.deleteOne(id); - } else if (type === CardType.STUDENT) { - this.studentStore.deleteOne(id); - } - } + // delete(id: number) { + // // const type = this.type(); + // // if (type === CardType.TEACHER) { + // // this.teacherStore.deleteOne(id); + // // } else if (type === CardType.STUDENT) { + // // this.studentStore.deleteOne(id); + // // } + // this.itemDeleted.emit(id) + // } }