From 705da0320c978ea9147aaee9c8d49c8fb5a53c68 Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 20 Mar 2024 16:14:47 +0100 Subject: [PATCH 1/6] finish task projection ! --- .../city-card/city-card.component.ts | 35 ++++++++++++++++--- .../src/app/ui/card/card.component.ts | 17 +++++++-- .../app/ui/list-item/list-item.component.ts | 4 +++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 30c8f88ec..22612eb10 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -1,13 +1,40 @@ import { Component, OnInit } from '@angular/core'; +import { CityStore } from '../../data-access/city.store'; +import { FakeHttpService } from '../../data-access/fake-http.service'; +import { CardType } from '../../model/card.model'; +import { City } from '../../model/city.model'; +import { CardComponent } from '../../ui/card/card.component'; @Component({ selector: 'app-city-card', - template: 'TODO City', + template: ` + + `, + styles: [ + ` + ::ng-deep .bg-light-red { + background-color: rgba(250, 0, 0, 0.1); + } + `, + ], standalone: true, - imports: [], + imports: [CardComponent], }) export class CityCardComponent implements OnInit { - constructor() {} + cities: City[] = []; + cardType = CardType.CITY; - ngOnInit(): void {} + constructor( + private http: FakeHttpService, + private store: CityStore, + ) {} + + ngOnInit(): void { + this.http.fetchCities$.subscribe((s) => this.store.addAll(s)); + + this.store.cities$.subscribe((s) => (this.cities = s)); + } } diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index f06c9ae00..417757cc5 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,6 +1,11 @@ import { NgFor, NgIf } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { randStudent, randTeacher } from '../../data-access/fake-http.service'; +import { CityStore } from '../../data-access/city.store'; +import { + randStudent, + randTeacher, + randomCity, +} 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'; @@ -21,10 +26,15 @@ import { ListItemComponent } from '../list-item/list-item.component'; src="assets/img/student.webp" width="200px" /> + +
@@ -49,6 +59,7 @@ export class CardComponent { constructor( private teacherStore: TeacherStore, private studentStore: StudentStore, + private cityStore: CityStore, ) {} addNewItem() { @@ -56,6 +67,8 @@ export class CardComponent { this.teacherStore.addOne(randTeacher()); } else if (this.type === CardType.STUDENT) { this.studentStore.addOne(randStudent()); + } else if (this.type === CardType.CITY) { + this.cityStore.addOne(randomCity()); } } } diff --git a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts b/apps/angular/projection/src/app/ui/list-item/list-item.component.ts index c0f9cff7f..e6a77dfcb 100644 --- a/apps/angular/projection/src/app/ui/list-item/list-item.component.ts +++ b/apps/angular/projection/src/app/ui/list-item/list-item.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core'; +import { CityStore } from '../../data-access/city.store'; import { StudentStore } from '../../data-access/student.store'; import { TeacherStore } from '../../data-access/teacher.store'; import { CardType } from '../../model/card.model'; @@ -23,6 +24,7 @@ export class ListItemComponent { constructor( private teacherStore: TeacherStore, private studentStore: StudentStore, + private cityStore: CityStore, ) {} delete(id: number) { @@ -30,6 +32,8 @@ export class ListItemComponent { this.teacherStore.deleteOne(id); } else if (this.type === CardType.STUDENT) { this.studentStore.deleteOne(id); + } else if (this.type === CardType.CITY) { + this.cityStore.deleteOne(id); } } } From 11964fa7c94c5e98e6543fc2ab33b5459a95d3a0 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 25 Mar 2024 08:26:44 +0100 Subject: [PATCH 2/6] fix: correct style css --- .../src/app/component/city-card/city-card.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 22612eb10..6d9fbe00e 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -15,7 +15,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, styles: [ ` - ::ng-deep .bg-light-red { + .bg-light-red { background-color: rgba(250, 0, 0, 0.1); } `, From 981ba9b308889e928ac26607df34aa006e88de25 Mon Sep 17 00:00:00 2001 From: michal Date: Mon, 25 Mar 2024 08:29:12 +0100 Subject: [PATCH 3/6] fix: correct style css v1 --- .../src/app/component/city-card/city-card.component.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 6d9fbe00e..558e39117 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -13,13 +13,6 @@ import { CardComponent } from '../../ui/card/card.component'; [type]="cardType" customClass="bg-light-red"> `, - styles: [ - ` - .bg-light-red { - background-color: rgba(250, 0, 0, 0.1); - } - `, - ], standalone: true, imports: [CardComponent], }) From 2b207fdbccc16f70476d9f8c2005d576985b4392 Mon Sep 17 00:00:00 2001 From: michal Date: Tue, 2 Apr 2024 14:02:06 +0200 Subject: [PATCH 4/6] fix: logic card component --- .../projection/src/app/model/card.model.ts | 8 +++++ .../src/app/services/card.service.ts | 31 +++++++++++++++++++ .../src/app/ui/card/card.component.ts | 25 +++------------ 3 files changed, 43 insertions(+), 21 deletions(-) create mode 100644 apps/angular/projection/src/app/services/card.service.ts diff --git a/apps/angular/projection/src/app/model/card.model.ts b/apps/angular/projection/src/app/model/card.model.ts index 740cd2ae4..0a1533782 100644 --- a/apps/angular/projection/src/app/model/card.model.ts +++ b/apps/angular/projection/src/app/model/card.model.ts @@ -3,3 +3,11 @@ export enum CardType { STUDENT, CITY, } + +export interface CardModel { + name: string; + firstName: string; + lastName: string; + subject: string; + id: number; +} diff --git a/apps/angular/projection/src/app/services/card.service.ts b/apps/angular/projection/src/app/services/card.service.ts new file mode 100644 index 000000000..0f7b6aad2 --- /dev/null +++ b/apps/angular/projection/src/app/services/card.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { CityStore } from '../data-access/city.store'; +import { + randomCity, + 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'; + +@Injectable({ + providedIn: 'root', +}) +export class CardService { + constructor( + private teacherStore: TeacherStore, + private studentStore: StudentStore, + private cityStore: CityStore, + ) {} + + addOne(type: CardType) { + if (type === CardType.TEACHER) { + this.teacherStore.addOne(randTeacher()); + } else if (type === CardType.STUDENT) { + this.studentStore.addOne(randStudent()); + } else if (type === CardType.CITY) { + this.cityStore.addOne(randomCity()); + } + } +} diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index 417757cc5..72e912ecd 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,14 +1,7 @@ import { NgFor, NgIf } from '@angular/common'; import { Component, Input } from '@angular/core'; -import { CityStore } from '../../data-access/city.store'; -import { - randStudent, - randTeacher, - randomCity, -} 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 { CardService } from '../../services/card.service'; import { ListItemComponent } from '../list-item/list-item.component'; @Component({ @@ -50,25 +43,15 @@ import { ListItemComponent } from '../list-item/list-item.component'; imports: [NgIf, NgFor, ListItemComponent], }) export class CardComponent { - @Input() list: any[] | null = null; + @Input() list!: any[]; @Input() type!: CardType; @Input() customClass = ''; CardType = CardType; - constructor( - private teacherStore: TeacherStore, - private studentStore: StudentStore, - private cityStore: CityStore, - ) {} + constructor(private cardService: CardService) {} addNewItem() { - if (this.type === CardType.TEACHER) { - this.teacherStore.addOne(randTeacher()); - } else if (this.type === CardType.STUDENT) { - this.studentStore.addOne(randStudent()); - } else if (this.type === CardType.CITY) { - this.cityStore.addOne(randomCity()); - } + this.cardService.addOne(this.type); } } From 3dd6adf9fb505a799f2129e0bc5c17e32105e9d6 Mon Sep 17 00:00:00 2001 From: michal Date: Thu, 4 Apr 2024 10:34:42 +0200 Subject: [PATCH 5/6] fix: use ng-content, ng-template-outlet an remove CardType --- .../city-card/city-card.component.ts | 2 + .../student-card/student-card.component.ts | 2 + .../teacher-card/teacher-card.component.ts | 2 + .../src/app/ui/card/card.component.ts | 47 ++++++++----------- 4 files changed, 25 insertions(+), 28 deletions(-) diff --git a/apps/angular/projection/src/app/component/city-card/city-card.component.ts b/apps/angular/projection/src/app/component/city-card/city-card.component.ts index 558e39117..714040f85 100644 --- a/apps/angular/projection/src/app/component/city-card/city-card.component.ts +++ b/apps/angular/projection/src/app/component/city-card/city-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, standalone: true, @@ -18,6 +19,7 @@ import { CardComponent } from '../../ui/card/card.component'; }) export class CityCardComponent implements OnInit { cities: City[] = []; + image = 'city.png'; cardType = CardType.CITY; constructor( diff --git a/apps/angular/projection/src/app/component/student-card/student-card.component.ts b/apps/angular/projection/src/app/component/student-card/student-card.component.ts index 441cda189..5b97d8ad6 100644 --- a/apps/angular/projection/src/app/component/student-card/student-card.component.ts +++ b/apps/angular/projection/src/app/component/student-card/student-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, standalone: true, @@ -26,6 +27,7 @@ import { CardComponent } from '../../ui/card/card.component'; export class StudentCardComponent implements OnInit { students: Student[] = []; cardType = CardType.STUDENT; + image = 'student.webp'; constructor( private http: FakeHttpService, diff --git a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts b/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts index 995cb7c2f..bc5699866 100644 --- a/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts +++ b/apps/angular/projection/src/app/component/teacher-card/teacher-card.component.ts @@ -11,6 +11,7 @@ import { CardComponent } from '../../ui/card/card.component'; `, styles: [ @@ -26,6 +27,7 @@ import { CardComponent } from '../../ui/card/card.component'; export class TeacherCardComponent implements OnInit { teachers: Teacher[] = []; cardType = CardType.TEACHER; + image = 'teacher.png'; constructor( private http: FakeHttpService, diff --git a/apps/angular/projection/src/app/ui/card/card.component.ts b/apps/angular/projection/src/app/ui/card/card.component.ts index 72e912ecd..a68f64a2f 100644 --- a/apps/angular/projection/src/app/ui/card/card.component.ts +++ b/apps/angular/projection/src/app/ui/card/card.component.ts @@ -1,4 +1,4 @@ -import { NgFor, NgIf } from '@angular/common'; +import { CommonModule } from '@angular/common'; import { Component, Input } from '@angular/core'; import { CardType } from '../../model/card.model'; import { CardService } from '../../services/card.service'; @@ -10,44 +10,35 @@ import { ListItemComponent } from '../list-item/list-item.component';
- - + + - +
+ +
-
- -
+ +
- +
`, standalone: true, - imports: [NgIf, NgFor, ListItemComponent], + imports: [CommonModule, ListItemComponent], }) export class CardComponent { @Input() list!: any[]; @Input() type!: CardType; @Input() customClass = ''; - - CardType = CardType; + @Input() image: string = ''; constructor(private cardService: CardService) {} From 8442953f65262af264b2d55c82ed3eff7dde69db Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 27 May 2026 16:26:56 +0200 Subject: [PATCH 6/6] feat(Answer:46): add animation stagger for listings and fade left for text --- .../src/app/app.component.ts | 66 +++++++++++++++++-- .../simple-animations/src/app/app.config.ts | 3 +- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/apps/angular/simple-animations/src/app/app.component.ts b/apps/angular/simple-animations/src/app/app.component.ts index 9f537b3fb..826f16a64 100644 --- a/apps/angular/simple-animations/src/app/app.component.ts +++ b/apps/angular/simple-animations/src/app/app.component.ts @@ -1,9 +1,60 @@ -import { Component } from '@angular/core'; +import { + animate, + keyframes, + query, + stagger, + style, + transition, + trigger, +} from '@angular/animations'; +import { Component, signal } from '@angular/core'; @Component({ standalone: true, - imports: [], selector: 'app-root', + animations: [ + trigger('fadeInLeft', [ + transition(':enter', [ + animate( + '500ms ease-out', + keyframes([ + style({ + opacity: 0, + transform: 'translateX(-30px)', + offset: 0, + }), + style({ + opacity: 1, + transform: 'translateX(0)', + offset: 1, + }), + ]), + ), + ]), + ]), + trigger('listStagger', [ + transition('* => *', [ + query( + '.list-item', + [style({ opacity: 0, transform: 'translateX(-100px)' })], + { optional: true }, + ), + + query( + '.list-item', + [ + stagger('500ms', [ + animate( + '500ms ease-out', + style({ opacity: 1, transform: 'translateX(0)' }), + ), + ]), + ], + { optional: true }, + ), + ]), + ]), + ], styles: ` section { @apply flex flex-1 flex-col gap-5; @@ -19,7 +70,7 @@ import { Component } from '@angular/core'; `, template: `
-
+

2008

@@ -51,7 +102,7 @@ import { Component } from '@angular/core';

-
+
Name: Samuel @@ -85,4 +136,9 @@ import { Component } from '@angular/core';
`, }) -export class AppComponent {} +export class AppComponent { + toggleFade = signal({ + value: '', + params: { duration: '0.8s', delay: '0.2s' }, + }); +} diff --git a/apps/angular/simple-animations/src/app/app.config.ts b/apps/angular/simple-animations/src/app/app.config.ts index 81a6edde4..59198e627 100644 --- a/apps/angular/simple-animations/src/app/app.config.ts +++ b/apps/angular/simple-animations/src/app/app.config.ts @@ -1,5 +1,6 @@ import { ApplicationConfig } from '@angular/core'; +import { provideAnimations } from '@angular/platform-browser/animations'; export const appConfig: ApplicationConfig = { - providers: [], + providers: [provideAnimations()], };