feat(doc): move projection

This commit is contained in:
thomas
2023-10-18 10:03:54 +02:00
parent fedab5eeb1
commit 01a41ed13f
36 changed files with 40 additions and 44 deletions

View File

@@ -0,0 +1,18 @@
import { Component } from '@angular/core';
import { CityCardComponent } from './component/city-card/city-card.component';
import { StudentCardComponent } from './component/student-card/student-card.component';
import { TeacherCardComponent } from './component/teacher-card/teacher-card.component';
@Component({
selector: 'app-root',
template: `
<div class="grid grid-cols-3 gap-3">
<app-teacher-card></app-teacher-card>
<app-student-card></app-student-card>
<app-city-card></app-city-card>
</div>
`,
standalone: true,
imports: [TeacherCardComponent, StudentCardComponent, CityCardComponent],
})
export class AppComponent {}

View File

@@ -0,0 +1,13 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-city-card',
template: 'TODO City',
standalone: true,
imports: [],
})
export class CityCardComponent implements OnInit {
constructor() {}
ngOnInit(): void {}
}

View File

@@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { FakeHttpService } from '../../data-access/fake-http.service';
import { StudentStore } from '../../data-access/student.store';
import { CardType } from '../../model/card.model';
import { Student } from '../../model/student.model';
import { CardComponent } from '../../ui/card/card.component';
@Component({
selector: 'app-student-card',
template: `<app-card
[list]="students"
[type]="cardType"
customClass="bg-light-green"></app-card>`,
standalone: true,
styles: [
`
::ng-deep .bg-light-green {
background-color: rgba(0, 250, 0, 0.1);
}
`,
],
imports: [CardComponent],
})
export class StudentCardComponent implements OnInit {
students: Student[] = [];
cardType = CardType.STUDENT;
constructor(private http: FakeHttpService, private store: StudentStore) {}
ngOnInit(): void {
this.http.fetchStudents$.subscribe((s) => this.store.addAll(s));
this.store.students$.subscribe((s) => (this.students = s));
}
}

View File

@@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { FakeHttpService } from '../../data-access/fake-http.service';
import { TeacherStore } from '../../data-access/teacher.store';
import { CardType } from '../../model/card.model';
import { Teacher } from '../../model/teacher.model';
import { CardComponent } from '../../ui/card/card.component';
@Component({
selector: 'app-teacher-card',
template: `<app-card
[list]="teachers"
[type]="cardType"
customClass="bg-light-red"></app-card>`,
styles: [
`
::ng-deep .bg-light-red {
background-color: rgba(250, 0, 0, 0.1);
}
`,
],
standalone: true,
imports: [CardComponent],
})
export class TeacherCardComponent implements OnInit {
teachers: Teacher[] = [];
cardType = CardType.TEACHER;
constructor(private http: FakeHttpService, private store: TeacherStore) {}
ngOnInit(): void {
this.http.fetchTeachers$.subscribe((t) => this.store.addAll(t));
this.store.teachers$.subscribe((t) => (this.teachers = t));
}
}

View File

@@ -0,0 +1,68 @@
import { Injectable } from '@angular/core';
import {
incrementalNumber,
rand,
randCity,
randCountry,
randFirstName,
randLastName,
randNumber,
randWord,
} from '@ngneat/falso';
import { map, timer } from 'rxjs';
import { City } from '../model/city.model';
import { Student } from '../model/student.model';
import { subject, Teacher } from '../model/teacher.model';
const factoryTeacher = incrementalNumber();
export const randTeacher = () => ({
id: factoryTeacher(),
firstname: randFirstName(),
lastname: randLastName(),
subject: rand(subject),
});
const teachers: Teacher[] = [
randTeacher(),
randTeacher(),
randTeacher(),
randTeacher(),
];
const factoryStudent = incrementalNumber();
export const randStudent = (): Student => ({
id: factoryStudent(),
firstname: randFirstName(),
lastname: randLastName(),
mainTeacher: teachers[randNumber({ max: teachers.length - 1 })],
school: randWord(),
});
const students: Student[] = [
randStudent(),
randStudent(),
randStudent(),
randStudent(),
randStudent(),
];
const factoryCity = incrementalNumber();
export const randomCity = (): City => ({
id: factoryCity(),
name: randCity(),
country: randCountry(),
});
const cities = [randomCity(), randomCity(), randomCity()];
@Injectable({
providedIn: 'root',
})
export class FakeHttpService {
fetchTeachers$ = timer(500).pipe(map(() => teachers));
fetchStudents$ = timer(500).pipe(map(() => students));
fetchCities$ = timer(500).pipe(map(() => cities));
}

