Skip to content

Commit

Permalink
feat: character main stats
Browse files Browse the repository at this point in the history
  • Loading branch information
ManuelRauber committed Jan 26, 2024
1 parent 569fb26 commit 28c70fc
Show file tree
Hide file tree
Showing 20 changed files with 262 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1,39 @@
<p>character-dashboard works!</p>
<pap-h1>{{ character().name }}</pap-h1>

<pap-content-group class="w-1/2" label="Main Stats">
<pap-character-statistic
(incrementChange)="updateStrength(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().strength"
label="Stärke"></pap-character-statistic>
<pap-character-statistic
(incrementChange)="updateAgility(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().agility"
class="mt-2"
label="Beweglichkeit"></pap-character-statistic>
<pap-character-statistic
(incrementChange)="updateStamina(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().stamina"
class="mt-2"
label="Ausdauer"></pap-character-statistic>
<pap-character-statistic
(incrementChange)="updateMagic(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().magic"
class="mt-2"
label="Magie"></pap-character-statistic>
<pap-character-statistic
(incrementChange)="updateSpirit(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().spirit"
class="mt-2"
label="Geist"></pap-character-statistic>
<pap-character-statistic
(incrementChange)="updateIntelligence(character(), $event)"
[allowEdit]="editModeStore.isEnabled()"
[value]="character().intelligence"
class="mt-2"
label="Intelligenz"></pap-character-statistic>
</pap-content-group>
Original file line number Diff line number Diff line change
@@ -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 });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
@apply block;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<div class="flex h-8 items-center justify-between">
<p>{{ label }}</p>

@if (!allowEdit) {
<p>{{ value }}</p>
}

@if (allowEdit) {
<div class="flex items-center">
<p>{{ value }}</p>
<div class="ml-4 inline-flex rounded-md shadow-sm" role="group">
@if (allowTenIncrement) {
<button
(click)="incrementChange.emit(10)"
class="rounded-s-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium hover:bg-gray-100 hover:text-green-500 focus:z-10 dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-600"
type="button">
+10
</button>
}

<button
(click)="incrementChange.emit(1)"
class="border-b border-t border-gray-200 bg-white px-4 py-2 text-sm font-medium hover:bg-gray-100 hover:text-green-500 focus:z-10 dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-600"
[class.border-l]="!allowTenIncrement"
[class.rounded-s-lg]="!allowTenIncrement"
type="button">
+1
</button>
<button
(click)="incrementChange.emit(-1)"
class="border-b border-l border-t border-gray-200 bg-white px-4 py-2 text-sm font-medium hover:bg-gray-100 hover:text-red-500 focus:z-10 dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-600"
[class.border-r]="!allowTenIncrement"
[class.rounded-e-lg]="!allowTenIncrement"
type="button">
-1
</button>

@if (allowTenIncrement) {
<button
(click)="incrementChange.emit(-10)"
class="rounded-e-lg border border-gray-200 bg-white px-4 py-2 text-sm font-medium hover:bg-gray-100 hover:text-red-500 focus:z-10 dark:border-gray-600 dark:bg-gray-700 dark:hover:bg-gray-600"
type="button">
-10
</button>
}
</div>
</div>
}
</div>
Original file line number Diff line number Diff line change
@@ -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<number>();
}
Empty file.
6 changes: 6 additions & 0 deletions src/app/components/content-group/content-group.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<div class="w-full rounded-lg bg-gray-50 shadow dark:border dark:border-gray-800 dark:bg-gray-900 sm:max-w-md md:mt-0 xl:p-0">
<div class="space-y-4 p-6 sm:p-8 md:space-y-6">
<pap-h2>{{ label }}</pap-h2>
<ng-content></ng-content>
</div>
</div>
14 changes: 14 additions & 0 deletions src/app/components/content-group/content-group.component.ts
Original file line number Diff line number Diff line change
@@ -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;
}
Empty file.
5 changes: 5 additions & 0 deletions src/app/components/edit-mode/edit-mode.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<button
(click)="editModeStore.isEnabled() ? editModeStore.disableEditMode() : editModeStore.enableEditMode()"
class="dark:hover: flex h-9 w-9 items-center justify-center rounded-lg border border-gray-200 bg-white p-2 text-xs font-medium text-gray-700 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:outline-none focus:ring-2 focus:ring-gray-300 dark:border-gray-600 dark:bg-gray-950 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-500">
<fa-icon [icon]="editModeStore.isEnabled() ? faCheck : faPenToSquare" size="xl"></fa-icon>
</button>
18 changes: 18 additions & 0 deletions src/app/components/edit-mode/edit-mode.component.ts
Original file line number Diff line number Diff line change
@@ -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;
}
3 changes: 2 additions & 1 deletion src/app/components/header/header.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
</div>
</div>
<div class="flex items-center">
<pap-dark-light-mode />
<pap-edit-mode />
<pap-dark-light-mode class="ml-2" />
</div>
</div>
</nav>
3 changes: 2 additions & 1 deletion src/app/components/header/header.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion src/app/components/headings/h1/h1.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<h1 class="mb-4 text-2xl font-extrabold leading-none tracking-tight text-gray-900 dark:text-white md:text-3xl lg:text-4xl">
<h1 class="mb-4 text-2xl font-extrabold leading-none tracking-tight md:text-3xl lg:text-4xl">
<ng-content></ng-content>
</h1>
Empty file.
3 changes: 3 additions & 0 deletions src/app/components/headings/h2/h2.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h2 class="mb-4 text-xl font-bold">
<ng-content></ng-content>
</h2>
11 changes: 11 additions & 0 deletions src/app/components/headings/h2/h2.component.ts
Original file line number Diff line number Diff line change
@@ -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 {}
8 changes: 6 additions & 2 deletions src/app/services/tables/character.table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ export class CharacterTable implements DatabaseTable<CharacterEntity> {
return this.entities.toArray();
}

item(id: number): Promise<CharacterEntity | undefined> {
return this.entities.get(id);
async update(character: CharacterEntity) {
await this.entities.update(character.id, character);
}

async add(name: string): Promise<CharacterEntity> {
Expand All @@ -37,4 +37,8 @@ export class CharacterTable implements DatabaseTable<CharacterEntity> {
const character = await this.item(id);
return character!;
}

private item(id: number): Promise<CharacterEntity | undefined> {
return this.entities.get(id);
}
}
12 changes: 11 additions & 1 deletion src/app/stores/character.store.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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 }) => ({
Expand Down
24 changes: 24 additions & 0 deletions src/app/stores/edit-mode.store.ts
Original file line number Diff line number Diff line change
@@ -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<EditModeState>({ mode: 'read' }),
withMethods(store => {
return {
enableEditMode: () => {
patchState(store, { mode: 'write' });
},
disableEditMode: () => {
patchState(store, { mode: 'read' });
},
};
}),
withComputed(store => ({
isEnabled: computed(() => store.mode() === 'write'),
})),
);

0 comments on commit 28c70fc

Please sign in to comment.