diff --git a/package.json b/package.json index 0974130..98afe1b 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,13 @@ "@angular-devkit/build-angular": "^15.1.5", "@angular/cli": "~15.1.5", "@angular/compiler-cli": "^15.1.0", + "angular-in-memory-web-api": "^0.15.0", + "cz-conventional-changelog": "^3.3.0", "typescript": "~4.9.4" + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8e27d34..fb21f00 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,15 +1,27 @@ import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BrowserModule } from '@angular/platform-browser'; +import { HttpClientModule } from '@angular/common/http'; +import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { PokemonModule } from './pokemon/pokemon.module'; +import { InMemoryDataService } from './in-memory-data.service'; @NgModule({ declarations: [AppComponent, PageNotFoundComponent], - imports: [BrowserModule, FormsModule, PokemonModule, AppRoutingModule], + imports: [ + BrowserModule, + FormsModule, + HttpClientModule, + HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService, { + dataEncapsulation: false, + }), + PokemonModule, + AppRoutingModule, + ], providers: [], bootstrap: [AppComponent], }) diff --git a/src/app/in-memory-data.service.ts b/src/app/in-memory-data.service.ts new file mode 100644 index 0000000..9133229 --- /dev/null +++ b/src/app/in-memory-data.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@angular/core'; +import { InMemoryDbService } from 'angular-in-memory-web-api'; +import { POKEMONS } from './pokemon/mock-pokemon-list'; + +@Injectable({ + providedIn: 'root', +}) +export class InMemoryDataService implements InMemoryDbService { + createDb() { + const pokemons = POKEMONS; + return { pokemons }; + } + + constructor() {} +} diff --git a/src/app/pokemon/add-pokemon/add-pokemon.component.html b/src/app/pokemon/add-pokemon/add-pokemon.component.html new file mode 100644 index 0000000..3f6c643 --- /dev/null +++ b/src/app/pokemon/add-pokemon/add-pokemon.component.html @@ -0,0 +1,2 @@ +

Ajouter un pokémon

