From 3aec16246ac2a85e19bdcdf963abb9f347c39a1a Mon Sep 17 00:00:00 2001 From: Andrew Kemp Date: Wed, 13 May 2020 12:55:31 -0400 Subject: [PATCH] Added pre and post game UI states --- src/app/app.component.css | 7 ++++ src/app/app.component.html | 7 +++- src/app/app.component.ts | 8 +++++ src/app/app.module.ts | 33 +++++++++++++++---- src/app/game-card/game-card.component.css | 24 ++++++++++++++ src/app/game-card/game-card.component.html | 16 +++++++++ src/app/game-card/game-card.component.ts | 33 +++++++++++++++++++ .../match-results/match-results.component.css | 23 +++++++++++++ .../match-results.component.html | 17 ++++++++++ .../match-results/match-results.component.ts | 21 ++++++++++++ src/app/store/game/game.facade.ts | 10 +++--- src/app/store/game/game.selectors.ts | 2 ++ 12 files changed, 190 insertions(+), 11 deletions(-) create mode 100644 src/app/game-card/game-card.component.css create mode 100644 src/app/game-card/game-card.component.html create mode 100644 src/app/game-card/game-card.component.ts create mode 100644 src/app/match-results/match-results.component.css create mode 100644 src/app/match-results/match-results.component.html create mode 100644 src/app/match-results/match-results.component.ts diff --git a/src/app/app.component.css b/src/app/app.component.css index e69de29..23fba11 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -0,0 +1,7 @@ +.app-body { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 1rem; +} \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index bbc6764..147b83f 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -6,6 +6,11 @@
- + + + + + +
\ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 68478a8..3f586bc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,9 +1,17 @@ import { Component } from '@angular/core'; +import { GameFacade } from './store/game'; + @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { + gameStatus$ = this.gameFacade.gameStatus$; + + constructor( + private readonly gameFacade: GameFacade + ) { } + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index dcd047a..467dd0b 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,26 +1,47 @@ -import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { ReactiveFormsModule, FormsModule } from '@angular/forms'; -import { MatButtonModule } from '@angular/material/button'; -import { MatToolbarModule } from '@angular/material/toolbar'; import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; +import { MatButtonModule } from '@angular/material/button'; +import { MatCardModule } from '@angular/material/card'; +import { MatIconModule } from '@angular/material/icon'; +import { MatRadioModule } from '@angular/material/radio'; +import { MatToolbarModule } from '@angular/material/toolbar'; + import { AppComponent } from './app.component'; import { GameStoreModule } from './store'; +import { DirectivesModule } from './directives/directives.module'; + +import { GameCardComponent } from './game-card/game-card.component'; +import { MatchResultsComponent } from './match-results/match-results.component'; + +const materialModules = [ + MatButtonModule, + MatCardModule, + MatIconModule, + MatRadioModule, + MatToolbarModule +]; @NgModule({ declarations: [ - AppComponent + AppComponent, + GameCardComponent, + MatchResultsComponent ], imports: [ BrowserModule, BrowserAnimationsModule, - MatButtonModule, - MatToolbarModule, + ReactiveFormsModule, + FormsModule, + ...materialModules, StoreModule.forRoot({}, {}), EffectsModule.forRoot([]), + DirectivesModule, GameStoreModule ], providers: [], diff --git a/src/app/game-card/game-card.component.css b/src/app/game-card/game-card.component.css new file mode 100644 index 0000000..2d900d1 --- /dev/null +++ b/src/app/game-card/game-card.component.css @@ -0,0 +1,24 @@ +:host { + display: block; +} + +.game-card { + width: 420px; +} + +.full-width-field { + width: 100%; +} + +:host ::ng-deep .mat-radio-group { + display: flex; + flex-direction: row; + justify-content: space-around; + margin: 1rem 0; +} + +:host ::ng-deep .mat-radio-label { + display: flex; + flex-direction: column-reverse; + margin: 1rem 0; +} \ No newline at end of file diff --git a/src/app/game-card/game-card.component.html b/src/app/game-card/game-card.component.html new file mode 100644 index 0000000..4fe09ee --- /dev/null +++ b/src/app/game-card/game-card.component.html @@ -0,0 +1,16 @@ + +
+ + + + + + + + + + +
+
\ No newline at end of file diff --git a/src/app/game-card/game-card.component.ts b/src/app/game-card/game-card.component.ts new file mode 100644 index 0000000..a3f8c2c --- /dev/null +++ b/src/app/game-card/game-card.component.ts @@ -0,0 +1,33 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; + +import { GameFacade } from "../store/game"; + +@Component({ + selector: 'app-game-card', + templateUrl: './game-card.component.html', + styleUrls: ['./game-card.component.css'] +}) +export class GameCardComponent implements OnInit { + form: FormGroup; + choices = ['rock', 'paper', 'scissors']; + + constructor( + private readonly fb: FormBuilder, + private readonly gameFacade: GameFacade + ) { } + + ngOnInit(): void { + this.form = this.fb.group({ + playerChoice: [undefined, [Validators.required]] + }); + } + + submit(event, gameForm): void { + event.preventDefault(); + this.gameFacade.play(this.form.value.playerChoice); + this.form.reset(); + gameForm.resetForm(); + } + +} diff --git a/src/app/match-results/match-results.component.css b/src/app/match-results/match-results.component.css new file mode 100644 index 0000000..e74500e --- /dev/null +++ b/src/app/match-results/match-results.component.css @@ -0,0 +1,23 @@ +:host { + display: block; +} + +.match-results { + width: 420px; +} + +.match-results-text { + font-weight: bold; +} + +.match-visual { + display: flex; + flex-direction: row; + margin: 1rem 0; + justify-content: space-around; + width: 100%; +} + +.match-visual .vs { + font-size: 3rem; +} \ No newline at end of file diff --git a/src/app/match-results/match-results.component.html b/src/app/match-results/match-results.component.html new file mode 100644 index 0000000..94656cc --- /dev/null +++ b/src/app/match-results/match-results.component.html @@ -0,0 +1,17 @@ + + Match Results + + +
You {{ results.result }}!
+
+ + vs + +
+
+ + + +
\ No newline at end of file diff --git a/src/app/match-results/match-results.component.ts b/src/app/match-results/match-results.component.ts new file mode 100644 index 0000000..1d0303f --- /dev/null +++ b/src/app/match-results/match-results.component.ts @@ -0,0 +1,21 @@ +import { Component } from '@angular/core'; + +import { GameFacade } from '../store/game'; + +@Component({ + selector: 'app-match-results', + templateUrl: './match-results.component.html', + styleUrls: ['./match-results.component.css'] +}) +export class MatchResultsComponent { + results$ = this.gameFacade.recentGameResults$; + + constructor( + private readonly gameFacade: GameFacade + ) { } + + playAgain(): void { + this.gameFacade.reset(); + } + +} diff --git a/src/app/store/game/game.facade.ts b/src/app/store/game/game.facade.ts index 2aed9be..7b21cbe 100644 --- a/src/app/store/game/game.facade.ts +++ b/src/app/store/game/game.facade.ts @@ -1,23 +1,25 @@ import { Injectable } from '@angular/core'; import { Store, select } from '@ngrx/store'; -import * as gameActions from './game.actions'; +import * as GameActions from './game.actions'; +import * as GameQuery from './game.selectors'; @Injectable() export class GameFacade { + recentGameResults$ = this.store.pipe(select(GameQuery.selectRecentMatchResults)); // gameHistory$ = this.store.pipe(select(getGameHistory)); // scores$ = this.store.pipe(select(getScores)); - // gameStatus$ = this.store.pipe(select(getGameStatus)); + gameStatus$ = this.store.pipe(select(GameQuery.selectGameStatus)); constructor( private readonly store: Store ) { } play(playerChoice: string): void { - this.store.dispatch(gameActions.playMatch({ playerChoice })); + this.store.dispatch(GameActions.playMatch({ playerChoice })); } reset(): void { - this.store.dispatch(gameActions.resetMatch()); + this.store.dispatch(GameActions.resetMatch()); } } diff --git a/src/app/store/game/game.selectors.ts b/src/app/store/game/game.selectors.ts index 859744e..029389b 100644 --- a/src/app/store/game/game.selectors.ts +++ b/src/app/store/game/game.selectors.ts @@ -4,3 +4,5 @@ import * as fromGame from './game.reducer'; export const selectGameState = createFeatureSelector( fromGame.gameFeatureKey ); +export const selectGameStatus = createSelector(selectGameState, fromGame.getGameStatus); +export const selectRecentMatchResults = createSelector(selectGameState, fromGame.getRecentMatchHistory); \ No newline at end of file