Browse Source

Finished attribute and save details components. Next is skills details

Christopher Giese 1 year ago
parent
commit
50ef2401a5
19 changed files with 330 additions and 67 deletions
  1. 75 0
      .nx/cache/d/daemon.log
  2. 1 1
      .nx/cache/d/server-process.json
  3. 1 0
      src/app/journal/journal-home/details-panel/details-panel.component.scss
  4. 30 48
      src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.html
  5. 32 4
      src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.scss
  6. 21 0
      src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.ts
  7. 2 1
      src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-field.component.scss
  8. 1 2
      src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-field.component.ts
  9. 16 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.html
  10. 36 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.scss
  11. 23 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.spec.ts
  12. 11 0
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.ts
  13. 8 4
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.html
  14. 63 3
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.ts
  15. 1 1
      src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-panel.component.html
  16. 1 1
      src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.ts
  17. 2 0
      src/app/journal/journal.module.ts
  18. 1 1
      src/interfaces/attribute.ts
  19. 5 1
      src/styles.scss

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

@@ -459745,3 +459745,78 @@ To fix this, set a unique name for each project in a project.json inside the pro
 [NX Daemon Server] - 2023-11-19T09:40:23.437Z - [WATCHER]: Processing file changes in outputs
 [NX Daemon Server] - 2023-11-19T09:40:23.437Z - [WATCHER]: Processing file changes in outputs
 [NX Daemon Server] - 2023-11-19T09:40:23.438Z - [WATCHER]: .nx/cache/d/daemon.log was modified
 [NX Daemon Server] - 2023-11-19T09:40:23.438Z - [WATCHER]: .nx/cache/d/daemon.log was modified
 [NX Daemon Server] - 2023-11-19T09:40:23.438Z - Done responding to the client null
 [NX Daemon Server] - 2023-11-19T09:40:23.438Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-20T17:45:45.792Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\e6a479e02f1047051806\d.sock
+[NX Daemon Server] - 2023-11-20T17:45:45.800Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\Test\DnDTools (native)
+[NX Daemon Server] - 2023-11-20T17:45:45.802Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-20T17:45:45.804Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2023-11-20T17:45:45.804Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-20T17:45:45.806Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-20T17:45:46.398Z - 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-20T17:45:46.398Z - [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\Test\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\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\Test\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2023-11-20T17:45:46.399Z - Time taken for 'hash changed files from watcher' 169.283999979496ms
+[NX Daemon Server] - 2023-11-20T17:45:46.400Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-20T17:45:46.401Z - [WATCHER]: .nx/cache/d/daemon.log was modified
+[NX Daemon Server] - 2023-11-20T17:45:46.401Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-20T18:05:08.380Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\e6a479e02f1047051806\d.sock
+[NX Daemon Server] - 2023-11-20T18:05:08.386Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\Test\DnDTools (native)
+[NX Daemon Server] - 2023-11-20T18:05:08.387Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-20T18:05:08.388Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2023-11-20T18:05:08.389Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-20T18:05:08.390Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-20T18:05:08.805Z - 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-20T18:05:08.805Z - [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\Test\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Users\chris\Softwareprojekte\Test\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\Test\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Users\chris\Softwareprojekte\Test\DnDTools\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2023-11-20T18:05:08.806Z - Time taken for 'hash changed files from watcher' 22.765500009059906ms
+[NX Daemon Server] - 2023-11-20T18:05:08.807Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-20T18:05:08.807Z - Done responding to the client null

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

@@ -1 +1 @@
-{"processId":10560}
+{"processId":15616}

+ 1 - 0
src/app/journal/journal-home/details-panel/details-panel.component.scss

@@ -23,6 +23,7 @@
     width: 25vw;
     width: 25vw;
     background-color: var(--background-color);
     background-color: var(--background-color);
     z-index: 999;
     z-index: 999;
+    padding: 1.5rem;
     transform: translateX(100%);
     transform: translateX(100%);
     transition: transform 0.3s ease-in-out;
     transition: transform 0.3s ease-in-out;
 }
 }

+ 30 - 48
src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.html

@@ -14,8 +14,16 @@
   @default{ Leider gab es einen Fehler bei der Datenübertragung. Bitte öffne ein
   @default{ Leider gab es einen Fehler bei der Datenübertragung. Bitte öffne ein
   Issue auf Github. } }
   Issue auf Github. } }
 </div>
 </div>