View File

@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Student } from '../model/student.model';
@Injectable({
providedIn: 'root',
})
export class StudentStore {
private students = new BehaviorSubject<Student[]>([]);
students$ = this.students.asObservable();
addAll(students: Student[]) {
this.students.next(students);
}
addOne(student: Student) {
this.students.next([...this.students.value, student]);
}
deleteOne(id: number) {
this.students.next(this.students.value.filter((s) => s.id !== id));
}
}

View File

@@ -0,0 +1,23 @@
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Teacher } from '../model/teacher.model';
@Injectable({
providedIn: 'root',
})
export class TeacherStore {
private teachers = new BehaviorSubject<Teacher[]>([]);
teachers$ = this.teachers.asObservable();
addAll(teachers: Teacher[]) {
this.teachers.next(teachers);
}
addOne(teacher: Teacher) {
this.teachers.next([...this.teachers.value, teacher]);
}
deleteOne(id: number) {
this.teachers.next(this.teachers.value.filter((t) => t.id !== id));
}
}

View File

@@ -0,0 +1,5 @@
export enum CardType {
TEACHER,
STUDENT,
CITY,
}

View File

@@ -0,0 +1,5 @@
export interface City {
id: number;
name: string;
country: string;
}

View File

@@ -0,0 +1,9 @@
import { Teacher } from './teacher.model';
export interface Student {
id: number;
firstname: string;
lastname: string;
mainTeacher: Teacher;
school: string;
}

View File

@@ -0,0 +1,15 @@
export const subject = [
'Sciences',
'History',
'English',
'Maths',
'Sport',
] as const;
export type Subject = (typeof subject)[number];
export interface Teacher {
id: number;
firstname: string;
lastname: string;
subject: Subject;
}

View File

@@ -0,0 +1,27 @@
<div
class="border-2 border-black rounded-md p-4 w-fit flex flex-col gap-3"
[class]="customClass">
<img
*ngIf="type === CardType.TEACHER"
src="assets/img/teacher.png"
width="200px" />
<img
*ngIf="type === CardType.STUDENT"
src="assets/img/student.webp"
width="200px" />
<section>
<app-list-item
*ngFor="let item of list"
[name]="item.firstname"
[id]="item.id"
[type]="type">
</app-list-item>
</section>
<button
class="border border-blue-500 bg-blue-300 p-2 rounded-sm"
(click)="addNewItem()">
Add
</button>
</div>

View File

@@ -0,0 +1,34 @@
import { NgFor, NgIf } from '@angular/common';
import { Component, 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';
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
standalone: true,
imports: [NgIf, NgFor, ListItemComponent],
})
export class CardComponent {
@Input() list: any[] | null = null;
@Input() type!: CardType;
@Input() customClass = '';
CardType = CardType;
constructor(
private teacherStore: TeacherStore,
private studentStore: StudentStore
) {}
addNewItem() {
if (this.type === CardType.TEACHER) {
this.teacherStore.addOne(randTeacher());
} else if (this.type === CardType.STUDENT) {
this.studentStore.addOne(randStudent());
}
}
}

View File

@@ -0,0 +1,35 @@
import { Component, Input } 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: `
<div class="border border-grey-300 py-1 px-2 flex justify-between">
{{ name }}
<button (click)="delete(id)">
<img class="h-5" src="assets/svg/trash.svg" />
</button>
</div>
`,
standalone: true,
})
export class ListItemComponent {
@Input() id!: number;
@Input() name!: string;
@Input() type!: CardType;
constructor(
private teacherStore: TeacherStore,
private studentStore: StudentStore
) {}
delete(id: number) {
if (this.type === CardType.TEACHER) {
this.teacherStore.deleteOne(id);
} else if (this.type === CardType.STUDENT) {
this.studentStore.deleteOne(id);
}
}
}