Browse Source

moved deathsaves to life component

Warafear 1 year ago
parent
commit
42214aeaf8
26 changed files with 325 additions and 685 deletions
  1. 6 2
      src/app/journal/journal-home/navigation-panel/navigation-panel.component.scss
  2. 1 90
      src/app/journal/journal-spellbook/journal-spellbook.component.html
  3. 1 248
      src/app/journal/journal-spellbook/journal-spellbook.component.scss
  4. 0 6
      src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.html
  5. 0 0
      src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.scss
  6. 0 22
      src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.spec.ts
  7. 0 8
      src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.ts
  8. 0 45
      src/app/journal/journal-stats/info-row/death-save/death-save.component.html
  9. 1 1
      src/app/journal/journal-stats/info-row/info-row.component.html
  10. 5 1
      src/app/journal/journal-stats/info-row/info-row.component.scss
  11. 9 5
      src/app/journal/journal-stats/journal-stats.component.scss
  12. 47 0
      src/app/journal/journal-stats/life-container/death-save/death-save.component.html
  13. 3 3
      src/app/journal/journal-stats/life-container/death-save/death-save.component.scss
  14. 0 0
      src/app/journal/journal-stats/life-container/death-save/death-save.component.spec.ts
  15. 1 10
      src/app/journal/journal-stats/life-container/death-save/death-save.component.ts
  16. 10 21
      src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.html
  17. 1 8
      src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.scss
  18. 15 9
      src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.ts
  19. 28 18
      src/app/journal/journal-stats/life-container/life/life-details/life-details.component.html
  20. 38 26
      src/app/journal/journal-stats/life-container/life/life-details/life-details.component.scss
  21. 18 25
      src/app/journal/journal-stats/life-container/life/life-details/life-details.component.ts
  22. 17 36
      src/app/journal/journal-stats/life-container/life/life.component.ts
  23. 1 3
      src/app/journal/journal.module.ts
  24. 7 9
      src/assets/i18n/de.json
  25. 112 85
      src/services/data/data.service.ts
  26. 4 4
      src/styles.scss

+ 6 - 2
src/app/journal/journal-home/navigation-panel/navigation-panel.component.scss