-
-<div class="attribute-value">{{ attribute.value }} => {{ modifier }}</div>
+<div class="attribute-container">
+  <div>
+    <div class="attribute-value">{{ attribute.value }}</div>
+    <div class="attribute-label">Attributwert</div>
+  </div>
+  <div>
+    <div class="attribute-value">{{ modifier }}</div>
+    <div class="attribute-label">Modifikator</div>
+  </div>
+</div>
 <div class="modifier-table">
 <div class="modifier-table">
   <table class="table table-striped">
   <table class="table table-striped">
     <thead>
     <thead>
@@ -72,42 +80,40 @@
     </tbody>
     </tbody>
   </table>
   </table>
 </div>
 </div>
+@if(attribute.name !== 'constitution'){
+<div class="details-subheading">Beeinflusste Fähigkeiten:</div>
+<div class="skills">
+  @for(skill of skillsTable[attribute.name]; track skill){
+  <div class="skill-item">{{ skill }}</div>
+  }
+</div>
+}
 
 
 <ng-template #strengthTemplate>
 <ng-template #strengthTemplate>
-  <div class="attribute-name">Stärke</div>
-  <div class="attribute-description">
+  <div class="details-title">Stärke</div>
+  <div class="details-content">
     Stärke misst die physische Kraft und Muskulatur deines Charakters. Ein hoher
     Stärke misst die physische Kraft und Muskulatur deines Charakters. Ein hoher
     Stärkewert deutet auf körperliche Robustheit, Muskelkraft und
     Stärkewert deutet auf körperliche Robustheit, Muskelkraft und
     Durchsetzungsvermögen hin. Charaktere mit hoher Stärke sind oft besser in
     Durchsetzungsvermögen hin. Charaktere mit hoher Stärke sind oft besser in
     der Lage, schwere Lasten zu tragen, mächtige Waffen zu schwingen und
     der Lage, schwere Lasten zu tragen, mächtige Waffen zu schwingen und
     physische Herausforderungen zu bewältigen.
     physische Herausforderungen zu bewältigen.
   </div>
   </div>
-  <div class="skills">
-    Beeinflusste Fähigkeiten:
-    <div class="skill-item">Athletik</div>
-  </div>
 </ng-template>
 </ng-template>
 
 
 <ng-template #dexterityTemplate>
 <ng-template #dexterityTemplate>
-  <div class="attribute-name">Geschicklichkeit</div>
-  <div class="attribute-description">
+  <div class="details-title">Geschicklichkeit</div>
+  <div class="details-content">
     Geschicklichkeit repräsentiert die Beweglichkeit, Reflexe und allgemeine
     Geschicklichkeit repräsentiert die Beweglichkeit, Reflexe und allgemeine
     Körperbeherrschung deines Charakters. Ein hoher Geschicklichkeitswert deutet
     Körperbeherrschung deines Charakters. Ein hoher Geschicklichkeitswert deutet
     auf schnelle Reaktionen, geschickte Bewegungen und eine gute
     auf schnelle Reaktionen, geschickte Bewegungen und eine gute
     Hand-Auge-Koordination hin. Charaktere mit hoher Geschicklichkeit sind oft
     Hand-Auge-Koordination hin. Charaktere mit hoher Geschicklichkeit sind oft
     geschickte Diebe, Bogenschützen oder Akrobaten.
     geschickte Diebe, Bogenschützen oder Akrobaten.
   </div>
   </div>
-  Beeinflusste Fähigkeiten:
-  <div class="skills">
-    <div class="skill-item">Akrobatik</div>
-    <div class="skill-item">Fingerfertigkeit</div>
-    <div class="skill-item">Heimlichkeit</div>
-  </div>
 </ng-template>
 </ng-template>
 
 
 <ng-template #constitutionTemplate>
 <ng-template #constitutionTemplate>
-  <div class="attribute-name">Konstitution</div>
-  <div class="attribute-description">
+  <div class="details-title">Konstitution</div>
+  <div class="details-content">
     Konstitution steht für die Widerstandsfähigkeit, Gesundheit und Ausdauer
     Konstitution steht für die Widerstandsfähigkeit, Gesundheit und Ausdauer
     deines Charakters. Ein hoher Konstitutionswert bedeutet, dass dein Charakter
     deines Charakters. Ein hoher Konstitutionswert bedeutet, dass dein Charakter
     robust ist und gut mit physischem Stress umgehen kann. Charaktere mit hoher
     robust ist und gut mit physischem Stress umgehen kann. Charaktere mit hoher
