Ver código fonte

Ability table almost complete

Christopher Giese 1 ano atrás
pai
commit
e3984d206c
21 arquivos alterados com 690 adições e 4 exclusões
  1. 37 0
      .nx/cache/d/daemon.log
  2. 1 1
      .nx/cache/d/server-process.json
  3. 37 0
      src/app/journal/journal-stats/ability-panel/ability-panel.component.html
  4. 5 0
      src/app/journal/journal-stats/ability-panel/ability-panel.component.scss
  5. 21 0
      src/app/journal/journal-stats/ability-panel/ability-panel.component.spec.ts
  6. 10 0
      src/app/journal/journal-stats/ability-panel/ability-panel.component.ts
  7. 81 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.html
  8. 5 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.scss
  9. 21 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.spec.ts
  10. 105 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.ts
  11. 43 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.html
  12. 71 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.scss
  13. 21 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.spec.ts
  14. 148 0
      src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.ts
  15. 3 3
      src/app/journal/journal-stats/journal-stats.component.html
  16. 3 0
      src/app/journal/journal-stats/life-container/life-container.component.html
  17. 6 0
      src/app/journal/journal.module.ts
  18. 8 0
      src/interfaces/ability.ts
  19. 5 0
      src/interfaces/heal.ts
  20. 56 0
      src/services/data/data.service.ts
  21. 3 0
      src/styles.scss

+ 37 - 0
.nx/cache/d/daemon.log

@@ -458885,3 +458885,40 @@ To fix this, set a unique name for each project in a project.json inside the pro
 [NX Daemon Server] - 2023-11-05T18:49:04.365Z - Time taken for 'hash changed files from watcher' 42.78379988670349ms
 [NX Daemon Server] - 2023-11-05T18:49:04.366Z - [WATCHER]: Processing file changes in outputs
 [NX Daemon Server] - 2023-11-05T18:49:04.366Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-06T16:28:26.288Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\b99a3e5445b3962b8dd8\d.sock