@@ -1,3 +1,5 @@
+@import "../../../../responsive";
+
 .backdrop {
   position: fixed;
   top: 0;
@@ -41,8 +43,10 @@ ul {
   font-size: 1.25rem;
   font-weight: 500;
   margin-bottom: 1rem;
-  padding-left: 2rem;
-  padding: 0.5rem 0 0.5rem 2rem;
+  padding: 0.25rem 0 0.25rem 2rem;
+  @include height-small {
+    padding: 0.5rem 0 0.5rem 2rem;
+  }
 
   border: solid 1px var(--border-color);
   background-color: var(--field-background-color);

+ 1 - 90
src/app/journal/journal-spellbook/journal-spellbook.component.html

@@ -1,4 +1,4 @@
-<!-- <div
+<div
   style="
     display: flex;
     justify-content: center;
@@ -12,93 +12,4 @@
     src="assets/images/spellbook_coming_soon.jpeg"
     alt=""
   />
-</div> -->
-
-<!-- <div class="complete">
-  <div class="left">
-    <div class="attributes">
-      <div class="box"></div>
-      <div class="box"></div>
-      <div class="box"></div>
-      <div class="box"></div>
-      <div class="box"></div>
-      <div class="box"></div>
-    </div>
-
-    <div class="skills">
-      <div class="save-container">
-        <div class="save"></div>
-        <div class="save"></div>
-        <div class="save"></div>
-        <div class="save"></div>
-        <div class="save"></div>
-        <div class="save"></div>
-      </div>
-
-      <div class="skill-container">
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-        <div class="skill"></div>
-      </div>
-    </div>
-  </div>
-
-  <div class="rest">
-    <div class="info-row">
-      <div class="small"></div>
-      <div class="small"></div>
-      <div class="small"></div>
-      <div class="small"></div>
-      <div class="medium"></div>
-      <div class="large"></div>
-    </div>
-
-    <div class="bottoms">
-      <div class="middle">
-        <div class="life"></div>
-        <div class="weapons"></div>
-      </div>
-
-      <div class="right"></div>
-    </div>
-  </div>
 </div>
--->
-
-<!-- <div class="h840"></div>
-<div class="h864"></div>
-
-<div class="h910"></div>
-<div class="h934"></div>
-
-<div class="h977"></div>
-<div class="h1001"></div>
-
-<div class="h1056"></div>
-<div class="h1080"></div>
-
-<div class="w1470"></div>
-<div class="w1494"></div>
-
-<div class="w1683"></div>
-<div class="w1707"></div>
-
-<div class="w1896"></div>
-<div class="w1920"></div> -->
-
-<div class="boxx"></div>

+ 1 - 248
src/app/journal/journal-spellbook/journal-spellbook.component.scss

@@ -1,249 +1,2 @@
-::ng-deep .journal-container {
-  scrollbar-width: none;
-}
+//
 @import url("src/responsive.scss");
-
-.complete {
-  display: flex;
-  gap: 1rem;
-  width: 1446px;
-  height: 886px;
-  border: 1px solid red;
-  margin: 1.5rem 1.5rem;
-}
-
-// LEFT
-
-.left {
-  display: flex;
-  gap: 1rem;
-}
-
-.attributes {
-  display: flex;
-  flex-direction: column;
-  gap: 2rem;
-}
-
-.box {
-  width: 8rem;
-  height: 7rem;
-  border: 1px solid black;
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-}
-
-.save-container,
-.skill-container {
-  display: flex;
-  flex-direction: column;
-  gap: 0.2rem;
-  border: va(--border);
-  padding: 0.5rem;
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-}
-
-.skill-container {
-  margin-top: 1rem;
-}
-
-.save,
-.skill {
-  width: 15rem;
-  height: 2rem;
-  border: var(--border);
-}
-
-// RIGHT
-
-.rest {
-  display: flex;
-  flex-direction: column;
-  gap: 1rem;
-  width: 1030px;
-}
-
-.bottoms {
-  display: flex;
-  gap: 1rem;
-}
-
-// INFO ROW
-
-.info-row {
-  width: 100%;
-  display: flex;
-  justify-content: space-between;
-  height: 6rem;
-
-  .small {
-    width: 7rem;
-    height: 6rem;
-    border: var(--border);
-    border-radius: 10px;
-    background-color: var(--field-background-color);
-  }
-
-  .large {
-    width: 17rem;
-    height: 6rem;
-    border: var(--border);
-    background-color: var(--field-background-color);
-    border-radius: 10px;
-  }
-
-  .medium {
-    width: 12rem;
-    height: 6rem;
-    border: var(--border);
-    background-color: var(--field-background-color);
-    border-radius: 10px;
-  }
-}
-
-//  MIDDLE
-
-.middle {
-  display: flex;
-  flex-direction: column;
-  gap: 1rem;
-  width: 33rem;
-}
-.life {
-  width: 33rem;
-  height: 11rem;
-  border: var(--border);
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-}
-
-.weapons {
-  width: 33rem;
-  height: 36.25rem;
-  border: var(--border);
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-}
-
-// RIGHT
-
-.right {
-  width: 33.25rem;
-  height: 48.25rem;
-  border: var(--border);
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-}
-
-//////////////////// WIDTH /////////////////////////////
-
-@media (width > 1919px) {
-  .complete {
-    width: 1872px;
-  }
-}
-
-// Bei relevanz noch einen Eintrag zwischen m und l
-@media (width < 1490px) {
-  .complete {
-    width: 1232px;
-  }
-}
-
-///////// HEIGHT ////////////
-
-.boxx {
-  margin-left: 1.5rem;
-  margin-top: 1.5rem;
-  height: 100px;
-  width: 100px;
-  background-color: var(--field-background-color);
-  border-radius: 10px;
-  //   margin: auto;
-  margin: 1.5rem;
-}
-
-// @mixin height-large {
-//   @media (height >= 1080px) {
-//     @content;
-//   }
-// }
-
-// @mixin height-medium {
-//   @media (height >= 1001px) {
-//     @content;
-//   }
-// }
-
-// @mixin height-small {
-//   @media (height >= 934px) {
-//     @content;
-//   }
-// }
-
-// @mixin height-xsmall {
-//   @media (height < 934px) {
-//     @content;
-//   }
-// }
-
-// .boxx {
-//   @include height-xsmall {
-//     height: 816px;
-//   }
-//   @include height-small {
-//     height: 886px;
-//   }
-//   @include height-medium {
-//     height: 953px;
-//   }
-//   @include height-large {
-//     height: 1032px;
-//   }
-// }
-///////// WIDTH ////////////
-
-$wxl: 1920px;
-$wl: 1705px;
-$wm: 1494px;
-$ws: 1445px; // wird nur als kleiner genutzt
-
-// @mixin width-large {
-//   @media (width >= 1920px) {
-//     @content;
-//   }
-// }
-
-// @mixin width-medium {
-//   @media (width >= 1707px) {
-//     @content;
-//   }
-// }
-
-// @mixin width-small {
-//   @media (width >= 1494px) {
-//     @content;
-//   }
-// }
-
-// @mixin width-xsmall {
-//   @media (width < 1445px) {
-//     @content;
-//   }
-// }
-
-// .boxx {
-//   @include width-xsmall {
-//     width: 1232px;
-//   }
-//   @include width-small {
-//     width: 1446px;
-//   }
-//   @include width-medium {
-//     width: 1659px;
-//   }
-//   @include width-large {
-//     width: 1872px;
-//   }
-// }

+ 0 - 6
src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.html

@@ -1,6 +0,0 @@
-<div class="title">{{ "deathSave.label" | translate }}</div>
-
-<div class="content">{{ "deathSave.description" | translate }}</div>
-
-<div class="subheading left">{{ "deathSave.criticalHeader" | translate }}</div>
-<div class="content t-05">{{ "deathSave.criticalContent" | translate }}</div>

+ 0 - 0
src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.scss


+ 0 - 22
src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.spec.ts

@@ -1,22 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { DeathSaveDetailsComponent } from './death-save-details.component';
-
-describe('DeathSaveDetailsComponent', () => {
-  let component: DeathSaveDetailsComponent;
-  let fixture: ComponentFixture<DeathSaveDetailsComponent>;
-
-  beforeEach(async () => {
-    await TestBed.configureTestingModule({
-      declarations: [DeathSaveDetailsComponent],
-    }).compileComponents();
-
-    fixture = TestBed.createComponent(DeathSaveDetailsComponent);
-    component = fixture.componentInstance;
-    fixture.detectChanges();
-  });
-
-  it('should create', () => {
-    expect(component).toBeTruthy();
-  });
-});

+ 0 - 8
src/app/journal/journal-stats/info-row/death-save/death-save-details/death-save-details.component.ts

@@ -1,8 +0,0 @@
-import { Component } from '@angular/core';
-
-@Component({
-  selector: 'app-death-save-details',
-  templateUrl: './death-save-details.component.html',
-  styleUrl: './death-save-details.component.scss',
-})
-export class DeathSaveDetailsComponent {}

+ 0 - 45
src/app/journal/journal-stats/info-row/death-save/death-save.component.html

@@ -1,45 +0,0 @@
-<div class="death-save-container" (click)="openDetails()">
-  <div style="margin: 0.625rem 0 0 0.4rem">
-    <div class="save-row">
-      <div class="save-label">{{ "deathSave.success" | translate }}</div>
-      <div class="save-checkbox" (click)="$event.stopPropagation()">
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveSucc1"
-          (change)="updateValue()"
-        />
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveSucc2"
-          (change)="updateValue()"
-        />
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveSucc3"
-          (change)="updateValue()"
-        />
-      </div>
-    </div>
-    <div class="save-row">
-      <div class="save-label">{{ "deathSave.fail" | translate }}</div>
-      <div class="save-checkbox fail" (click)="$event.stopPropagation()">
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveFail1"
-          (change)="updateValue()"
-        />
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveFail2"
-          (change)="updateValue()"
-        />
-        <input
-          type="checkbox"
-          [(ngModel)]="deathSaveFail3"
-          (change)="updateValue()"
-        />
-      </div>
-    </div>
-  </div>
-  <div class="death-save">{{ "deathSave.label" | translate }}</div>
-</div>

+ 1 - 1
src/app/journal/journal-stats/info-row/info-row.component.html

@@ -4,5 +4,5 @@
   <movement></movement>
   <proficiency></proficiency>
   <conditions></conditions>
-  <death-save></death-save>
+  <!-- <death-save></death-save> -->
 </div>

+ 5 - 1
src/app/journal/journal-stats/info-row/info-row.component.scss

@@ -3,7 +3,11 @@
 .row-container {
   display: flex;
   justify-content: space-between;
-  width: 1011px;
+  width: 797px;
+
+  @include width-small {
+    width: 1011px;
+  }
 
   @include width-medium {
     width: 1225px;

+ 9 - 5
src/app/journal/journal-stats/journal-stats.component.scss

@@ -58,20 +58,24 @@
   display: flex;
   flex-direction: column;
   gap: 1rem;
-  width: 500px;
+  width: 388px;
 
-  // @include width-small {
-  //   width: 614px;
-  // }
+  @include width-small {
+    width: 500px;
+  }
   @include width-medium {
     width: 600px;
   }
 }
 
 ability-panel {
-  width: 495px;
+  width: 391px;
   height: 702px;
 
+  @include width-small {
+    width: 495px;
+  }
+
   @include width-medium {
     width: 609px;
   }

+ 47 - 0
src/app/journal/journal-stats/life-container/death-save/death-save.component.html

@@ -0,0 +1,47 @@
+<div class="content t-05">{{ "life.description" | translate }}</div>
+
+<div class="left">
+  <b>{{ "life.criticalHeader" | translate }}</b>
+</div>
+<div class="content t-05">{{ "life.criticalContent" | translate }}</div>
+
+<div class="save-row">
+  <div class="save-label">{{ "life.success" | translate }}</div>
+  <div class="save-checkbox" (click)="$event.stopPropagation()">
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveSucc1"
+      (change)="updateValue()"
+    />
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveSucc2"
+      (change)="updateValue()"
+    />
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveSucc3"
+      (change)="updateValue()"
+    />
+  </div>
+</div>
+<div class="save-row t-05">
+  <div class="save-label">{{ "life.fail" | translate }}</div>
+  <div class="save-checkbox fail" (click)="$event.stopPropagation()">
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveFail1"
+      (change)="updateValue()"
+    />
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveFail2"
+      (change)="updateValue()"
+    />
+    <input
+      type="checkbox"
+      [(ngModel)]="deathSaveFail3"
+      (change)="updateValue()"
+    />
+  </div>
+</div>

+ 3 - 3
src/app/journal/journal-stats/info-row/death-save/death-save.component.scss → src/app/journal/journal-stats/life-container/death-save/death-save.component.scss

@@ -14,12 +14,12 @@
   display: flex;
   width: 100%;
   justify-content: space-between;
+  padding-right: 6rem;
 }
 
 .save-label {
-  font-weight: 600;
-  text-align: center;
-  padding: 0 0.5rem 0 0.5rem;
+  font-weight: 700;
+  padding-left: 0.5rem;
 }
 
 .save-checkbox {

+ 0 - 0
src/app/journal/journal-stats/info-row/death-save/death-save.component.spec.ts → src/app/journal/journal-stats/life-container/death-save/death-save.component.spec.ts


+ 1 - 10
src/app/journal/journal-stats/info-row/death-save/death-save.component.ts → src/app/journal/journal-stats/life-container/death-save/death-save.component.ts

@@ -1,7 +1,5 @@
 import { Component } from '@angular/core';
 import { DataService } from 'src/services/data/data.service';
-import { DetailsService } from 'src/services/details/details.service';
-import { DeathSaveDetailsComponent } from './death-save-details/death-save-details.component';
 
 @Component({
   selector: 'death-save',
@@ -9,10 +7,7 @@ import { DeathSaveDetailsComponent } from './death-save-details/death-save-detai
   styleUrls: ['./death-save.component.scss'],
 })
 export class DeathSaveComponent {
-  public constructor(
-    private dataAccessor: DataService,
-    public detailsAccessor: DetailsService,
-  ) {}
+  public constructor(private dataAccessor: DataService) {}
 
   public deathSave: number[] = [0, 0];
 
@@ -94,8 +89,4 @@ export class DeathSaveComponent {
       }
     });
   }
-
-  public openDetails(): void {
-    this.detailsAccessor.openPanel(DeathSaveDetailsComponent, {});
-  }
 }

+ 10 - 21
src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.html

@@ -1,11 +1,4 @@
-<div class="heading-line">
-  <div class="heading left t-0">{{ "life.hitdice" | translate }}</div>
-  <icon-button
-    [icon]="showEditButtons ? 'cross' : 'edit'"
-    (click)="showEditButtons = !showEditButtons"
-  ></icon-button>
-</div>
-<div class="content">{{ "life.hitdiceDescription" | translate }}</div>
+<div class="content t-05">{{ "life.hitdiceDescription" | translate }}</div>
 <p>
   <b>{{ "general.diceType" | translate }}: </b>
   {{ "general.dice" | translate }}{{ hitDice.diceType }}
@@ -21,17 +14,13 @@
       />
     }
   </div>