@@ -117,45 +123,28 @@
 </ng-template>
 </ng-template>
 
 
 <ng-template #intelligenceTemplate>
 <ng-template #intelligenceTemplate>
-  <div class="attribute-name">Intelligenz</div>
-  <div class="attribute-description">
+  <div class="details-title">Intelligenz</div>
+  <div class="details-content">
     Intelligenz misst die geistige Schärfe, das logische Denkvermögen und die
     Intelligenz misst die geistige Schärfe, das logische Denkvermögen und die
     Lernfähigkeit deines Charakters. Ein hoher Intelligenzwert deutet auf eine
     Lernfähigkeit deines Charakters. Ein hoher Intelligenzwert deutet auf eine
     gute Allgemeinbildung, Wissensdurst und analytische Fähigkeiten hin.
     gute Allgemeinbildung, Wissensdurst und analytische Fähigkeiten hin.
     Charaktere mit hoher Intelligenz sind oft Magier, Forscher oder Strategen.
     Charaktere mit hoher Intelligenz sind oft Magier, Forscher oder Strategen.
   </div>
   </div>
-  Beeinflusste Fähigkeiten:
-  <div class="skills">
-    <div class="skill-item">Arkana</div>
-    <div class="skill-item">Geschichte</div>
-    <div class="skill-item">Nachforschung</div>
-    <div class="skill-item">Natur</div>
-    <div class="skill-item">Religion</div>
-  </div>
 </ng-template>
 </ng-template>
 
 
 <ng-template #wisdomTemplate>
 <ng-template #wisdomTemplate>
-  <div class="attribute-name">Weisheit</div>
-  <div class="attribute-description">
+  <div class="details-title">Weisheit</div>
+  <div class="details-content">
     Beschreibung: Weisheit repräsentiert die Wahrnehmung, Intuition und
     Beschreibung: Weisheit repräsentiert die Wahrnehmung, Intuition und
     emotionale Intelligenz deines Charakters. Ein hoher Weisheitswert deutet auf
     emotionale Intelligenz deines Charakters. Ein hoher Weisheitswert deutet auf
     eine gute Urteilsfähigkeit, Einsicht und innere Stärke hin. Charaktere mit
     eine gute Urteilsfähigkeit, Einsicht und innere Stärke hin. Charaktere mit
     hoher Weisheit sind oft Kleriker, Druiden oder Weise.
     hoher Weisheit sind oft Kleriker, Druiden oder Weise.
   </div>
   </div>
-  Beeinflusste Fähigkeiten:
-  <div class="skills">
-    <div class="skill-item">Tierkunde</div>
-    <div class="skill-item">Geschichte</div>
-    <div class="skill-item">Motiv erkennen</div>
-    <div class="skill-item">Heilkunde</div>
-    <div class="skill-item">Wahrnehmung</div>
-    <div class="skill-item">Überlebenskunst</div>
-  </div>
 </ng-template>
 </ng-template>
 
 
 <ng-template #charismaTemplate>
 <ng-template #charismaTemplate>
-  <div class="attribute-name">Charisma</div>
-  <div class="attribute-description">
+  <div class="details-title">Charisma</div>
+  <div class="details-content">
     Charisma spiegelt die Ausstrahlung, Überzeugungskraft und soziale
     Charisma spiegelt die Ausstrahlung, Überzeugungskraft und soziale
     Fähigkeiten deines Charakters wider. Ein hoher Charismawert bedeutet, dass
     Fähigkeiten deines Charakters wider. Ein hoher Charismawert bedeutet, dass
     dein Charakter charmant, einnehmend und überzeugend ist. Charaktere mit
     dein Charakter charmant, einnehmend und überzeugend ist. Charaktere mit
@@ -163,11 +152,4 @@
     Führungsaufgaben übernehmen. Charisma ist oft wichtig für Barden, Anführer
     Führungsaufgaben übernehmen. Charisma ist oft wichtig für Barden, Anführer
     oder Diplomaten.
     oder Diplomaten.
   </div>
   </div>
-  Beeinflusste Fähigkeiten:
-  <div class="skills">
-    <div class="skill-item">Täuschung</div>
-    <div class="skill-item">Einschütern</div>
-    <div class="skill-item">Auftreten</div>
-    <div class="skill-item">Überzeugen</div>
-  </div>
 </ng-template>
 </ng-template>

+ 32 - 4
src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.scss