+[NX Daemon Server] - 2023-11-06T16:28:26.295Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools (native)
+[NX Daemon Server] - 2023-11-06T16:28:26.296Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-06T16:28:26.297Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2023-11-06T16:28:26.298Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-06T16:28:26.300Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-06T16:28:26.930Z - Error detected when recomputing project file map: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+[NX Daemon Server] - 2023-11-06T16:28:26.930Z - [REQUEST]: Responding to the client with an error. Error when preparing serialized project graph. The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+Error: The following projects are defined in multiple locations:
+- DnDTools: 
+  - 
+  - .
+
+To fix this, set a unique name for each project in a project.json inside the project's root. If the project does not currently have a project.json, you can create one that contains only a name.
+    at readProjectConfigurationsFromRootMap (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:58:12)
+    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
+    at async processCollectedUpdatedAndDeletedFiles (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Users\chris\Softwareprojekte\CharacterJournal\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2023-11-06T16:28:26.932Z - Time taken for 'hash changed files from watcher' 129.30799984931946ms
+[NX Daemon Server] - 2023-11-06T16:28:26.932Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-06T16:28:26.932Z - Done responding to the client null

+ 1 - 1
.nx/cache/d/server-process.json

@@ -1 +1 @@
-{"processId":20216}
+{"processId":19856}

+ 37 - 0
src/app/journal/journal-stats/ability-panel/ability-panel.component.html

@@ -0,0 +1,37 @@
+<div class="ability-panel-container">
+  <ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs">
+    <li [ngbNavItem]="1">
+      <button ngbNavLink>Fähigkeiten</button>
+      <ng-template ngbNavContent>
+        <ability-table></ability-table>
+      </ng-template>
+    </li>
+    <li [ngbNavItem]="2">
+      <button ngbNavLink>Eigenschaften</button>
+      <ng-template ngbNavContent>
+        <p>Fey Ancestry Great Weapon Mastery Darkvision R</p>
+      </ng-template>
+    </li>
+    <li [ngbNavItem]="3">
+      <button ngbNavLink>Zauberplätze</button>
+      <ng-template ngbNavContent>
+        <p>
+          Level 1 O O O <br />Level 2 O O <br />
+          Level 3 O
+        </p>
+      </ng-template>
+    </li>
+    <li [ngbNavItem]="4">
+      <button ngbNavLink>Proficiencies and Languages</button>
+      <ng-template ngbNavContent>
+        <p>Sprachen</p>
+        <p>Tools</p>
+        <p>Rüstung und Waffen</p>
+      </ng-template>
+    </li>
+  </ul>
+
+  <div [ngbNavOutlet]="nav" class="mt-2"></div>
+
+  <pre>Active: {{ active }}</pre>
+</div>

+ 5 - 0
src/app/journal/journal-stats/ability-panel/ability-panel.component.scss

@@ -0,0 +1,5 @@
+.ability-panel-container{
+    border: 1px solid #525252;
+    border-radius: 5px;
+    height: 60vh;
+}

+ 21 - 0
src/app/journal/journal-stats/ability-panel/ability-panel.component.spec.ts

@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AbilityPanelComponent } from './ability-panel.component';
+
+describe('AbilityPanelComponent', () => {
+  let component: AbilityPanelComponent;
+  let fixture: ComponentFixture<AbilityPanelComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [AbilityPanelComponent]
+    });
+    fixture = TestBed.createComponent(AbilityPanelComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 10 - 0
src/app/journal/journal-stats/ability-panel/ability-panel.component.ts

@@ -0,0 +1,10 @@
+import { Component } from '@angular/core';
+
+@Component({
+  selector: 'ability-panel',
+  templateUrl: './ability-panel.component.html',
+  styleUrls: ['./ability-panel.component.scss'],
+})
+export class AbilityPanelComponent {
+  active = 1;
+}

+ 81 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.html

@@ -0,0 +1,81 @@
+<ngx-smart-modal
+  #abilityModal
+  identifier="abilityModal"
+  (onOpenFinished)="checkIfUpdate()"
+>
+  <div class="modal-title">
+    <h3 *ngIf="!isToUpdate">Fähigkeit erstellen</h3>
+    <h3 *ngIf="isToUpdate">Fähigkeit anpassen</h3>
+  </div>
+  <div class="modal-body">
+    <div class="modal-input">
+      <label for="abilityName">Name</label>
+      <input
+        type="text"
+        class="modal-input"
+        id="abilityName"
+        [(ngModel)]="newAbilityName"
+      />
+    </div>
+
+    <div class="modal-input">
+      <label for="abilityShortDescription">Kurzbeschreibung</label>
+      <textarea
+        id="abilityShortDescription"
+        [(ngModel)]="newAbilityShortDescription"
+      ></textarea>
+    </div>
+
+    <div class="modal-input">
+      <label for="abilityLongDescription">Ausführliche Beschreibung</label>
+      <textarea
+        id="abilityLongDescription"
+        [(ngModel)]="newAbilityLongDescription"
+      ></textarea>
+    </div>
+
+    <div class="modal-input">
+      <label>Kosten</label>
+      <select [(ngModel)]="newAbilityCost">
+        <option *ngFor="let cost of costs" [value]="cost.value">
+          {{ cost.display }}
+        </option>
+      </select>
+    </div>
+
+    <div class="modal-input">
+      <label>Verwendungen</label>
+      <select [(ngModel)]="newAbilityCharges">
+        <option *ngFor="let charge of charges" [value]="charge.value">
+          {{ charge.display }}
+        </option>
+      </select>
+    </div>
+  </div>
+  <button
+    *ngIf="!isToUpdate"
+    class="modal-button"
+    (click)="createAbility()"
+    [disabled]="
+      !newAbilityName ||
+      !newAbilityShortDescription ||
+      !newAbilityLongDescription
+    "
+  >
+    Fähigkeit hinzufügen
+  </button>
+  <button
+    *ngIf="isToUpdate"
+    (click)="updateAbility()"
+    [disabled]="
+      !newAbilityName ||
+      !newAbilityShortDescription ||
+      !newAbilityLongDescription
+    "
+  >
+    Fähigkeit aktualisieren
+  </button>
+</ngx-smart-modal>
+
+<!-- (onAnyCloseEventFinished)="removeData()"
+  (onOpenFinished)="checkIfUpdate()" -->

+ 5 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.scss

@@ -0,0 +1,5 @@
+.modal-input{
+    display: flex;
+    flex-direction: column;
+    gap: 0.5rem;
+}

+ 21 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.spec.ts

@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AbilityModalComponent } from './ability-modal.component';
+
+describe('AbilityModalComponent', () => {
+  let component: AbilityModalComponent;
+  let fixture: ComponentFixture<AbilityModalComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [AbilityModalComponent]
+    });
+    fixture = TestBed.createComponent(AbilityModalComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 105 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component.ts

@@ -0,0 +1,105 @@
+import { Component, Output, EventEmitter, Input } from '@angular/core';
+import { NgxSmartModalService } from 'ngx-smart-modal';
+import { Ability } from 'src/interfaces/ability';
+import { Damage } from 'src/interfaces/damage';
+import { Heal } from 'src/interfaces/heal';
+
+@Component({
+  selector: 'ability-modal',
+  templateUrl: './ability-modal.component.html',
+  styleUrls: ['./ability-modal.component.scss'],
+})
+export class AbilityModalComponent {
+  public constructor(public ngxSmartModalService: NgxSmartModalService) {}
+
+  @Output() public abilityCreated: EventEmitter<Ability> =
+    new EventEmitter<Ability>();
+
+  @Output() public abilityUpdated: EventEmitter<any> = new EventEmitter<any>();
+
+  @Output() public abilityDelete: EventEmitter<number> =
+    new EventEmitter<number>();
+
+  @Input() public isToUpdate: boolean = false;
+  @Input() public abilityToUpdate: Ability | undefined;
+
+  public newAbilityName: string = '';
+  public newAbilityCharges: number = 0;
+  public newAbilityCurrentlyUsedCharges: number = 0;
+  public newAbilityCost: string = 'none';
+  public newAbilityShortDescription: string = '';
+  public newAbilityLongDescription: string = '';
+
+  public costs: any[] = [
+    { display: 'keine', value: 'none' },
+    { display: 'Aktion', value: 'action' },
+    { display: 'Bonusaktion', value: 'bonus' },
+    { display: 'Reaktion', value: 'reaction' },
+  ];
+
+  public charges: any[] = [
+    { display: 'unbegrenzt', value: 0 },
+    { display: '1', value: 1 },
+    { display: '2', value: 2 },
+    { display: '3', value: 3 },
+    { display: '4', value: 4 },
+    { display: '5', value: 5 },
+    { display: '6', value: 6 },
+    { display: '7', value: 7 },
+    { display: '8', value: 8 },
+    { display: '9', value: 9 },
+    { display: '10', value: 10 },
+  ];
+
+  public createAbility(): void {
+    const newAbility: Ability = {
+      name: this.newAbilityName,
+      shortDescription: this.newAbilityShortDescription,
+      longDescription: this.newAbilityLongDescription,
+      cost: this.newAbilityCost,
+      charges: this.newAbilityCharges,
+      currentlyUsedCharges: 0,
+    };
+    this.abilityCreated.emit(newAbility);
+    this.ngxSmartModalService.closeLatestModal();
+    this.resetModalData();
+  }
+
+  public checkIfUpdate(): void {
+    if (this.isToUpdate) {
+      this.newAbilityName = this.abilityToUpdate?.name || '';
+      this.newAbilityCharges = this.abilityToUpdate?.charges || 0;
+      this.newAbilityCurrentlyUsedCharges =
+        this.abilityToUpdate?.currentlyUsedCharges || 0;
+      this.newAbilityCost = this.abilityToUpdate?.cost || 'none';
+      this.newAbilityShortDescription =
+        this.abilityToUpdate?.shortDescription || '';
+      this.newAbilityLongDescription =
+        this.abilityToUpdate?.longDescription || '';
+    }
+  }
+
+  public updateAbility(): void {
+    const updatedAbility: Ability = {
+      name: this.newAbilityName,
+      shortDescription: this.newAbilityShortDescription,
+      longDescription: this.newAbilityLongDescription,
+      cost: this.newAbilityCost,
+      charges: this.newAbilityCharges,
+      currentlyUsedCharges: this.newAbilityCurrentlyUsedCharges,
+    };
+    this.abilityUpdated.emit(updatedAbility);
+    this.ngxSmartModalService.closeLatestModal();
+    this.resetModalData();
+  }
+
+  private resetModalData(): void {
+    this.newAbilityName = '';
+    this.newAbilityShortDescription = '';
+    this.newAbilityLongDescription = '';
+    this.newAbilityCost = 'none';
+    this.newAbilityCharges = 0;
+    this.isToUpdate = false;
+    this.abilityToUpdate = undefined;
+  }
+}

+ 43 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.html

@@ -0,0 +1,43 @@
+<div cdkDropList class="example-list" (cdkDropListDropped)="drop($event)">
+  <div
+    class="example-box"
+    [class]="ability.currentlyUsedCharges === ability.charges ? 'used' : ''"
+    *ngFor="let ability of abilities; let abilityIndex = index"
+    (click)="openAbilityModal(abilityIndex)"
+    cdkDrag
+  >
+    <div *ngIf="ability.cost != 'none'" class="cost-box">
+      {{ costTranslator[ability.cost] }}
+    </div>
+    <div class="ability-name">{{ ability.name }}</div>
+    <br />
+
+    <p>{{ ability.shortDescription }}</p>
+
+    <div class="charges-box" *ngIf="ability.charges != 0">
+      <span>Aufladungen: </span>
+      <span
+        *ngFor="let _ of getArray(ability.charges); let chargeIndex = index"
+      >
+        <input
+          [id]="'checkbox' + abilityIndex + '-' + chargeIndex"
+          type="checkbox"
+          (click)="$event.stopPropagation()"
+          (change)="
+            $event.stopPropagation();
+            handleChangedCharges(abilityIndex, $event.target)
+          "
+        />
+      </span>
+    </div>
+  </div>
+
+  <button (click)="openAbilityModal()">+</button>
+</div>
+
+<ability-modal
+  (abilityCreated)="addNewlyCreatedAbility($event)"
+  (abilityUpdated)="updateAbility($event)"
+  [isToUpdate]="isToUpdate"
+  [abilityToUpdate]="abilityToUpdate"
+></ability-modal>

+ 71 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.scss

@@ -0,0 +1,71 @@
+.ability-name{
+  font-size: 1.25rem;
+  font-weight: 600;
+}
+
+.cost-info{
+  position: absolute;
+  left: 0;
+  top: 0;
+}
+
+
+
+
+
+
+
+
+// Table
+.used{
+  opacity: 0.5;
+}
+
+.example-list {
+  width: 100%;
+  border: solid 1px #ccc;
+  min-height: 60px;
+  display: block;
+  background: white;
+  border-radius: 4px;
+  overflow: hidden;
+}
+
+.example-box {
+  padding: 20px 10px;
+  border-bottom: solid 1px #ccc;
+  color: rgba(0, 0, 0, 0.87);
+  display: flex;
+  position: relative;
+  flex-direction: column;
+  // align-items: center;
+  justify-content: space-between;
+  box-sizing: border-box;
+  cursor: move;
+  background: white;
+  font-size: 14px;
+}
+
+.cdk-drag-preview {
+  box-sizing: border-box;
+  border-radius: 4px;
+  box-shadow: 0 5px 5px -3px rgba(0, 0, 0, 0.2),
+              0 8px 10px 1px rgba(0, 0, 0, 0.14),
+              0 3px 14px 2px rgba(0, 0, 0, 0.12);
+}
+
+.cdk-drag-placeholder {
+  opacity: 0;
+}
+
+.cdk-drag-animating {
+  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
+}
+
+.example-box:last-child {
+  border: none;
+}
+
+.example-list.cdk-drop-list-dragging .example-box:not(.cdk-drag-placeholder) {
+  transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
+}

+ 21 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.spec.ts

@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AbilityTableComponent } from './ability-table.component';
+
+describe('AbilityTableComponent', () => {
+  let component: AbilityTableComponent;
+  let fixture: ComponentFixture<AbilityTableComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [AbilityTableComponent]
+    });
+    fixture = TestBed.createComponent(AbilityTableComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});

