From 28c70fc51266ef8babe6670c7c1c43c3d067bfe6 Mon Sep 17 00:00:00 2001 From: Manuel Rauber Date: Fri, 26 Jan 2024 16:41:12 +0100 Subject: [PATCH] feat: character main stats --- .../character-dashboard.component.html | 40 +++++++++++++- .../character-dashboard.component.ts | 53 +++++++++++++++++-- .../character-statistic.component.css | 3 ++ .../character-statistic.component.html | 49 +++++++++++++++++ .../character-statistic.component.ts | 18 +++++++ .../content-group/content-group.component.css | 0 .../content-group.component.html | 6 +++ .../content-group/content-group.component.ts | 14 +++++ .../edit-mode/edit-mode.component.css | 0 .../edit-mode/edit-mode.component.html | 5 ++ .../edit-mode/edit-mode.component.ts | 18 +++++++ .../components/header/header.component.html | 3 +- src/app/components/header/header.component.ts | 3 +- .../components/headings/h1/h1.component.html | 2 +- .../components/headings/h2/h2.component.css | 0 .../components/headings/h2/h2.component.html | 3 ++ .../components/headings/h2/h2.component.ts | 11 ++++ src/app/services/tables/character.table.ts | 8 ++- src/app/stores/character.store.ts | 12 ++++- src/app/stores/edit-mode.store.ts | 24 +++++++++ 20 files changed, 262 insertions(+), 10 deletions(-) create mode 100644 src/app/components/characters/character-statistic/character-statistic.component.css create mode 100644 src/app/components/characters/character-statistic/character-statistic.component.html create mode 100644 src/app/components/characters/character-statistic/character-statistic.component.ts create mode 100644 src/app/components/content-group/content-group.component.css create mode 100644 src/app/components/content-group/content-group.component.html create mode 100644 src/app/components/content-group/content-group.component.ts create mode 100644 src/app/components/edit-mode/edit-mode.component.css create mode 100644 src/app/components/edit-mode/edit-mode.component.html create mode 100644 src/app/components/edit-mode/edit-mode.component.ts create mode 100644 src/app/components/headings/h2/h2.component.css create mode 100644 src/app/components/headings/h2/h2.component.html create mode 100644 src/app/components/headings/h2/h2.component.ts create mode 100644 src/app/stores/edit-mode.store.ts diff --git a/src/app/components/characters/character-dashboard/character-dashboard.component.html b/src/app/components/characters/character-dashboard/character-dashboard.component.html index f9c0d1e..ed76017 100644 --- a/src/app/components/characters/character-dashboard/character-dashboard.component.html +++ b/src/app/components/characters/character-dashboard/character-dashboard.component.html @@ -1 +1,39 @@ -

character-dashboard works!

+{{ character().name }} + + + + + + + + + diff --git a/src/app/components/characters/character-dashboard/character-dashboard.component.ts b/src/app/components/characters/character-dashboard/character-dashboard.component.ts index 5fc1ce2..158b809 100644 --- a/src/app/components/characters/character-dashboard/character-dashboard.component.ts +++ b/src/app/components/characters/character-dashboard/character-dashboard.component.ts @@ -1,11 +1,58 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { CharacterStore } from '../../../stores/character.store'; +import { filter, map } from 'rxjs'; +import { toSignal } from '@angular/core/rxjs-interop'; +import { H1Component } from '../../headings/h1/h1.component'; +import { CharacterStatisticComponent } from '../character-statistic/character-statistic.component'; +import { CharacterEntity } from '../../../models/character/character.entity'; +import { ContentGroupComponent } from '../../content-group/content-group.component'; +import { EditModeStore } from '../../../stores/edit-mode.store'; @Component({ selector: 'pap-character-dashboard', standalone: true, - imports: [], + imports: [H1Component, CharacterStatisticComponent, ContentGroupComponent], templateUrl: './character-dashboard.component.html', styleUrl: './character-dashboard.component.css', changeDetection: ChangeDetectionStrategy.OnPush, }) -export default class CharacterDashboardComponent {} +export default class CharacterDashboardComponent { + private readonly activatedRoute = inject(ActivatedRoute); + private readonly characterStore = inject(CharacterStore); + private readonly id = toSignal( + this.activatedRoute.paramMap.pipe( + map(params => params.get('id')), + filter(id => !!id), + map(id => +id!), + ), + ); + protected readonly character = computed(() => { + return this.characterStore.entityMap()[this.id()!]; + }); + protected readonly editModeStore = inject(EditModeStore); + + protected updateStrength(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, strength: character.strength + increment }); + } + + protected updateAgility(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, agility: character.agility + increment }); + } + + protected updateStamina(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, stamina: character.stamina + increment }); + } + + protected updateMagic(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, magic: character.magic + increment }); + } + + protected updateSpirit(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, spirit: character.spirit + increment }); + } + + protected updateIntelligence(character: CharacterEntity, increment: number) { + void this.characterStore.update({ ...character, intelligence: character.intelligence + increment }); + } +} diff --git a/src/app/components/characters/character-statistic/character-statistic.component.css b/src/app/components/characters/character-statistic/character-statistic.component.css new file mode 100644 index 0000000..52d0451 --- /dev/null +++ b/src/app/components/characters/character-statistic/character-statistic.component.css @@ -0,0 +1,3 @@ +:host { + @apply block; +} diff --git a/src/app/components/characters/character-statistic/character-statistic.component.html b/src/app/components/characters/character-statistic/character-statistic.component.html new file mode 100644 index 0000000..4194cb4 --- /dev/null +++ b/src/app/components/characters/character-statistic/character-statistic.component.html @@ -0,0 +1,49 @@ +
+

