Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions apps/angular/1-projection/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,25 @@ import { TeacherCardComponent } from './component/teacher-card/teacher-card.comp
@Component({
selector: 'app-root',
template: `
<div class="grid grid-cols-3 gap-3">
<app-teacher-card />
<app-student-card />
<app-city-card />
<div class="app-container">
<div class="cards-grid">
<app-teacher-card />
<app-student-card />
<app-city-card />
</div>
</div>
`,
styles: [
`
.app-container {
@apply min-h-screen bg-gray-50 p-8;
}
.cards-grid {
@apply grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3;
@apply mx-auto max-w-7xl;
}
`,
],
imports: [TeacherCardComponent, StudentCardComponent, CityCardComponent],
})
export class AppComponent {}
Original file line number Diff line number Diff line change
@@ -1,9 +1,80 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgOptimizedImage } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import { CityStore } from '../../data-access/city.store';
import {
FakeHttpService,
randomCity,
} from '../../data-access/fake-http.service';
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-city-card',
template: 'TODO City',
imports: [],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<app-card [list]="cities()" [type]="cardType" customClass="city-card">
<!-- Header Template -->
<div cardHeader class="header-content">
<img
ngSrc="assets/img/city.png"
width="200"
height="200"
alt="City"
class="header-image" />
</div>

<!-- Item Template -->
<ng-template #itemTemplate let-city>
<app-list-item
[name]="city.name"
[id]="city.id"
[type]="cardType"
(delete)="deleteCity(city.id)"></app-list-item>
</ng-template>

<!-- Footer Template -->
<div cardFooter>
<button class="add-button" (click)="addCity()">Add City</button>
</div>
</app-card>
`,
styles: [
`
.city-card {
@apply bg-gradient-to-br from-blue-50 to-white;
}
.header-content {
@apply flex justify-center;
}
.header-image {
@apply rounded-lg object-cover shadow-sm;
}
.add-button {
@apply w-full rounded-md bg-blue-500 px-4 py-2 text-white;
@apply transition-colors duration-200 hover:bg-blue-600;
@apply disabled:cursor-not-allowed disabled:opacity-50;
}
`,
],
imports: [CardComponent, ListItemComponent, NgOptimizedImage],
standalone: true,
})
export class CityCardComponent {}
export class CityCardComponent implements OnInit {
private http = inject(FakeHttpService);
private store = inject(CityStore);

cities = this.store.cities;
cardType = CardType.CITY;

ngOnInit(): void {
this.http.fetchCities$.subscribe((c) => this.store.addAll(c));
}

addCity() {
this.store.addOne(randomCity());
}

deleteCity(id: number) {
this.store.deleteOne(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,31 +1,63 @@
import { NgOptimizedImage } from '@angular/common';
import { Component, inject, OnInit } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
inject,
OnInit,
} from '@angular/core';
import { FakeHttpService } from '../../data-access/fake-http.service';
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: `
<app-card
[list]="students()"
[type]="cardType"
customClass="bg-light-green" />
<app-card [list]="students()" [type]="cardType" customClass="student-card">
<!-- Header Template -->
<div cardHeader class="header-content">
<img
ngSrc="assets/img/student.webp"
width="200"
height="200"
alt="Student"
class="header-image" />
</div>

<!-- Item Template -->
<ng-template #itemTemplate let-student>
<app-list-item
[name]="student.firstName"
[id]="student.id"
[type]="cardType"
(delete)="deleteStudent(student.id)"></app-list-item>
</ng-template>

<!-- Footer Template -->
<div cardFooter>
<button class="add-button" (click)="addStudent()">Add Student</button>
</div>
</app-card>
`,
styles: [
`
::ng-deep .bg-light-green {
background-color: rgba(0, 250, 0, 0.1);
.student-card {
@apply bg-gradient-to-br from-green-50 to-white;
}
.header-content {
@apply flex justify-center;
}
.header-image {
@apply rounded-lg object-cover shadow-sm;
}
.add-button {
@apply w-full rounded-md bg-blue-500 px-4 py-2 text-white;
@apply transition-colors duration-200 hover:bg-blue-600;
@apply disabled:cursor-not-allowed disabled:opacity-50;
}
`,
],
imports: [CardComponent],
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [CardComponent, ListItemComponent, NgOptimizedImage],
standalone: true,
})
export class StudentCardComponent implements OnInit {
private http = inject(FakeHttpService);
Expand All @@ -37,4 +69,12 @@ export class StudentCardComponent implements OnInit {
ngOnInit(): void {
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
}

addStudent() {
this.store.addOne(randStudent());
}

deleteStudent(id: number) {
this.store.deleteOne(id);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,63 @@
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: `
<app-card
[list]="teachers()"
[type]="cardType"
customClass="bg-light-red"></app-card>
<app-card [list]="teachers()" [type]="cardType" customClass="teacher-card">
<!-- Header Template -->
<div cardHeader class="header-content">
<img
ngSrc="assets/img/teacher.png"
width="200"
height="200"
alt="Teacher"
class="header-image" />
</div>

<!-- Item Template -->
<ng-template #itemTemplate let-teacher>
<app-list-item
[name]="teacher.firstName"
[id]="teacher.id"
[type]="cardType"
(delete)="deleteTeacher(teacher.id)"></app-list-item>
</ng-template>

<!-- Footer Template -->
<div cardFooter>
<button class="add-button" (click)="addTeacher()">Add Teacher</button>
</div>
</app-card>
`,
styles: [
`
::ng-deep .bg-light-red {
background-color: rgba(250, 0, 0, 0.1);
.teacher-card {
@apply bg-gradient-to-br from-red-50 to-white;
}
.header-content {
@apply flex justify-center;
}
.header-image {
@apply rounded-lg object-cover shadow-sm;
}
.add-button {
@apply w-full rounded-md bg-blue-500 px-4 py-2 text-white;
@apply transition-colors duration-200 hover:bg-blue-600;
@apply disabled:cursor-not-allowed disabled:opacity-50;
}
`,
],
imports: [CardComponent],
imports: [CardComponent, ListItemComponent, NgOptimizedImage],
standalone: true,
})
export class TeacherCardComponent implements OnInit {
private http = inject(FakeHttpService);
Expand All @@ -31,4 +69,12 @@ export class TeacherCardComponent implements OnInit {
ngOnInit(): void {
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
}

addTeacher() {
this.store.addOne(randTeacher());
}

deleteTeacher(id: number) {
this.store.deleteOne(id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { City } from '../model/city.model';
providedIn: 'root',
})
export class CityStore {
private cities = signal<City[]>([]);
public cities = signal<City[]>([]);

addAll(cities: City[]) {
this.cities.set(cities);
Expand Down
Loading
Loading