+ 148 - 0
src/app/journal/journal-stats/ability-panel/ability-table/ability-table.component.ts

@@ -0,0 +1,148 @@
+import { Component, signal } from '@angular/core';
+import {
+  CdkDragDrop,
+  CdkDropList,
+  CdkDrag,
+  moveItemInArray,
+} from '@angular/cdk/drag-drop';
+import { DataService } from 'src/services/data/data.service';
+import { Ability } from 'src/interfaces/ability';
+import { NgxSmartModalService } from 'ngx-smart-modal';
+
+@Component({
+  selector: 'ability-table',
+  templateUrl: './ability-table.component.html',
+  styleUrls: ['./ability-table.component.scss'],
+})
+export class AbilityTableComponent {
+  public abilities!: Ability[];
+
+  public costTranslator: any = {
+    action: 'Aktion',
+    bonus: 'Bonusaktion',
+    reaction: 'Reaktion',
+  };
+
+  public isToUpdate: boolean = false;
+  public abilityToUpdate: Ability | undefined;
+  public updateAbilityIndex: number | undefined;
+
+  ///////////
+
+  public constructor(
+    public dataAccessor: DataService,
+    public ngxSmartModalService: NgxSmartModalService
+  ) {}
+
+  public ngOnInit(): void {
+    this.abilities = this.dataAccessor.getAbilities();
+    console.log(this.abilities);
+  }
+
+  public ngAfterViewInit(): void {
+    this.abilities.forEach((ability, abilityIndex) => {
+      this.correctChargesView(abilityIndex);
+    });
+  }
+
+  ///////////
+
+  public getArray(length: number): any[] {
+    return Array.from({ length: length });
+  }
+
+  public drop(event: CdkDragDrop<string[]>): void {
+    moveItemInArray(this.abilities, event.previousIndex, event.currentIndex);
+    this.updateDatabase();
+  }
+
+  public openAbilityModal(abilityIndex?: number): void {
+    if (abilityIndex !== undefined) {
+      this.isToUpdate = true;
+      this.abilityToUpdate = this.abilities[abilityIndex];
+      this.updateAbilityIndex = abilityIndex;
+    }
+    this.ngxSmartModalService.getModal('abilityModal').open();
+  }
+
+  public handleChangedCharges(abilityindex: number, CheckBoxRef: any): void {
+    const newValue = CheckBoxRef.checked;
+    // checked now, so a charge was used -> decrease
+    if (newValue) {
+      this.abilities[abilityindex].currentlyUsedCharges++;
+      // else increase
+    } else {
+      this.abilities[abilityindex].currentlyUsedCharges--;
+    }
+    this.correctChargesView(abilityindex);
+    this.updateDatabase();
+  }
+
+  public correctChargesView(abilityIndex: number): void {
+    console.log('correcting charges view');
+    console.log(this.abilities);
+    console.log(abilityIndex);
+
+    const charges = this.abilities[abilityIndex].charges;
+    const currentlyUsedCharges =
+      this.abilities[abilityIndex].currentlyUsedCharges;
+
+    console.log('charges: ', charges);
+    console.log('currentlyUsedCharges: ', currentlyUsedCharges);
+
+    for (
+      let chargeIndex = 0;
+      chargeIndex < currentlyUsedCharges;
+      chargeIndex++
+    ) {
+      console.log(
+        'setting checkbox ' + abilityIndex + '-' + chargeIndex + ' to true'
+      );
+      (
+        document.getElementById(
+          'checkbox' + abilityIndex + '-' + chargeIndex
+        ) as HTMLInputElement
+      ).checked = true;
+    }
+    for (
+      let chargeIndex = currentlyUsedCharges;
+      chargeIndex < charges;
+      chargeIndex++
+    ) {
+      console.log(
+        'setting checkbox ' + abilityIndex + '-' + chargeIndex + ' to false'
+      );
+      (
+        document.getElementById(
+          'checkbox' + abilityIndex + '-' + chargeIndex
+        ) as HTMLInputElement
+      ).checked = false;
+    }
+  }
+
+  public updateDatabase(): void {
+    this.dataAccessor.setSAbilities(this.abilities);
+  }
+
+  // add
+  public addNewlyCreatedAbility(ability: Ability): void {
+    this.abilities.push(ability);
+    this.updateDatabase();
+  }
+
+  //  update
+  public updateAbility(ability: Ability): void {
+    console.log(ability);
+    console.log(this.updateAbilityIndex);
+    this.abilities[this.updateAbilityIndex!] = ability;
+    this.updateDatabase();
+    this.correctChargesView(this.updateAbilityIndex!);
+    this.resetUpdateData();
+  }
+
+  private resetUpdateData(): void {
+    this.isToUpdate = false;
+    this.abilityToUpdate = undefined;
+    this.updateAbilityIndex = undefined;
+  }
+}