{{ label }}

+ + @if (!allowEdit) { +

{{ value }}

+ } + + @if (allowEdit) { +
+

{{ value }}

+
+ @if (allowTenIncrement) { + + } + + + + + @if (allowTenIncrement) { + + } +
+
+ } +
diff --git a/src/app/components/characters/character-statistic/character-statistic.component.ts b/src/app/components/characters/character-statistic/character-statistic.component.ts new file mode 100644 index 0000000..e24f363 --- /dev/null +++ b/src/app/components/characters/character-statistic/character-statistic.component.ts @@ -0,0 +1,18 @@ +import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; + +@Component({ + selector: 'pap-character-statistic', + standalone: true, + imports: [], + templateUrl: './character-statistic.component.html', + styleUrl: './character-statistic.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class CharacterStatisticComponent { + @Input({ required: true }) label!: string; + @Input() allowEdit = false; + @Input() allowOneIncrement = true; + @Input() allowTenIncrement = true; + @Input({ required: true }) value!: number; + @Output() incrementChange = new EventEmitter(); +} diff --git a/src/app/components/content-group/content-group.component.css b/src/app/components/content-group/content-group.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/content-group/content-group.component.html b/src/app/components/content-group/content-group.component.html new file mode 100644 index 0000000..2026fd5 --- /dev/null +++ b/src/app/components/content-group/content-group.component.html @@ -0,0 +1,6 @@ +
+
+ {{ label }} + +
+
diff --git a/src/app/components/content-group/content-group.component.ts b/src/app/components/content-group/content-group.component.ts new file mode 100644 index 0000000..684edc4 --- /dev/null +++ b/src/app/components/content-group/content-group.component.ts @@ -0,0 +1,14 @@ +import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; +import { H2Component } from '../headings/h2/h2.component'; + +@Component({ + selector: 'pap-content-group', + standalone: true, + imports: [H2Component], + templateUrl: './content-group.component.html', + styleUrl: './content-group.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class ContentGroupComponent { + @Input({ required: true }) label!: string; +} diff --git a/src/app/components/edit-mode/edit-mode.component.css b/src/app/components/edit-mode/edit-mode.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/edit-mode/edit-mode.component.html b/src/app/components/edit-mode/edit-mode.component.html new file mode 100644 index 0000000..f5ac630 --- /dev/null +++ b/src/app/components/edit-mode/edit-mode.component.html @@ -0,0 +1,5 @@ + diff --git a/src/app/components/edit-mode/edit-mode.component.ts b/src/app/components/edit-mode/edit-mode.component.ts new file mode 100644 index 0000000..2546890 --- /dev/null +++ b/src/app/components/edit-mode/edit-mode.component.ts @@ -0,0 +1,18 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { EditModeStore } from '../../stores/edit-mode.store'; +import { FaIconComponent } from '@fortawesome/angular-fontawesome'; +import { faCheck, faPenToSquare } from '@fortawesome/free-solid-svg-icons'; + +@Component({ + selector: 'pap-edit-mode', + standalone: true, + imports: [FaIconComponent], + templateUrl: './edit-mode.component.html', + styleUrl: './edit-mode.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class EditModeComponent { + protected readonly editModeStore = inject(EditModeStore); + protected readonly faCheck = faCheck; + protected readonly faPenToSquare = faPenToSquare; +} diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index eeea890..d5e2c81 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -15,7 +15,8 @@
- + +
diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index 541242a..1f28044 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -2,11 +2,12 @@ import { ChangeDetectionStrategy, Component } from '@angular/core'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { faBars, faDiceD20 } from '@fortawesome/free-solid-svg-icons'; import { DarkLightModeComponent } from '../dark-light-mode/dark-light-mode.component'; +import { EditModeComponent } from '../edit-mode/edit-mode.component'; @Component({ selector: 'pap-header', standalone: true, - imports: [FaIconComponent, DarkLightModeComponent], + imports: [FaIconComponent, DarkLightModeComponent, EditModeComponent], templateUrl: './header.component.html', styleUrl: './header.component.css', changeDetection: ChangeDetectionStrategy.OnPush, diff --git a/src/app/components/headings/h1/h1.component.html b/src/app/components/headings/h1/h1.component.html index 41f18bc..accc91f 100644 --- a/src/app/components/headings/h1/h1.component.html +++ b/src/app/components/headings/h1/h1.component.html @@ -1,3 +1,3 @@ -

+

diff --git a/src/app/components/headings/h2/h2.component.css b/src/app/components/headings/h2/h2.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/components/headings/h2/h2.component.html b/src/app/components/headings/h2/h2.component.html new file mode 100644 index 0000000..4496b25 --- /dev/null +++ b/src/app/components/headings/h2/h2.component.html @@ -0,0 +1,3 @@ +

+ +

diff --git a/src/app/components/headings/h2/h2.component.ts b/src/app/components/headings/h2/h2.component.ts new file mode 100644 index 0000000..513f8fb --- /dev/null +++ b/src/app/components/headings/h2/h2.component.ts @@ -0,0 +1,11 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; + +@Component({ + selector: 'pap-h2', + standalone: true, + imports: [], + templateUrl: './h2.component.html', + styleUrl: './h2.component.css', + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class H2Component {} diff --git a/src/app/services/tables/character.table.ts b/src/app/services/tables/character.table.ts index 5fb05af..747ce12 100644 --- a/src/app/services/tables/character.table.ts +++ b/src/app/services/tables/character.table.ts @@ -19,8 +19,8 @@ export class CharacterTable implements DatabaseTable { return this.entities.toArray(); } - item(id: number): Promise { - return this.entities.get(id); + async update(character: CharacterEntity) { + await this.entities.update(character.id, character); } async add(name: string): Promise { @@ -37,4 +37,8 @@ export class CharacterTable implements DatabaseTable { const character = await this.item(id); return character!; } + + private item(id: number): Promise { + return this.entities.get(id); + } } diff --git a/src/app/stores/character.store.ts b/src/app/stores/character.store.ts index d0c8ede..b93736d 100644 --- a/src/app/stores/character.store.ts +++ b/src/app/stores/character.store.ts @@ -1,5 +1,5 @@ import { patchState, signalStore, withComputed, withMethods } from '@ngrx/signals'; -import { addEntity, setAllEntities, withEntities } from '@ngrx/signals/entities'; +import { addEntity, setAllEntities, updateEntity, withEntities } from '@ngrx/signals/entities'; import { CharacterEntity } from '../models/character/character.entity'; import { CharacterTable } from '../services/tables/character.table'; import { computed, effect, inject, Injector } from '@angular/core'; @@ -23,6 +23,16 @@ export const CharacterStore = signalStore( return newCharacter.id; }, + update: async (character: CharacterEntity) => { + await characterTable.update(character); + patchState( + store, + updateEntity({ + id: character.id, + changes: character, + }), + ); + }, }; }), withComputed(({ ids }) => ({ diff --git a/src/app/stores/edit-mode.store.ts b/src/app/stores/edit-mode.store.ts new file mode 100644 index 0000000..a18265a --- /dev/null +++ b/src/app/stores/edit-mode.store.ts @@ -0,0 +1,24 @@ +import { patchState, signalStore, withComputed, withMethods, withState } from '@ngrx/signals'; +import { computed } from '@angular/core'; + +interface EditModeState { + mode: 'read' | 'write'; +} + +export const EditModeStore = signalStore( + { providedIn: 'root' }, + withState({ mode: 'read' }), + withMethods(store => { + return { + enableEditMode: () => { + patchState(store, { mode: 'write' }); + }, + disableEditMode: () => { + patchState(store, { mode: 'read' }); + }, + }; + }), + withComputed(store => ({ + isEnabled: computed(() => store.mode() === 'write'), + })), +);