-  @if (showEditButtons) {
-    <div style="display: flex; flex-direction: column">
-      <icon-button
-        [icon]="'add'"
-        (click)="hitDice.diceNumber = hitDice.diceNumber + 1"
-      ></icon-button>
-      <icon-button
-        [icon]="'remove'"
-        style="margin-top: 1rem"
-        (click)="hitDice.diceNumber = hitDice.diceNumber - 1"
-      ></icon-button>
-    </div>
-  }
+  <div style="display: flex; flex-direction: column">
+    <icon-button [icon]="'add'" (click)="addDice()"></icon-button>
+    <icon-button
+      [icon]="'remove'"
+      [disabled]="hitDice.diceNumber === 1"
+      style="margin-top: 1rem"
+      (click)="removeDice()"
+    ></icon-button>
+  </div>
 </div>

+ 1 - 8
src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.scss

@@ -1,8 +1,3 @@
-.heading-line {
-  display: flex;
-  align-items: flex-start;
-  gap: 0.5rem;
-}
 .hit-dice-container {
   display: flex;
   flex-direction: row;
@@ -13,11 +8,9 @@
     flex-direction: row;
     flex-wrap: wrap;
     width: 20rem;
+    padding-right: 5rem;
     row-gap: 0.5rem;
     column-gap: 3rem;
-    // input {
-    //     flex: 0 0 4rem;
-    // }
   }
 }
 

