From b37f41e4b877f444fcfdb9de09a49057d93023e2 Mon Sep 17 00:00:00 2001 From: Ronan Connolly Date: Mon, 29 Apr 2024 19:21:38 +0200 Subject: [PATCH] Hook up the API, and add all the necessary elements --- src/app/app.component.ts | 3 +- src/app/app.config.ts | 7 ++- src/app/app.routes.ts | 3 +- .../chuck-norris-joke-generator.constant.ts | 1 + .../chuck-norris-joke-generator.model.ts | 6 +++ ...huck-norris-joke-generator.service.spec.ts | 16 ++++++ .../chuck-norris-joke-generator.service.ts | 19 +++++++ src/app/favourites/favourites.component.html | 1 + src/app/favourites/favourites.component.scss | 0 .../favourites/favourites.component.spec.ts | 23 +++++++++ src/app/favourites/favourites.component.ts | 11 ++++ src/app/home/home.component.scss | 6 +++ src/app/home/home.component.ts | 2 +- src/app/joke-store/joke-store.service.spec.ts | 16 ++++++ src/app/joke-store/joke-store.service.ts | 22 ++++++++ src/app/jokes/jokes.component.scss | 25 ++++++++++ src/app/jokes/jokes.component.ts | 47 ++++-------------- src/favicon.ico | Bin 15086 -> 15406 bytes src/index.html | 2 +- 19 files changed, 169 insertions(+), 41 deletions(-) create mode 100644 src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.constant.ts create mode 100644 src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.model.ts create mode 100644 src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.spec.ts create mode 100644 src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.ts create mode 100644 src/app/favourites/favourites.component.html create mode 100644 src/app/favourites/favourites.component.scss create mode 100644 src/app/favourites/favourites.component.spec.ts create mode 100644 src/app/favourites/favourites.component.ts create mode 100644 src/app/joke-store/joke-store.service.spec.ts create mode 100644 src/app/joke-store/joke-store.service.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index cf8a471..dbd14d2 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,10 +1,11 @@ +import { HttpClientModule } from '@angular/common/http'; import { Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'cnjg-root', standalone: true, - imports: [RouterOutlet], + imports: [RouterOutlet, HttpClientModule], template: '', }) export class AppComponent {} diff --git a/src/app/app.config.ts b/src/app/app.config.ts index bcd5df3..ecf3b75 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -3,7 +3,12 @@ import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; +import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { - providers: [provideRouter(routes), provideAnimationsAsync()], + providers: [ + provideRouter(routes), + provideAnimationsAsync(), + provideHttpClient(), + ], }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 0443762..329bec9 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,7 +1,8 @@ import { Routes } from '@angular/router'; import { HomeComponent } from './home/home.component'; +import { FavouritesComponent } from './favourites/favourites.component'; export const routes: Routes = [ { path: '', component: HomeComponent }, - // Add more routes here if needed + { path: 'favourites', component: FavouritesComponent }, ]; diff --git a/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.constant.ts b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.constant.ts new file mode 100644 index 0000000..5ef4d04 --- /dev/null +++ b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.constant.ts @@ -0,0 +1 @@ +export const chuckNorrisApi = 'https://api.chucknorris.io/jokes/random'; diff --git a/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.model.ts b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.model.ts new file mode 100644 index 0000000..fd70d83 --- /dev/null +++ b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.model.ts @@ -0,0 +1,6 @@ +export interface ChuckNorrisJoke { + icon_url: string; + id: string; + url: string; + value: string; +} diff --git a/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.spec.ts b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.spec.ts new file mode 100644 index 0000000..245aa8d --- /dev/null +++ b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ChuckNorrisJokeGeneratorService } from './chuck-norris-joke-generator.service'; + +describe('ChuckNorrisJokeGeneratorService', () => { + let service: ChuckNorrisJokeGeneratorService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ChuckNorrisJokeGeneratorService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.ts b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.ts new file mode 100644 index 0000000..0737dd5 --- /dev/null +++ b/src/app/chuck-norris-joke-generator/chuck-norris-joke-generator.service.ts @@ -0,0 +1,19 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { ChuckNorrisJoke } from './chuck-norris-joke-generator.model'; +import { Observable, forkJoin, map, switchMap, tap } from 'rxjs'; +import { chuckNorrisApi } from './chuck-norris-joke-generator.constant'; + +@Injectable({ + providedIn: 'root', +}) +export class ChuckNorrisJokeGeneratorService { + constructor(private httpClient: HttpClient) {} + + public getJoke(): Observable { + return this.httpClient.get(chuckNorrisApi).pipe( + tap((joke) => console.log(joke)), + map((joke) => joke.value) + ); + } +} diff --git a/src/app/favourites/favourites.component.html b/src/app/favourites/favourites.component.html new file mode 100644 index 0000000..14a5819 --- /dev/null +++ b/src/app/favourites/favourites.component.html @@ -0,0 +1 @@ +

favourites works!

diff --git a/src/app/favourites/favourites.component.scss b/src/app/favourites/favourites.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/app/favourites/favourites.component.spec.ts b/src/app/favourites/favourites.component.spec.ts new file mode 100644 index 0000000..b0e14d5 --- /dev/null +++ b/src/app/favourites/favourites.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { FavouritesComponent } from './favourites.component'; + +describe('FavouritesComponent', () => { + let component: FavouritesComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [FavouritesComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(FavouritesComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/favourites/favourites.component.ts b/src/app/favourites/favourites.component.ts new file mode 100644 index 0000000..a0dd239 --- /dev/null +++ b/src/app/favourites/favourites.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'cnjg-favourites', + standalone: true, + imports: [], + templateUrl: './favourites.component.html', + styleUrl: './favourites.component.scss', + // changeDetection: ChangeDetectionStrategy.OnPush +}) +export class FavouritesComponent {} diff --git a/src/app/home/home.component.scss b/src/app/home/home.component.scss index e69de29..e4dca38 100644 --- a/src/app/home/home.component.scss +++ b/src/app/home/home.component.scss @@ -0,0 +1,6 @@ +:host { + display: flex; + flex-direction: column; + align-items: center; + padding: 25px; +} diff --git a/src/app/home/home.component.ts b/src/app/home/home.component.ts index 081f0d3..df2fb26 100644 --- a/src/app/home/home.component.ts +++ b/src/app/home/home.component.ts @@ -7,6 +7,6 @@ import { JokesComponent } from '../jokes/jokes.component'; imports: [JokesComponent], templateUrl: './home.component.html', styleUrl: './home.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, + // changeDetection: ChangeDetectionStrategy.OnPush, }) export class HomeComponent {} diff --git a/src/app/joke-store/joke-store.service.spec.ts b/src/app/joke-store/joke-store.service.spec.ts new file mode 100644 index 0000000..e860e0f --- /dev/null +++ b/src/app/joke-store/joke-store.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { JokeStoreService } from './joke-store.service'; + +describe('JokeStoreService', () => { + let service: JokeStoreService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(JokeStoreService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/joke-store/joke-store.service.ts b/src/app/joke-store/joke-store.service.ts new file mode 100644 index 0000000..8cd2bc9 --- /dev/null +++ b/src/app/joke-store/joke-store.service.ts @@ -0,0 +1,22 @@ +import { Injectable } from '@angular/core'; +import { ChuckNorrisJokeGeneratorService } from '../chuck-norris-joke-generator/chuck-norris-joke-generator.service'; +import { Observable, forkJoin } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class JokeStoreService { + constructor( + private chuckNorrisJokeGeneratorService: ChuckNorrisJokeGeneratorService + ) {} + + /** + * @returns a list of 10 jokes + */ + public getJokes(): Observable { + // TODO: Look into a more efficient way to do 10 concurrent requests (showing them as they return in the view): + return forkJoin( + Array(10).fill(this.chuckNorrisJokeGeneratorService.getJoke()) + ); + } +} diff --git a/src/app/jokes/jokes.component.scss b/src/app/jokes/jokes.component.scss index e69de29..1e9e856 100644 --- a/src/app/jokes/jokes.component.scss +++ b/src/app/jokes/jokes.component.scss @@ -0,0 +1,25 @@ +:host { + display: flex; + flex-direction: column; + align-items: center; + + ul { + width: 80%; + + display: flex; + flex-direction: column; + align-items: center; + + li { + list-style: none; + margin-bottom: 20px; + } + li:nth-child(even) { + color: orange; + } + + li:nth-child(odd) { + color: lightblue; + } + } +} diff --git a/src/app/jokes/jokes.component.ts b/src/app/jokes/jokes.component.ts index 64b9c7b..fe7f56f 100644 --- a/src/app/jokes/jokes.component.ts +++ b/src/app/jokes/jokes.component.ts @@ -1,5 +1,6 @@ import { CommonModule } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { Component } from '@angular/core'; +import { JokeStoreService } from '../joke-store/joke-store.service'; @Component({ selector: 'cnjg-jokes', @@ -7,41 +8,15 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; imports: [CommonModule], templateUrl: './jokes.component.html', styleUrl: './jokes.component.scss', - changeDetection: ChangeDetectionStrategy.OnPush, + // changeDetection: ChangeDetectionStrategy.OnPush, }) export class JokesComponent { - public jokes = [ - 'Joke 1', - 'Joke 2', - 'Joke 3', - 'Joke 4', - 'Joke 5', - 'Joke 6', - 'Joke 7', - 'Joke 8', - 'Joke 9', - 'Joke 10', - 'Joke 11', - 'Joke 12', - 'Joke 13', - 'Joke 14', - 'Joke 15', - 'Joke 16', - 'Joke 17', - 'Joke 18', - 'Joke 19', - 'Joke 20', - 'Joke 21', - 'Joke 22', - 'Joke 23', - 'Joke 24', - 'Joke 25', - 'Joke 26', - 'Joke 27', - 'Joke 28', - 'Joke 29', - 'Joke 30', - 'Joke 31', - 'Joke 32', - ]; + public jokes: string[] = []; + + constructor(private jokeStoreService: JokeStoreService) { + // TODO: Look into using async pipe? + this.jokeStoreService.getJokes().subscribe((jokes) => { + this.jokes = jokes; + }); + } } diff --git a/src/favicon.ico b/src/favicon.ico index 57614f9c967596fad0a3989bec2b1deff33034f6..0eb37c59fe47c8d63692d9084a5070c56500525b 100644 GIT binary patch literal 15406 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 literal 15086 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 Nr__JTFzvMr^FKp4S3v*( diff --git a/src/index.html b/src/index.html index 4f6114c..1746ff7 100644 --- a/src/index.html +++ b/src/index.html @@ -2,7 +2,7 @@ - ChuckNorrisJokeGenerator + Chuck Norris Joke Generator