+ 3 - 3
src/app/journal/journal-stats/journal-stats.component.html

@@ -2,7 +2,7 @@
   <div class="name-container">Eliane Langwasser</div>
 
   <div class="stats-container">
-    <div class="attribute-skill-container">
+    <div class="attribute-skill-container" style="width: 20vw">
       <ng-container *ngFor="let attribute of attributes">
         <app-attribute-skill-container
           [attributeObject]="attribute"
@@ -10,10 +10,10 @@
       </ng-container>
     </div>
 
-    <div class="life-weapon-container">
+    <div class="life-weapon-container" style="width: 35vw">
       <app-life-container></app-life-container>
       <app-weapons-container></app-weapons-container>
     </div>
-    <div class="platzhalter">platzhalter</div>
+    <ability-panel style="width: 35vw"></ability-panel>
   </div>
 </div>

+ 3 - 0
src/app/journal/journal-stats/life-container/life-container.component.html

@@ -7,5 +7,8 @@
   <app-death-save></app-death-save>
 
   <div class="cont30">Inspiration</div>
+  <div>stati</div>
+
+  <!-- Trefferpunkte -->
   <app-life style="width: 100%"></app-life>
 </div>

+ 6 - 0
src/app/journal/journal.module.ts

@@ -34,6 +34,9 @@ import { WeaponTableComponent } from './journal-stats/weapons-container/weapon-t
 import { WeaponModalComponent } from './weapon-modal/weapon-modal.component';
 import { SpellTableComponent } from './journal-stats/weapons-container/spell-table/spell-table.component';
 import { SpellModalComponent } from './spell-modal/spell-modal.component';