+ 15 - 9
src/app/journal/journal-stats/life-container/hit-dice/hit-dice.component.ts

@@ -8,7 +8,6 @@ import { DataService } from 'src/services/data/data.service';
 })
 export class HitDiceComponent {
   public hitDice: any;
-  showEditButtons: boolean = false;
 
   @Output() public setHitDice: EventEmitter<any> = new EventEmitter();
 
@@ -18,26 +17,21 @@ export class HitDiceComponent {
 
   public ngOnInit(): void {
     this.correctHitDiceView();
-    this.emitHitDice();
   }
 
   public handleUsedHitDice(index: number, element: any): void {
-    console.log('HITDICE in hitdice first: ', this.hitDice);
     if (element.checked) {
-      console.log('The checkbox is checked now ');
       this.hitDice.diceUsed++;
       if (index + 1 !== this.hitDice.diceUsed) {
         this.correctHitDiceView();
       }
     } else {
-      console.log('The checkbox is unchecked now ');
       this.hitDice.diceUsed--;
       if (index !== this.hitDice.diceUsed) {
         this.correctHitDiceView();
       }
     }
-    console.log('HITDICE in hitdice: ', this.hitDice);
-    this.emitHitDice();
+    this.updateDatabase();
   }
 
   private correctHitDiceView(): void {
@@ -64,10 +58,22 @@ export class HitDiceComponent {
     return Array.from({ length: length });
   }
 
-  private emitHitDice(): void {
+  public addDice(): void {
+    this.hitDice.diceNumber++;
+    this.updateDatabase();
+  }
+
+  public removeDice(): void {
+    if (this.hitDice.diceNumber > 1) {
+      this.hitDice.diceNumber--;
+    }
     if (this.hitDice.diceUsed > this.hitDice.diceNumber) {
       this.hitDice.diceUsed = this.hitDice.diceNumber;
     }
-    this.setHitDice.emit(this.hitDice);
+    this.updateDatabase();
+  }
+
+  public updateDatabase(): void {
+    this.dataAccessor.hitDice = this.hitDice;
   }
 }

+ 28 - 18
src/app/journal/journal-stats/life-container/life/life-details/life-details.component.html

@@ -3,14 +3,14 @@
 <div class="value-row t-2 b-15">
   <value-box
     [isInput]="true"
-    [(ngModel)]="maxHitPoints"
-    [label]="'life.max'"
+    [(ngModel)]="currentHitPoints"
+    [label]="'life.current'"
     (change)="checkValidity()"
   ></value-box>
   <value-box
     [isInput]="true"
-    [(ngModel)]="currentHitPoints"
-    [label]="'life.current'"
+    [(ngModel)]="maxHitPoints"
+    [label]="'life.max'"
     (change)="checkValidity()"
   ></value-box>
   <value-box
@@ -19,21 +19,31 @@
     [label]="'life.temporary'"
   ></value-box>
 </div>
-<hit-dice style="margin-top: 5rem" (setHitDice)="setHitDice($event)"></hit-dice>
 
-<div class="vertical-buttons bottom">
-  <ui-button
-    [color]="'green'"
-    [type]="'apply'"
-    [width]="'w20'"
-    (click)="close('update')"
+<div class="tab-row">
+  <button
+    class="tab-button"
+    (click)="active = 1"
+    [class]="active === 1 ? 'active' : ''"
   >
-  </ui-button>
-  <ui-button
-    [color]="'red'"
-    [type]="'discard'"
-    [width]="'w20'"
-    (click)="close('cancel')"
+    {{ "life.hitdice" | translate }}
+  </button>
+  <button
+    class="tab-button"
+    (click)="active = 2"
+    [class]="active === 2 ? 'active' : ''"
   >
-  </ui-button>
+    {{ "life.deathSave" | translate }}
+  </button>
+</div>
+
+<div class="life-data-container">
+  @switch (active) {
+    @case (1) {
+      <hit-dice style="margin-top: 5rem"></hit-dice>
+    }
+    @case (2) {
+      <death-save></death-save>
+    }
+  }
 </div>

+ 38 - 26
src/app/journal/journal-stats/life-container/life/life-details/life-details.component.scss

@@ -33,37 +33,49 @@
   }
 }
 
-hit-dice {
-  margin-top: 1.5rem;
+.tab-button {
+  height: 3rem;
+  font-size: 1.375rem;
+  font-weight: 600;
+  color: black;
+  transition: all 0.25s ease-in-out;
+  background-color: var(--tab);
+  border-top: 0;
+  border-left: 0;
+  border-bottom: 1px solid var(--border-color);
+  border-right: 0;
+
+  &.active {
+    background-color: var(--tab-active);
+    border-bottom: 3px solid var(--border-color);
+  }
 }
 
-.button-container {
-  height: 9rem;
-  width: 27rem;
-  position: absolute;
-  bottom: 0;
+.tab-row {
   display: flex;
-  justify-content: space-evenly;
-  align-items: center;
-  flex-direction: column;
-
-  .confirm {
-    width: 20rem;
-    margin: 0 auto;
-    background-color: var(--accept);
-
-    &:hover {
-      background-color: var(--accept-hover);
+  flex: 0 0 3rem;
+  > * {
+    flex: 1 1 0;
+  }
+  > :first-child {
+    border-radius: 10px 0 0 0;
+    &.active {
+      border-right: 1px solid var(--border-color);
     }
   }
-
-  .cancel {
-    width: 20rem;
-    margin: 0 auto;
-    background-color: var(--delete);
-
-    &:hover {
-      background-color: var(--delete-hover);
+  > :last-child {
+    border-radius: 0 10px 0 0;
+    border-right: 1px solid var(--border-color);
+    &.active {
+      border-left: 1px solid var(--border-color);
     }
   }
 }
+
+.life-data-container {
+  height: calc(100% - 30rem);
+  background-color: var(--field-background-color);
+  border: var(--border);
+  border-radius: 0 0 10px 10px;
+  padding: 0.5rem;
+}

+ 18 - 25
src/app/journal/journal-stats/life-container/life/life-details/life-details.component.ts

@@ -1,5 +1,6 @@
 import { Component, Input } from '@angular/core';
 import { DetailsService } from 'src/services/details/details.service';
+import { DataService } from 'src/services/data/data.service';
 
 @Component({
   selector: 'app-life-details',
@@ -7,45 +8,37 @@ import { DetailsService } from 'src/services/details/details.service';
   styleUrls: ['./life-details.component.scss'],
 })
 export class LifeDetailsComponent {
-  public constructor(public detailsAccessor: DetailsService) {}
+  public constructor(
+    public detailsAccessor: DetailsService,
+    private dataAccessor: DataService,
+  ) {}
 
-  @Input() lifeData: any;
-  private hitDice: any;
+  public active: number = 1;
 
   public maxHitPoints: number = 0;
   public currentHitPoints: number = 0;
   public temporaryHitPoints: number = 0;
 
   public ngOnInit(): void {
-    this.maxHitPoints = this.lifeData.maxHitPoints;
-    this.currentHitPoints = this.lifeData.currentHitPoints;
-    this.temporaryHitPoints = this.lifeData.temporaryHitPoints;
+    this.dataAccessor.hitPoints$.subscribe((hitPoints: any) => {
+      this.maxHitPoints = hitPoints.maxHitPoints;
+      this.currentHitPoints = hitPoints.currentHitPoints;
+      this.temporaryHitPoints = hitPoints.temporaryHitPoints;
+    });
   }
 
   public checkValidity(): void {
     if (this.currentHitPoints > this.maxHitPoints) {
       this.currentHitPoints = this.maxHitPoints;
     }
+    this.updateHitPointsDatabas();
   }
 
-  public close(result: string): void {
-    if (result === 'update') {
-      this.detailsAccessor.closePanel(result, {
-        maxHitPoints: this.maxHitPoints,
-        currentHitPoints: this.currentHitPoints,
-        temporaryHitPoints: this.temporaryHitPoints,
-        hitDice: this.hitDice,
-      });
-    } else if (result === 'cancel') {
-      this.detailsAccessor.closePanel(result);
-    }
-  }
-
-  public setHitDice(hitDiceData: any): void {
-    this.hitDice = hitDiceData;
-  }
-
-  test() {
-    console.log('TEST');
+  public updateHitPointsDatabas(): void {
+    this.dataAccessor.updateHitPoints({
+      maxHitPoints: this.maxHitPoints,
+      currentHitPoints: this.currentHitPoints,
+      temporaryHitPoints: this.temporaryHitPoints,
+    });
   }
 }

+ 17 - 36
src/app/journal/journal-stats/life-container/life/life.component.ts

@@ -17,22 +17,28 @@ export class LifeComponent {
   public temporaryHitPointsPercentage: number = 0;
   public missingHitPointsPercentage: number = 0;
 
-  private hitDice: any;
-
   public constructor(
     public dataAccessor: DataService,
     public detailsAccessor: DetailsService,
   ) {}
 
   ngOnInit(): void {
-    const hitPointsData = this.dataAccessor.hitPoints;
-    this.maxHitPoints = hitPointsData.maxHitPoints;
-    this.currentHitPoints = hitPointsData.currentHitPoints;
-    this.temporaryHitPoints = hitPointsData.temporaryHitPoints;
-    this.hitDice = this.dataAccessor.hitDice;
-    this.calculatePercentages();
+    this.dataAccessor.hitPoints$.subscribe((hitPoints: any) => {
+      this.maxHitPoints = hitPoints.maxHitPoints;
+      this.currentHitPoints = hitPoints.currentHitPoints;
+      this.temporaryHitPoints = hitPoints.temporaryHitPoints;
+      this.calculatePercentages();
+    });
   }
 
+  //   const hitPointsData = this.dataAccessor.hitPoints;
+  //   this.maxHitPoints = hitPointsData.maxHitPoints;
+  //   this.currentHitPoints = hitPointsData.currentHitPoints;
+  //   this.temporaryHitPoints = hitPointsData.temporaryHitPoints;
+  //   this.hitDice = this.dataAccessor.hitDice;
+  //   this.calculatePercentages();
+  // }
+
   public addHitPoints(): void {
     if (this.currentHitPoints < this.maxHitPoints) {
       this.currentHitPoints = this.currentHitPoints + 1;
@@ -73,39 +79,14 @@ export class LifeComponent {
   }
 
   public openDetailsPanel(): void {
-    this.detailsAccessor.openPanel(LifeDetailsComponent, {
-      lifeData: {
-        maxHitPoints: this.maxHitPoints,
-        currentHitPoints: this.currentHitPoints,
-        temporaryHitPoints: this.temporaryHitPoints,
-      },
-    });
-    // The result from the details panel with return values
-    const resultSubscription = this.detailsAccessor.result$.subscribe(
-      (result) => {
-        if (result.state === 'update') {
-          this.maxHitPoints = result.data.maxHitPoints;
-          this.currentHitPoints = result.data.currentHitPoints;
-          this.temporaryHitPoints = result.data.temporaryHitPoints;
-          this.hitDice = result.data.hitDice;
-          console.log('HITDICE IN LIFE-RESPONSE: ', this.hitDice);
-          this.calculatePercentages();
-          this.updateDatabase();
-        } else if (result.state === 'cancel') {
-          // Do nothing
-        }
-        resultSubscription.unsubscribe();
-      },
-    );
+    this.detailsAccessor.openPanel(LifeDetailsComponent, {});
   }
 
   public updateDatabase() {
-    console.warn(this.hitDice.diceNumber);
-    this.dataAccessor.hitPoints = {
+    this.dataAccessor.updateHitPoints({
       maxHitPoints: this.maxHitPoints,
       currentHitPoints: this.currentHitPoints,
       temporaryHitPoints: this.temporaryHitPoints,
-    };
-    this.dataAccessor.hitDice = this.hitDice;
+    });
   }
 }

+ 1 - 3
src/app/journal/journal.module.ts

@@ -35,7 +35,7 @@ import { MovementComponent } from './journal-stats/info-row/movement/movement.co
 import { HitDiceComponent } from './journal-stats/life-container/hit-dice/hit-dice.component';
 import { InitiativeComponent } from './journal-stats/info-row/initiative/initiative.component';
 import { ConditionsDetailsComponent } from './journal-stats/info-row/conditions/conditions-details/conditions-details.component';
-import { DeathSaveComponent } from './journal-stats/info-row/death-save/death-save.component';
+import { DeathSaveComponent } from './journal-stats/life-container/death-save/death-save.component';
 import { LifeComponent } from './journal-stats/life-container/life/life.component';
 import { IconComponent } from './icon/icon.component';
 import { WeaponTableComponent } from './journal-stats/weapons-container/weapon-table/weapon-table.component';
@@ -74,7 +74,6 @@ import { ArmorClassDetailsComponent } from './journal-stats/info-row/armor-class
 import { InitiativeDetailsComponent } from './journal-stats/info-row/initiative/initiative-details/initiative-details.component';
 import { MovementDetailsComponent } from './journal-stats/info-row/movement/movement-details/movement-details.component';
 import { ProficiencyDetailsComponent } from './journal-stats/info-row/proficiency/proficiency-details/proficiency-details.component';
-import { DeathSaveDetailsComponent } from './journal-stats/info-row/death-save/death-save-details/death-save-details.component';
 import { ExhaustionDetailsComponent } from './journal-stats/info-row/conditions/exhaustion-details/exhaustion-details.component';
 import { NavigationPanelComponent } from './journal-home/navigation-panel/navigation-panel.component';
 import { JournalNotesComponent } from './journal-notes/journal-notes.component';
@@ -150,7 +149,6 @@ import { CombinedComponent } from './journal-character/combined/combined.compone
     InitiativeDetailsComponent,
     MovementDetailsComponent,
     ProficiencyDetailsComponent,
-    DeathSaveDetailsComponent,
     ExhaustionDetailsComponent,
     NavigationPanelComponent,
     JournalNotesComponent,

+ 7 - 9
src/assets/i18n/de.json

@@ -496,21 +496,19 @@
     "5": "Bewegungsrate fällt auf 0",
     "6": "Sofortiger Tod"
   },
-  "deathSave": {
-    "label": "Todesrettungswürfe",
-    "success": "Erfolg",
-    "fail": "Fehlschlag",
-    "description": "Immer wenn ein Charakter seinen Zug mit 0 Trefferpunkten beginnt und nicht stabilisiert wurde, muss er einen Todesrettungswurf ablegen. Ist das Ergebnis 10 oder höher, ist der Wurf erfolgreich, ansonsten fehlgeschlagen. Beim dritten Erfolg wird der Charakter stabilisiert, beim dritten Fehlschlag stirbt er.",
-    "criticalHeader": "Eine 1 oder 20 würfeln",
-    "criticalContent": "Würfelt ein Charakter eine 1, zählt der Wurf als zwei Fehlschläge. Würfelt er eine 20, erhält er sofort einen Lebenspunkt dazu und ist nicht mehr bewustlos."
-  },
   "life": {
     "hitpoints": "Trefferpunkte",
     "max": "Maximale Trefferpunkte",
     "temporary": "Temporäre Trefferpunkte",
     "current": "Aktuelle Trefferpunkte",
     "hitdice": "Trefferwürfel",
-    "hitdiceDescription": "Trefferwürfel werden verwendet, um bei einer kurzen Rast Trefferpunkte wiederherzustellen. Du kannst eine beliebige Anzahl deiner verfügbaren Trefferwürfel verwenden. Sie werden bei einer langen rast wiederhergestellt."
+    "hitdiceDescription": "Trefferwürfel werden verwendet, um bei einer kurzen Rast Trefferpunkte wiederherzustellen. Du kannst eine beliebige Anzahl deiner verfügbaren Trefferwürfel verwenden. Sie werden bei einer langen rast wiederhergestellt.",
+    "deathSave": "Todesrettungswürfe",
+    "success": "Erfolg",
+    "fail": "Fehlschlag",
+    "description": "Immer wenn ein Charakter seinen Zug mit 0 Trefferpunkten beginnt und nicht stabilisiert wurde, muss er einen Todesrettungswurf ablegen. Ist das Ergebnis 10 oder höher, ist der Wurf erfolgreich, ansonsten fehlgeschlagen. Beim dritten Erfolg wird der Charakter stabilisiert, beim dritten Fehlschlag stirbt er.",
+    "criticalHeader": "Eine 1 oder 20 würfeln",
+    "criticalContent": "Würfelt ein Charakter eine 1, zählt der Wurf als zwei Fehlschläge. Würfelt er eine 20, erhält er sofort einen Lebenspunkt dazu und ist nicht mehr bewustlos."
   },
   "weapons": {
     "header": {

+ 112 - 85
src/services/data/data.service.ts

@@ -96,7 +96,7 @@ export class DataService {
     });
 
     // Hit Points
-    this.hitPoints = hitPointsData.hitPoints;
+    this.hitPointsSubject.next(hitPointsData.hitPoints);
     this.hitDice = hitPointsData.hitDice;
 
     // Combat Stats
@@ -622,19 +622,16 @@ export class DataService {
 
   // #region # HIT POINTS
 
-  private _hitPoints = {
+  private hitPointsSubject = new BehaviorSubject<any>({
     maxHitPoints: 6,
     currentHitPoints: 6,
     temporaryHitPoints: 1,
-  };
-
-  public get hitPoints(): any {
-    return this._hitPoints;
-  }
+  });
+  public hitPoints$ = this.hitPointsSubject.asObservable();
 
-  public set hitPoints(newValue: any) {
-    this._hitPoints = newValue;
-    this.updateHitPoints();
+  public updateHitPoints(newValue: any) {
+    this.hitPointsSubject.next(newValue);
+    this.updateLifeData();
   }
 
   private _hitDice = {
@@ -649,12 +646,12 @@ export class DataService {
 
   public set hitDice(newValue: any) {
     this._hitDice = newValue;
-    this.updateHitPoints();
+    this.updateLifeData();
   }
 
-  private updateHitPoints() {
+  private updateLifeData() {
     const hitPointsData = {
-      hitPoints: this._hitPoints,
+      hitPoints: this.hitPointsSubject.getValue(),
       hitDice: this._hitDice,
     };
     this.setData('hitPoints', hitPointsData);
@@ -677,34 +674,46 @@ export class DataService {
     this.setData('attributes', attributesData);
   }
 
-  private strengthSubject = new BehaviorSubject<Attribute>(
-    { name: 'strength', value: 10, proficiency: true }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private strengthSubject = new BehaviorSubject<Attribute>({
+    name: 'strength',
+    value: 10,
+    proficiency: true,
+  });
   public strength$ = this.strengthSubject.asObservable();
 
-  private dexteritySubject = new BehaviorSubject<Attribute>(
-    { name: 'dexterity', value: 10, proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private dexteritySubject = new BehaviorSubject<Attribute>({
+    name: 'dexterity',
+    value: 10,
+    proficiency: false,
+  });
   public dexterity$ = this.dexteritySubject.asObservable();
 
-  private constitutionSubject = new BehaviorSubject<Attribute>(
-    { name: 'constitution', value: 10, proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private constitutionSubject = new BehaviorSubject<Attribute>({
+    name: 'constitution',
+    value: 10,
+    proficiency: false,
+  });
   public constitution$ = this.constitutionSubject.asObservable();
 
-  private intelligenceSubject = new BehaviorSubject<Attribute>(
-    { name: 'intelligence', value: 10, proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private intelligenceSubject = new BehaviorSubject<Attribute>({
+    name: 'intelligence',
+    value: 10,
+    proficiency: false,
+  });
   public intelligence$ = this.intelligenceSubject.asObservable();
 
-  private wisdomSubject = new BehaviorSubject<Attribute>(
-    { name: 'wisdom', value: 10, proficiency: true }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private wisdomSubject = new BehaviorSubject<Attribute>({
+    name: 'wisdom',
+    value: 10,
+    proficiency: true,
+  });
   public wisdom$ = this.wisdomSubject.asObservable();
 
-  private charismaSubject = new BehaviorSubject<Attribute>(
-    { name: 'charisma', value: 10, proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private charismaSubject = new BehaviorSubject<Attribute>({
+    name: 'charisma',
+    value: 10,
+    proficiency: false,
+  });
   public charisma$ = this.charismaSubject.asObservable();
 
   // #endregion
@@ -737,94 +746,112 @@ export class DataService {
     this.setData('skills', skillsData);
   }
 
-  private acrobaticsSubject = new BehaviorSubject<Skill>(
-    { name: 'acrobatics', proficiency: true }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private acrobaticsSubject = new BehaviorSubject<Skill>({
+    name: 'acrobatics',
+    proficiency: true,
+  });
   public acrobatics$ = this.acrobaticsSubject.asObservable();
 
-  private animalHandlingSubject = new BehaviorSubject<Skill>(
-    { name: 'animalHandling', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private animalHandlingSubject = new BehaviorSubject<Skill>({
+    name: 'animalHandling',
+    proficiency: false,
+  });
   public animalHandling$ = this.animalHandlingSubject.asObservable();
 
-  private arcanaSubject = new BehaviorSubject<Skill>(
-    { name: 'arcana', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private arcanaSubject = new BehaviorSubject<Skill>({
+    name: 'arcana',
+    proficiency: false,
+  });
   public arcana$ = this.arcanaSubject.asObservable();
 
-  private athleticsSubject = new BehaviorSubject<Skill>(
-    { name: 'athletics', proficiency: true }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private athleticsSubject = new BehaviorSubject<Skill>({
+    name: 'athletics',
+    proficiency: true,
+  });
   public athletics$ = this.athleticsSubject.asObservable();
 
-  private deceptionSubject = new BehaviorSubject<Skill>(
-    { name: 'deception', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private deceptionSubject = new BehaviorSubject<Skill>({
+    name: 'deception',
+    proficiency: false,
+  });
   public deception$ = this.deceptionSubject.asObservable();
 
-  private historySubject = new BehaviorSubject<Skill>(
-    { name: 'history', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private historySubject = new BehaviorSubject<Skill>({
+    name: 'history',
+    proficiency: false,
+  });
   public history$ = this.historySubject.asObservable();
 
-  private insightSubject = new BehaviorSubject<Skill>(
-    { name: 'insight', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private insightSubject = new BehaviorSubject<Skill>({
+    name: 'insight',
+    proficiency: false,
+  });
   public insight$ = this.insightSubject.asObservable();
 
-  private intimidationSubject = new BehaviorSubject<Skill>(
-    { name: 'intimidation', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private intimidationSubject = new BehaviorSubject<Skill>({
+    name: 'intimidation',
+    proficiency: false,
+  });
   public intimidation$ = this.intimidationSubject.asObservable();
 
-  private investigationSubject = new BehaviorSubject<Skill>(
-    { name: 'investigation', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private investigationSubject = new BehaviorSubject<Skill>({
+    name: 'investigation',
+    proficiency: false,
+  });
   public investigation$ = this.investigationSubject.asObservable();
 
-  private medicineSubject = new BehaviorSubject<Skill>(
-    { name: 'medicine', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private medicineSubject = new BehaviorSubject<Skill>({
+    name: 'medicine',
+    proficiency: false,
+  });
   public medicine$ = this.medicineSubject.asObservable();
 
-  private natureSubject = new BehaviorSubject<Skill>(
-    { name: 'nature', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private natureSubject = new BehaviorSubject<Skill>({
+    name: 'nature',
+    proficiency: false,
+  });
   public nature$ = this.natureSubject.asObservable();
 
-  private perceptionSubject = new BehaviorSubject<Skill>(
-    { name: 'perception', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private perceptionSubject = new BehaviorSubject<Skill>({
+    name: 'perception',
+    proficiency: false,
+  });
   public perception$ = this.perceptionSubject.asObservable();
 
-  private performanceSubject = new BehaviorSubject<Skill>(
-    { name: 'performance', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private performanceSubject = new BehaviorSubject<Skill>({
+    name: 'performance',
+    proficiency: false,
+  });
   public performance$ = this.performanceSubject.asObservable();
 
-  private persuasionSubject = new BehaviorSubject<Skill>(
-    { name: 'persuasion', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private persuasionSubject = new BehaviorSubject<Skill>({
+    name: 'persuasion',
+    proficiency: false,
+  });
   public persuasion$ = this.persuasionSubject.asObservable();
 
-  private religionSubject = new BehaviorSubject<Skill>(
-    { name: 'religion', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private religionSubject = new BehaviorSubject<Skill>({
+    name: 'religion',
+    proficiency: false,
+  });
   public religion$ = this.religionSubject.asObservable();
 
-  private sleightOfHandSubject = new BehaviorSubject<Skill>(
-    { name: 'sleightOfHand', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private sleightOfHandSubject = new BehaviorSubject<Skill>({
+    name: 'sleightOfHand',
+    proficiency: false,
+  });
   public sleightOfHand$ = this.sleightOfHandSubject.asObservable();
 
-  private stealthSubject = new BehaviorSubject<Skill>(
-    { name: 'stealth', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private stealthSubject = new BehaviorSubject<Skill>({
+    name: 'stealth',
+    proficiency: false,
+  });
   public stealth$ = this.stealthSubject.asObservable();
 
-  private survivalSubject = new BehaviorSubject<Skill>(
-    { name: 'survival', proficiency: false }, //erstmal nur gemockt, später muss der Wert aus der Datenbank kommen
-  );
+  private survivalSubject = new BehaviorSubject<Skill>({
+    name: 'survival',
+    proficiency: false,
+  });
   public survival$ = this.survivalSubject.asObservable();
 
   // #endregion

+ 4 - 4
src/styles.scss

@@ -142,11 +142,11 @@ input[type="checkbox"] {
   height: 6rem;
   width: 7rem;
 
-  @include width-medium {
+  @include width-small {
     width: 10rem;
   }
 }
-// Responsive styles
+// // Responsive styles
 .responsive-small {
   display: block;
 }
@@ -155,13 +155,13 @@ input[type="checkbox"] {
   display: none;
 }
 .responsive-large {
-  @include width-medium {
+  @include width-small {
     display: block;
   }
 }
 
 .responsive-small {
-  @include width-medium {
+  @include width-small {
     display: none;
   }
 }