@@ -1,18 +1,46 @@
+.attribute-container{
+    display: flex;
+    justify-content: space-around;
+    margin-top: 2rem;
+}
 
 
+.attribute-value{
+    width: 4rem;
+    height: 3rem;
+    font-size: 1.5rem;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin:auto;
+    border-radius: 10px;
+    background-color: white;
+    box-shadow: var(--shadow-small);
+}
 
 
-
+.attribute-label{
+    margin-top: 0.5rem;
+    font-weight: 500;
+}
 
 
 .skills{
 .skills{
     display: flex;
     display: flex;
-    gap: 0.5rem;
     flex-wrap: wrap;
     flex-wrap: wrap;
-    margin-left: 1rem;
-
+    gap: 0.5rem;
+    margin-top: 0.5rem;
 }
 }
 
 
 .skill-item{
 .skill-item{
     background-color: var(--primary-color);
     background-color: var(--primary-color);
     border-radius: 1rem;
     border-radius: 1rem;
+    font-weight: 500;
     padding: 0.25rem 0.5rem;
     padding: 0.25rem 0.5rem;
     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
     box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.75);
+}
+
+.modifier-table{
+    margin-top: 1.5rem;
+}
+
+td{
+    padding: .375rem 1rem
 }
 }

+ 21 - 0
src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component.ts

@@ -11,4 +11,25 @@ export class AttributeDetailsComponent {
   public constructor(public detailsService: DetailsService) {}
   public constructor(public detailsService: DetailsService) {}
   @Input() public attribute!: Attribute;
   @Input() public attribute!: Attribute;
   @Input() public modifier!: string;
   @Input() public modifier!: string;
+
+  public skillsTable: any = {
+    strength: ['Athletik'],
+    dexterity: ['Akrobatik', 'Fingerfertigkeit', 'Heimlichkeit'],
+    constitution: [],
+    intelligence: [
+      'Arkana',
+      'Geschichte',
+      'Nachforschung',
+      'Naturkunde',
+      'Religion',
+    ],
+    wisdom: [
+      'Tierkunde',
+      'Motiv erkennen',
+      'Heilkunde',
+      'Wahrnehmung',
+      'Überlebenskunde',
+    ],
+    charisma: ['Täuschung', 'Einschüchterung', 'Auftreten', 'Überzeugung'],
+  };
 }
 }

+ 2 - 1
src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-field.component.scss

