From 10aa9f5dfae2e6faedd8976f7101424702cdcd14 Mon Sep 17 00:00:00 2001 From: victor Date: Fri, 9 Jan 2026 22:28:30 -0500 Subject: [PATCH 1/8] refactor(list-item): simplify the component variables and the methods --- .../app/ui/list-item/list-item.component.ts | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) 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..6b7a0b900 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,12 +1,10 @@ import { ChangeDetectionStrategy, Component, - inject, + EventEmitter, input, + Output, } 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', @@ -21,19 +19,13 @@ import { CardType } from '../../model/card.model'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class ListItemComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); + @Output() + deleteClicked = new EventEmitter(); readonly id = input.required(); readonly name = input.required(); - readonly type = input.required(); 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.deleteClicked.emit(id); } } From 037308f857a71cfe15de39bf6e96f41dd55c7dab Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 11 Jan 2026 20:10:15 -0500 Subject: [PATCH 2/8] refactor(list-item): simplyfy the list-item using content projection --- .../app/ui/list-item/list-item.component.ts | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) 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 6b7a0b900..350e07e2d 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,31 +1,13 @@ -import { - ChangeDetectionStrategy, - Component, - EventEmitter, - input, - Output, -} from '@angular/core'; +import { ChangeDetectionStrategy, Component } from '@angular/core'; @Component({ selector: 'app-list-item', template: `
- {{ name() }} - + +
`, changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ListItemComponent { - @Output() - deleteClicked = new EventEmitter(); - - readonly id = input.required(); - readonly name = input.required(); - - delete(id: number) { - this.deleteClicked.emit(id); - } -} +export class ListItemComponent {} From 9270fa1260d578afc0b18cfd9f178b84a0a6c8b7 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 14:06:39 -0500 Subject: [PATCH 3/8] refactor(student-card): recontructor student card by content projection --- .../student-card/student-card.component.ts | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) 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..f9429bd12 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 @@ -1,40 +1,59 @@ +import { NgOptimizedImage } from '@angular/common'; import { ChangeDetectionStrategy, Component, 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'; +import { ListItemComponent } from '../../ui/list-item/list-item.component'; @Component({ selector: 'app-student-card', template: ` + + + {{ itemName }} + + + + [cardContent]="configurableList" + [customBgColor]="bgColor"> + + + `, - styles: [ - ` - ::ng-deep .bg-light-green { - background-color: rgba(0, 250, 0, 0.1); - } - `, - ], - imports: [CardComponent], + imports: [CardComponent, NgOptimizedImage, ListItemComponent], changeDetection: ChangeDetectionStrategy.OnPush, }) export class StudentCardComponent implements OnInit { private http = inject(FakeHttpService); private store = inject(StudentStore); - students = this.store.students; - cardType = CardType.STUDENT; + bgColor = { 'background-color': 'rgba(0, 250, 0, 0.1)' }; ngOnInit(): void { this.http.fetchStudents$.subscribe((s) => this.store.addAll(s)); } + + addNewItem() { + this.store.addOne(randStudent()); + } + + delete(id: number) { + this.store.deleteOne(id); + } } From 05c7d5d63967ea95bbb3574987a9d718b8db8b81 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 14:08:19 -0500 Subject: [PATCH 4/8] refactor(teacher-card): recontructor teacher card by content projection --- .../teacher-card/teacher-card.component.ts | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) 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..4968c4259 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,34 +1,53 @@ +import { NgOptimizedImage } from '@angular/common'; 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'; +import { ListItemComponent } from '../../ui/list-item/list-item.component'; @Component({ selector: 'app-teacher-card', template: ` + + + {{ itemName }} + + + + [customBgColor]="bgColor" + [cardContent]="configurableList"> + + + `, - styles: [ - ` - ::ng-deep .bg-light-red { - background-color: rgba(250, 0, 0, 0.1); - } - `, - ], - imports: [CardComponent], + imports: [CardComponent, NgOptimizedImage, ListItemComponent], }) export class TeacherCardComponent implements OnInit { private http = inject(FakeHttpService); private store = inject(TeacherStore); - teachers = this.store.teachers; - cardType = CardType.TEACHER; + bgColor = { 'background-color': 'rgba(250, 0, 0, 0.1)' }; ngOnInit(): void { this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t)); } + + delete(id: number) { + this.store.deleteOne(id); + } + + addNewItem() { + this.store.addOne(randTeacher()); + } } From 7feef0318ad33f6279a9e8bead26e831e10bd36b Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 14:11:25 -0500 Subject: [PATCH 5/8] refactor(card): customize the bg color, card component by receiving template, and ng-content --- .../src/app/ui/card/card.component.ts | 58 +++++-------------- 1 file changed, 15 insertions(+), 43 deletions(-) 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..4d9b68cb4 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,58 +1,30 @@ -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 { CardType } from '../../model/card.model'; -import { ListItemComponent } from '../list-item/list-item.component'; +import { NgStyle, NgTemplateOutlet } from '@angular/common'; +import { Component, input, TemplateRef } from '@angular/core'; @Component({ selector: 'app-card', template: `
- @if (type() === CardType.TEACHER) { - - } - @if (type() === CardType.STUDENT) { - - } - + [ngStyle]="customBgColor()" + [style.background-color]=""> +
- @for (item of list(); track item) { - + @for (item of list(); track item.id) { + }
- - +
`, - imports: [ListItemComponent, NgOptimizedImage], + imports: [NgTemplateOutlet, NgStyle], }) export class CardComponent { - private teacherStore = inject(TeacherStore); - private studentStore = inject(StudentStore); - readonly list = input(null); - readonly type = input.required(); - readonly customClass = input(''); - - CardType = CardType; - - addNewItem() { - const type = this.type(); - if (type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } - } + readonly cardContent = input>(); + readonly customBgColor = input | null>(null); } From 45431315427a562f71f5087c226a1d055cd749b0 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 14:52:20 -0500 Subject: [PATCH 6/8] fix(): passed the all item as the context --- .../app/component/student-card/student-card.component.ts | 6 +++--- .../app/component/teacher-card/teacher-card.component.ts | 6 +++--- apps/angular/1-projection/src/app/ui/card/card.component.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) 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 f9429bd12..7b1d3bb82 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 @@ -16,10 +16,10 @@ import { ListItemComponent } from '../../ui/list-item/list-item.component'; @Component({ selector: 'app-student-card', template: ` - + - {{ itemName }} - 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 4968c4259..a953bc20a 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 @@ -11,10 +11,10 @@ import { ListItemComponent } from '../../ui/list-item/list-item.component'; @Component({ selector: 'app-teacher-card', template: ` - + - {{ itemName }} - 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 4d9b68cb4..debe4468c 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 @@ -14,7 +14,7 @@ import { Component, input, TemplateRef } from '@angular/core'; } From db12ed148fced901488e752fa425f3875bbde249 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 14:53:16 -0500 Subject: [PATCH 7/8] feat(city): implmented the city-card --- .../city-card/city-card.component.ts | 58 +++++++++++++++++-- .../src/app/data-access/city.store.ts | 2 +- 2 files changed, 55 insertions(+), 5 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..40fb98f8f 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,59 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { NgOptimizedImage } from '@angular/common'; +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'; +import { ListItemComponent } from '../../ui/list-item/list-item.component'; @Component({ selector: 'app-city-card', - template: 'TODO City', - imports: [], + template: ` + + + {{ item.name }} + + + + + + + + `, + imports: [ListItemComponent, CardComponent, NgOptimizedImage], changeDetection: ChangeDetectionStrategy.OnPush, }) -export class CityCardComponent {} +export class CityCardComponent implements OnInit { + private http = inject(FakeHttpService); + private store = inject(CityStore); + cities = this.store.cities; + bgColor = { 'background-color': 'rgba(0, 0, 250, 0.1)' }; + + ngOnInit(): void { + this.http.fetchCities$.subscribe((c) => this.store.addAll(c)); + } + + delete(id: number) { + this.store.deleteOne(id); + } + + addNewItem() { + this.store.addOne(randomCity()); + } +} 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..6d270404f 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([]); + cities = signal([]); addAll(cities: City[]) { this.cities.set(cities); From 625eddd9a0b6a04d9b16c436455783058714d804 Mon Sep 17 00:00:00 2001 From: victor Date: Tue, 13 Jan 2026 15:04:57 -0500 Subject: [PATCH 8/8] fix(): version mismatch --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index c5627c36e..6e3b76f70 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,6 @@ "node": ">=20.19.6" }, "private": true, - "packageManager": "pnpm@10.23.0", "dependencies": { "@actions/core": "^1.10.1", "@actions/github": "^6.0.0",