+import { AbilityPanelComponent } from './journal-stats/ability-panel/ability-panel.component';
+import { AbilityTableComponent } from './journal-stats/ability-panel/ability-table/ability-table.component';
+import { AbilityModalComponent } from './journal-stats/ability-panel/ability-table/ability-modal/ability-modal.component';
 
 @NgModule({
   declarations: [
@@ -64,6 +67,9 @@ import { SpellModalComponent } from './spell-modal/spell-modal.component';
     WeaponModalComponent,
     SpellTableComponent,
     SpellModalComponent,
+    AbilityPanelComponent,
+    AbilityTableComponent,
+    AbilityModalComponent,
   ],
   imports: [
     CommonModule,

+ 8 - 0
src/interfaces/ability.ts

@@ -0,0 +1,8 @@
+export interface Ability {
+  name: string;
+  shortDescription: string;
+  longDescription?: string;
+  cost: string;
+  charges: number;
+  currentlyUsedCharges: number;
+}

+ 5 - 0
src/interfaces/heal.ts

@@ -0,0 +1,5 @@
+export interface Heal {
+  diceNumber: string;
+  diceType: string;
+  additionalHeal?: string;
+}

+ 56 - 0
src/services/data/data.service.ts

@@ -7,6 +7,7 @@ import { Attribute } from 'src/interfaces/attribute';
 import { Skill } from 'src/interfaces/skill';
 import { Weapon } from 'src/interfaces/weapon';
 import { Spell } from 'src/interfaces/spell';
+import { Ability } from 'src/interfaces/ability';
 
 @Injectable({
   providedIn: 'root',
@@ -257,6 +258,47 @@ export class DataService {
     console.log('spells updated from data service: ', this.spells);
   }
 
+  private abilities: Ability[] = [
+    {
+      name: 'Feenschritt',
+      charges: 8,
+      currentlyUsedCharges: 4,
+      cost: 'bonus',
+      shortDescription:
+        'Als Bonusaktion kannst du dich bis zu 30 Fuß zu einem Punkt teleportieren, den du sehen kannst.',
+      longDescription:
+        'Als Bonusaktion kannst du dich auf magische Weise bis zu 30 Fuß weit in einen unbesetzten Raum teleportieren, den du sehen kannst. Du kannst diese Eigenschaft so oft einsetzen, wie es deinem Fertigkeitsbonus entspricht, und du erhältst alle verbrauchten Einsätze zurück, wenn du eine lange Pause machst.',
+    },
+    {
+      name: 'Durchschnaufen',
+      charges: 1,
+      currentlyUsedCharges: 0,
+      cost: 'bonus',
+      shortDescription:
+        'Als Bonusaktion kannst du dich um 1 d10 + Fighter Level Trefferpunkten heilen.',
+      longDescription:
+        'Als Bonusaktion kannst du dich um 1 d10 + Fighter Level Trefferpunkten heilen. Du kannst diese Fähigkeit einmal pro langer Rast einsetzen.',
+    },
+    {
+      name: 'Tatendrang',
+      charges: 1,
+      currentlyUsedCharges: 1,
+      cost: 'none',
+      shortDescription: 'Du kannst eine weitere Aktion ausführen.',
+      longDescription:
+        'Du kannst eine weitere Aktion ausführen. Du kannst diese Fähigkeit einmal pro langer Rast einsetzen.',
+    },
+  ];
+
+  public getAbilities(): Ability[] {
+    return this.abilities;
+  }
+
+  public setSAbilities(abilities: Ability[]): void {
+    this.abilities = abilities;
+    console.log('abilities updated from data service: ', this.abilities);
+  }
+
   // #region Character Data observables
 
   /**
@@ -358,6 +400,20 @@ export class DataService {
   });
   public spells$ = this.experienceSubject.asObservable();
 
+  private abilitiesSubject = new BehaviorSubject<object>({
+    name: 'abilities',
+    value: [
+      {
+        name: '',
+        doesDamage: false,
+        doesHeal: false,
+        damageType: '',
+        description: '',
+      },
+    ],
+  });
+  public abilities$ = this.experienceSubject.asObservable();
+
   // #region Attribute observables
 
   /**

+ 3 - 0
src/styles.scss

@@ -112,3 +112,6 @@ $dialog-position-right: 20%;
 .gap-20{
     gap: 2rem;
 }
+
+// Drag and Drop Table
+