@@ -1,9 +1,10 @@
 .attribute-box{
 .attribute-box{
     border: solid 1px black;
     border: solid 1px black;
     text-align: center;
     text-align: center;
+    cursor: pointer;
 
 
     .attribute-name{
     .attribute-name{
-        // font-size: 1.5rem;
+        cursor: pointer;
         font-weight: 600;
         font-weight: 600;
     }
     }
 
 

+ 1 - 2
src/app/journal/journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-field.component.ts

@@ -12,7 +12,7 @@ import { AttributeDetailsComponent } from './attribute-details/attribute-details
 })
 })
 export class AttributeFieldComponent {
 export class AttributeFieldComponent {
   @Input() attributeName: string = '';
   @Input() attributeName: string = '';
-  public attribute: Attribute = { name: '', value: 0 };
+  public attribute: Attribute = { name: '', value: 0, proficiency: false };
   public attributeModifier: string = '0';
   public attributeModifier: string = '0';
   public saveModifier: string = '0';
   public saveModifier: string = '0';
   public proficiencyBonus: number = 0;
   public proficiencyBonus: number = 0;
@@ -32,7 +32,6 @@ export class AttributeFieldComponent {
   ) {}
   ) {}
 
 
   ngOnInit(): void {
   ngOnInit(): void {
-    this.initProficiencySubscription();
     this.initAttributeSubscription();
     this.initAttributeSubscription();
   }
   }
 
 

+ 16 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.html

@@ -0,0 +1,16 @@
+<div class="details-title">{{ attributeName }}</div>
+<div class="save-subheading">Rettungswurf</div>
+
+<div class="details-content">
+  Ein Rettungswurf wird immer dann verlangt, wenn überprüft werden soll, ob ein
+  Spieler einem Angriff oder äußeren Einfluss widerstehen kann. Durch das
+  bestehen eines Rettungswurfes kann der Effekt verhindert, oder zumindest
+  abgeschwächt werden.
+</div>
+
+<div class="value-container">
+  <div class="save-value">
+    {{ saveModifier }}
+  </div>
+  <div class="save-label">Modifikator</div>
+</div>

+ 36 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.scss

@@ -0,0 +1,36 @@
+.save-subheading{
+    font-size: 1.25rem;
+    text-align: center;
+    font-weight: bold;
+}
+
+.value-container{
+    display: flex;
+    flex-direction: column;
+    margin-top: 2rem;
+}
+
+.save-value{
+    width: 3.5rem;
+    height: 3rem;
+    font-size: 1.5rem;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    margin:auto;
+    border-radius: 10px;
+    background-color: white;
+    box-shadow: var(--shadow-small);
+}
+
+.save-label{
+    margin-top: 0.5rem;
+    font-weight: 500;
+    text-align: center;
+}
+
+.save-calculation-heading{
+    font-size: 1.25rem;
+    font-weight: 500;
+}
+

+ 23 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.spec.ts

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

+ 11 - 0
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component.ts

@@ -0,0 +1,11 @@
+import { Component, Input } from '@angular/core';
+
+@Component({
+  selector: 'app-save-throw-details',
+  templateUrl: './save-throw-details.component.html',
+  styleUrl: './save-throw-details.component.scss',
+})
+export class SaveThrowDetailsComponent {
+  @Input() attributeName: string = '';
+  @Input() saveModifier: string = '0';
+}

+ 8 - 4
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.html

@@ -1,7 +1,11 @@
-<div class="save-throw-field">
-  <input class="save-throw-field__input" type="checkbox" />
+<div class="save-throw-field" (click)="openDetails()">
+  <input
+    class="save-throw-field__input"
+    type="checkbox"
+    [(ngModel)]="attribute.proficiency"
+  />
 
 
-  <div class="save-throw-field__name">{{ nameTranslator[attribute] }}</div>
+  <div class="save-throw-field__name">{{ nameTranslator[attributeName] }}</div>
 
 
-  <div class="save-throw-field__value">{{ modifier }}</div>
+  <div class="save-throw-field__value">{{ saveModifier }}</div>
 </div>
 </div>

+ 63 - 3
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component.ts

@@ -1,5 +1,9 @@
 import { Component, Input } from '@angular/core';
 import { Component, Input } from '@angular/core';
-import { FormControl } from '@angular/forms';
+import { DataService } from 'src/services/data/data.service';
+import { Observable } from 'rxjs';
+import { Attribute } from 'src/interfaces/attribute';
+import { DetailsService } from 'src/services/details/details.service';
+import { SaveThrowDetailsComponent } from '../save-throw-details/save-throw-details.component';
 
 
 @Component({
 @Component({
   selector: 'save-throw-field',
   selector: 'save-throw-field',
@@ -7,9 +11,18 @@ import { FormControl } from '@angular/forms';
   styleUrls: ['./save-throw-field.component.scss'],
   styleUrls: ['./save-throw-field.component.scss'],
 })
 })
 export class SaveThrowFieldComponent {
 export class SaveThrowFieldComponent {
-  @Input() attribute: string = '';
+  constructor(
+    public dataAccessor: DataService,
+    public detailsAccessor: DetailsService
+  ) {}
 
 
-  public modifier: string = '+5';
+  @Input() attributeName: string = '';
+
+  public attribute: Attribute = { name: '', value: 0, proficiency: false };
+
+  private proficiencyBonus: number = 0;
+  private attributeModifier: number = 0;
+  public saveModifier: string = '0';
 
 
   public nameTranslator: any = {
   public nameTranslator: any = {
     strength: 'Stärke',
     strength: 'Stärke',
@@ -19,4 +32,51 @@ export class SaveThrowFieldComponent {
     wisdom: 'Weisheit',
     wisdom: 'Weisheit',
     charisma: 'Charisma',
     charisma: 'Charisma',
   };
   };
+
+  public ngOnInit(): void {
+    this.initAttributeSubscription();
+    this.initProficiencySubscription();
+  }
+
+  private initAttributeSubscription(): void {
+    const observable: Observable<Attribute> = eval(
+      `this.dataAccessor.${this.attributeName}$`
+    );
+    observable.subscribe((newValue: Attribute) => {
+      this.attribute = newValue;
+      this.attributeModifier = this.calculateAttributeModifier();
+      this.saveModifier = this.calculateSaveModifier();
+    });
+  }
+
+  private initProficiencySubscription(): void {
+    this.dataAccessor.proficiency$.subscribe((newValue: any) => {
+      this.proficiencyBonus = newValue.value;
+      this.attributeModifier = this.calculateAttributeModifier();
+      this.saveModifier = this.calculateSaveModifier();
+    });
+  }
+
+  private calculateAttributeModifier(): number {
+    return Math.floor((this.attribute.value - 10) / 2);
+  }
+
+  public calculateSaveModifier(): string {
+    let mod = this.attributeModifier;
+    if (this.attribute.proficiency) {
+      mod += this.proficiencyBonus;
+    }
+    if (mod > 0) {
+      return '+' + mod;
+    } else {
+      return mod.toString();
+    }
+  }
+
+  public openDetails(): void {
+    this.detailsAccessor.openPanel(SaveThrowDetailsComponent, {
+      attributeName: this.nameTranslator[this.attributeName],
+      saveModifier: this.saveModifier,
+    });
+  }
 }
 }

+ 1 - 1
src/app/journal/journal-stats/attribute-skill-container/save-throw-panel/save-throw-panel.component.html

@@ -1,5 +1,5 @@
 <div class="save-throw-panel">
 <div class="save-throw-panel">
   <ng-container *ngFor="let attribute of attributes">
   <ng-container *ngFor="let attribute of attributes">
-    <save-throw-field [attribute]="attribute"></save-throw-field>
+    <save-throw-field [attributeName]="attribute"></save-throw-field>
   </ng-container>
   </ng-container>
 </div>
 </div>

+ 1 - 1
src/app/journal/journal-stats/attribute-skill-container/skill-panel/skill-field/skill-field.component.ts

@@ -12,7 +12,7 @@ import { Attribute } from 'src/interfaces/attribute';
 export class SkillFieldComponent {
 export class SkillFieldComponent {
   @Input() skillName: string = '';
   @Input() skillName: string = '';
   public skill: Skill = { name: '', proficiency: false };
   public skill: Skill = { name: '', proficiency: false };
-  private attribute: Attribute = { name: '', value: 0 };
+  private attribute: Attribute = { name: '', value: 0, proficiency: false };
   public skillModifier: string = '0';
   public skillModifier: string = '0';
   public skillProficiency: boolean = false;
   public skillProficiency: boolean = false;
   private proficiencyBonus: number = 0;
   private proficiencyBonus: number = 0;

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

@@ -57,6 +57,7 @@ import { SkillPanelComponent } from './journal-stats/attribute-skill-container/s
 import { SaveThrowPanelComponent } from './journal-stats/attribute-skill-container/save-throw-panel/save-throw-panel.component';
 import { SaveThrowPanelComponent } from './journal-stats/attribute-skill-container/save-throw-panel/save-throw-panel.component';
 import { SaveThrowFieldComponent } from './journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component';
 import { SaveThrowFieldComponent } from './journal-stats/attribute-skill-container/save-throw-panel/save-throw-field/save-throw-field.component';
 import { ProficiencyFieldComponent } from './journal-stats/info-row/proficiency/proficiency-field.component';
 import { ProficiencyFieldComponent } from './journal-stats/info-row/proficiency/proficiency-field.component';
+import { SaveThrowDetailsComponent } from './journal-stats/attribute-skill-container/save-throw-panel/save-throw-details/save-throw-details.component';
 
 
 @NgModule({
 @NgModule({
   declarations: [
   declarations: [
@@ -108,6 +109,7 @@ import { ProficiencyFieldComponent } from './journal-stats/info-row/proficiency/
     InfoRowComponent,
     InfoRowComponent,
     ConditionsComponent,
     ConditionsComponent,
     AttributeDetailsComponent,
     AttributeDetailsComponent,
+    SaveThrowDetailsComponent,
   ],
   ],
   imports: [
   imports: [
     CommonModule,
     CommonModule,

+ 1 - 1
src/interfaces/attribute.ts

@@ -1,5 +1,5 @@
 export interface Attribute {
 export interface Attribute {
   name: string;
   name: string;
   value: number;
   value: number;
-  proficiency?: boolean;
+  proficiency: boolean;
 }
 }

+ 5 - 1
src/styles.scss

@@ -122,9 +122,13 @@ $dialog-position-right: 20%;
     margin-top: 1.5rem;
     margin-top: 1.5rem;
 }
 }
 
 
+.details-bold{
+    font-weight: 500;
+}
+
 .details-content{
 .details-content{
     font-size: 1rem;
     font-size: 1rem;
-    margin-top: .5rem;
+    margin-top: 1.5rem;
     font-weight: 400;
     font-weight: 400;
 }
 }