+ diff --git a/src/app/pokemon/add-pokemon/add-pokemon.component.ts b/src/app/pokemon/add-pokemon/add-pokemon.component.ts new file mode 100644 index 0000000..20462d4 --- /dev/null +++ b/src/app/pokemon/add-pokemon/add-pokemon.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; +import { Pokemon } from '../pokemon'; + +@Component({ + selector: 'app-add-pokemon', + templateUrl: './add-pokemon.component.html', + styles: [], +}) +export class AddPokemonComponent implements OnInit { + pokemon: Pokemon; + + ngOnInit() { + this.pokemon = new Pokemon(); + } +} diff --git a/src/app/pokemon/detail-pokemon/detail-pokemon.component.html b/src/app/pokemon/detail-pokemon/detail-pokemon.component.html index 7a536c5..fe42eb2 100644 --- a/src/app/pokemon/detail-pokemon/detail-pokemon.component.html +++ b/src/app/pokemon/detail-pokemon/detail-pokemon.component.html @@ -49,6 +49,7 @@
Retour Modifier + Supprimer
diff --git a/src/app/pokemon/detail-pokemon/detail-pokemon.component.ts b/src/app/pokemon/detail-pokemon/detail-pokemon.component.ts index 02e0347..390be53 100644 --- a/src/app/pokemon/detail-pokemon/detail-pokemon.component.ts +++ b/src/app/pokemon/detail-pokemon/detail-pokemon.component.ts @@ -19,10 +19,18 @@ export class DetailPokemonComponent implements OnInit { ngOnInit(): void { const pokemonId: string | null = this.route.snapshot.paramMap.get('id'); if (pokemonId) { - this.pokemon = this.pokemonService.getPokemonById(+pokemonId); + this.pokemonService + .getPokemonById(+pokemonId) + .subscribe((pokemon) => (this.pokemon = pokemon)); } } + deletePokemon(pokemon: Pokemon) { + this.pokemonService + .deletePokemonById(pokemon) + .subscribe(() => this.goToPokemonList()); + } + goToPokemonList() { this.router.navigate(['/pokemons']); } diff --git a/src/app/pokemon/edit-pokemon/edit-pokemon.component.ts b/src/app/pokemon/edit-pokemon/edit-pokemon.component.ts index 81964f9..3bf366f 100644 --- a/src/app/pokemon/edit-pokemon/edit-pokemon.component.ts +++ b/src/app/pokemon/edit-pokemon/edit-pokemon.component.ts @@ -19,7 +19,9 @@ export class EditPokemonComponent implements OnInit { ngOnInit() { const pokemonId: string | null = this.route.snapshot.paramMap.get('id'); if (pokemonId) { - this.pokemon = this.pokemonService.getPokemonById(+pokemonId); + this.pokemonService + .getPokemonById(+pokemonId) + .subscribe((pokemon) => (this.pokemon = pokemon)); } } } diff --git a/src/app/pokemon/list-pokemon/list-pokemon.component.html b/src/app/pokemon/list-pokemon/list-pokemon.component.html index cffce96..4ab7c02 100644 --- a/src/app/pokemon/list-pokemon/list-pokemon.component.html +++ b/src/app/pokemon/list-pokemon/list-pokemon.component.html @@ -29,3 +29,9 @@ + diff --git a/src/app/pokemon/list-pokemon/list-pokemon.component.ts b/src/app/pokemon/list-pokemon/list-pokemon.component.ts index 2b9485d..6e51022 100644 --- a/src/app/pokemon/list-pokemon/list-pokemon.component.ts +++ b/src/app/pokemon/list-pokemon/list-pokemon.component.ts @@ -13,7 +13,9 @@ export class ListPokemonComponent implements OnInit { constructor(private router: Router, private pokemonService: PokemonService) {} ngOnInit() { - this.pokemonList = this.pokemonService.getPokemonList(); + this.pokemonService + .getPokemonList() + .subscribe((pokemonList) => (this.pokemonList = pokemonList)); } goToPokemon(pokemon: Pokemon) { diff --git a/src/app/pokemon/pokemon-form/pokemon-form.component.html b/src/app/pokemon/pokemon-form/pokemon-form.component.html index e27799f..412dae5 100644 --- a/src/app/pokemon/pokemon-form/pokemon-form.component.html +++ b/src/app/pokemon/pokemon-form/pokemon-form.component.html @@ -24,6 +24,27 @@ + +
+ + + +
+ L’image du pokémon est requise. +
+
+
diff --git a/src/app/pokemon/pokemon-form/pokemon-form.component.ts b/src/app/pokemon/pokemon-form/pokemon-form.component.ts index ad0c5ae..caa82d9 100644 --- a/src/app/pokemon/pokemon-form/pokemon-form.component.ts +++ b/src/app/pokemon/pokemon-form/pokemon-form.component.ts @@ -11,11 +11,15 @@ import { PokemonService } from '../pokemon.service'; export class PokemonFormComponent implements OnInit { @Input() pokemon: Pokemon; types: string[]; + isAddForm: boolean; constructor(private pokemonService: PokemonService, private router: Router) {} ngOnInit(): void { - this.types = this.pokemonService.getPokemonTypeList(); + this.pokemonService + .getPokemonTypeList() + .subscribe((types) => (this.types = types)); + this.isAddForm = this.router.url.includes('add'); } hasType(type: string) { @@ -33,8 +37,17 @@ export class PokemonFormComponent implements OnInit { } onSubmit() { - console.log('Submit form!'); - this.router.navigate(['/pokemon', this.pokemon.id]); + if (this.isAddForm) { + this.pokemonService + .addPokemon(this.pokemon) + .subscribe((pokemon: Pokemon) => { + this.router.navigate(['/pokemon', pokemon.id]); + }); + } else { + this.pokemonService.updatePokemon(this.pokemon).subscribe(() => { + this.router.navigate(['/pokemon', this.pokemon.id]); + }); + } } isTypesValid(type: string): boolean { diff --git a/src/app/pokemon/pokemon.module.ts b/src/app/pokemon/pokemon.module.ts index 9a0f19b..9a2d47d 100644 --- a/src/app/pokemon/pokemon.module.ts +++ b/src/app/pokemon/pokemon.module.ts @@ -10,9 +10,11 @@ import { PokemonService } from './pokemon.service'; import { FormsModule } from '@angular/forms'; import { PokemonFormComponent } from './pokemon-form/pokemon-form.component'; import { EditPokemonComponent } from './edit-pokemon/edit-pokemon.component'; +import { AddPokemonComponent } from './add-pokemon/add-pokemon.component'; const pokemonRoutes: Routes = [ { path: 'edit/pokemon/:id', component: EditPokemonComponent }, + { path: 'pokemon/add', component: AddPokemonComponent }, { path: 'pokemon/:id', component: DetailPokemonComponent }, { path: 'pokemons', component: ListPokemonComponent }, ]; @@ -25,6 +27,7 @@ const pokemonRoutes: Routes = [ DetailPokemonComponent, PokemonFormComponent, EditPokemonComponent, + AddPokemonComponent, ], imports: [CommonModule, FormsModule, RouterModule.forChild(pokemonRoutes)], providers: [PokemonService], diff --git a/src/app/pokemon/pokemon.service.ts b/src/app/pokemon/pokemon.service.ts index 01bbb2f..fc27bee 100644 --- a/src/app/pokemon/pokemon.service.ts +++ b/src/app/pokemon/pokemon.service.ts @@ -1,22 +1,74 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { POKEMONS } from './mock-pokemon-list'; +import { catchError, mergeMap, Observable, of, tap } from 'rxjs'; import { Pokemon } from './pokemon'; @Injectable() export class PokemonService { - getPokemonList(): Pokemon[] { - return POKEMONS; + constructor(private http: HttpClient) {} + + getPokemonList(): Observable { + return this.http.get('api/pokemons').pipe( + tap((pokemonList) => this.log(pokemonList)), + catchError((error) => this.handleError(error, [])) + ); } - getPokemonById(pokemonId: number): Pokemon | undefined { - return POKEMONS.find((pokemon) => pokemon.id === pokemonId); + getPokemonById(pokemonId: number): Observable { + return this.http.get(`api/pokemons/${pokemonId}`).pipe( + tap((pokemon) => this.log(pokemon)), + catchError((error) => this.handleError(error, undefined)) + ); } - getPokemonTypeList(): string[] { - const types: Set = new Set(); - POKEMONS.forEach((pokemon) => { - pokemon.types.forEach((type) => types.add(type)); - }); - return Array.from(types.values()); + getPokemonTypeList(): Observable { + return this.http.get('api/pokemons').pipe( + mergeMap((pokemons: Pokemon[]) => { + const set = new Set(); + pokemons.forEach((pokemon) => + pokemon.types.forEach((type) => set.add(type)) + ); + return [Array.from(set.values())]; + }), + tap((pokemon) => this.log(pokemon)), + catchError((error) => this.handleError(error, [])) + ); + } + + updatePokemon(pokemon: Pokemon): Observable { + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + }; + return this.http.put('api/pokemons', pokemon, httpOptions).pipe( + tap((response) => this.log(response)), + catchError((error) => this.handleError(error, null)) + ); + } + + addPokemon(pokemon: Pokemon): Observable { + const httpOptions = { + headers: new HttpHeaders({ 'Content-Type': 'application/json' }), + }; + + return this.http.post('api/pokemons', pokemon, httpOptions).pipe( + tap((response) => this.log(response)), + catchError((error) => this.handleError(error, null)) + ); + } + + deletePokemonById(pokemon: Pokemon): Observable { + return this.http.delete(`api/pokemons/${pokemon.id}`).pipe( + tap((response) => this.log(response)), + catchError((error) => this.handleError(error, null)) + ); + } + + private log(response: any) { + console.table(response); + } + + private handleError(error: Error, errorValue: any) { + console.error(error); + return of(errorValue); } } diff --git a/src/app/pokemon/pokemon.ts b/src/app/pokemon/pokemon.ts index 71b3abc..be31c38 100644 --- a/src/app/pokemon/pokemon.ts +++ b/src/app/pokemon/pokemon.ts @@ -1,9 +1,25 @@ export class Pokemon { id: number; + name: string; hp: number; cp: number; - name: string; picture: string; types: Array; created: Date; + + constructor( + name: string = 'Enter a name...', + hp: number = 100, + cp: number = 10, + picture: string = 'https://assets.pokemon.com/assets/cms2/img/pokedex/detail/xxx.png', + types: string[] = ['Normal'], + created: Date = new Date() + ) { + this.hp = hp; + this.cp = cp; + this.name = name; + this.picture = picture; + this.types = types; + this.created = created; + } }