Bladeren bron

feat: Reworked inventory, made it full screen, implemented weight and optimized money.

Warafear 1 jaar geleden
bovenliggende
commit
12a34f63f0

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

@@ -463184,3 +463184,40 @@ To fix this, set a unique name for each project in a project.json inside the pro
     at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
 [NX Daemon Server] - 2024-01-23T06:51:42.908Z - Time taken for 'hash changed files from watcher' 507.5174999999581ms
 [NX Daemon Server] - 2024-01-23T06:51:42.908Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-23T20:35:10.845Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-23T20:35:10.848Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-23T20:35:10.851Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-23T20:35:10.853Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-23T20:35:10.853Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-23T20:35:10.856Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-23T20:35:11.443Z - 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] - 2024-01-23T20:35:11.443Z - [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:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:97:15)
+    at buildProjectsConfigurationsFromProjectPathsAndPlugins (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\project-configuration-utils.js:70:19)
+    at createProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:131:129)
+    at WorkspaceContext.<anonymous> (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:82:39)
+    at getProjectConfigurationsFromContext (c:\Softwareprojekte\DnD\node_modules\nx\src\utils\workspace-context.js:26:29)
+    at _retrieveProjectConfigurations (c:\Softwareprojekte\DnD\node_modules\nx\src\project-graph\utils\retrieve-workspace-files.js:81:72)
+    at retrieveProjectConfigurations (c:\Softwareprojekte\DnD\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:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:102:34)
+    at async processFilesAndCreateAndSerializeProjectGraph (c:\Softwareprojekte\DnD\node_modules\nx\src\daemon\server\project-graph-incremental-recomputation.js:138:17)
+[NX Daemon Server] - 2024-01-23T20:35:11.445Z - Time taken for 'hash changed files from watcher' 24.491800002753735ms
+[NX Daemon Server] - 2024-01-23T20:35:11.445Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-01-23T20:35:11.446Z - Done responding to the client null

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

@@ -1 +1 @@
-{"processId":13264}
+{"processId":10464}

+ 0 - 1
src/app/character/character-creator/character-creator.component.ts

@@ -330,7 +330,6 @@ export class CharacterCreatorComponent {
         {
           platinum: 0,
           gold: 0,
-          electrum: 0,
           silver: 0,
           copper: 0,
         },

+ 4 - 7
src/app/journal/journal-character/journal-character.component.scss

@@ -29,6 +29,7 @@
         }
         input[type="number"] {
             -moz-appearance: textfield;
+            appearance: textfield;
         }
     }
 
@@ -73,14 +74,10 @@
             font-weight: 600;
             color: var(--text);
 
+            &.active,
             &:hover {
-                background-color: var(--button-color-hover);
-                box-shadow: var(--shadow-hover);
-            }
-
-            &.active {
-                background-color: var(--button-color-hover);
-                box-shadow: var(--shadow-hover);
+                background-color: var(--tab-active);
+                box-shadow: var(--shadow);
             }
         }
     }

+ 1 - 1
src/app/journal/journal-home/navigation-panel/navigation-panel.component.html

@@ -55,7 +55,7 @@
     <li>
       <div
         class="navigation-entry"
-        [class]="active === 3 ? 'active' : ''"
+        [class]="active === 6 ? 'active' : ''"
         (click)="setActiveProperty(6)"
         [routerLink]="'./spellbook'"
       >

+ 48 - 1
src/app/journal/journal-home/navigation-panel/navigation-panel.component.ts

@@ -1,4 +1,5 @@
 import { Component, ViewChild } from '@angular/core';
+import { Router } from '@angular/router';
 import { NavigationPanelService } from 'src/services/navigationPanel/navigation-panel.service';
 
 @Component({
@@ -11,7 +12,10 @@ export class NavigationPanelComponent {
   @ViewChild('navigationPanel') panel: any;
   public active: number = 1;
 
-  constructor(private navigation: NavigationPanelService) {}
+  constructor(
+    private navigation: NavigationPanelService,
+    private router: Router
+  ) {}
 
   public ngOnInit(): void {
     this.navigation.showNavigationPanel$.subscribe((state) => {
@@ -21,6 +25,7 @@ export class NavigationPanelComponent {
         this.closePanel();
       }
     });
+    this.checkForActiveTab();
   }
 
   public openPanel(): void {
@@ -33,6 +38,48 @@ export class NavigationPanelComponent {
     this.panel?.nativeElement.classList.remove('panel--open');
   }
 
+  private checkForActiveTab(): void {
+    const tab = this.router.url.split('/')[2];
+    switch (tab) {
+      case 'stats':
+        this.active = 1;
+        break;
+      case 'character':
+        this.active = 2;
+        break;
+      case 'inventory':
+        this.active = 3;
+        break;
+      case 'spellcards':
+        this.active = 4;
+        break;
+      case 'notes':
+        this.active = 5;
+        break;
+      case 'spellbook':
+        this.active = 6;
+        break;
+      case 'quests':
+        this.active = 7;
+        break;
+      case 'npcs':
+        this.active = 8;
+        break;
+      case 'places':
+        this.active = 9;
+        break;
+      case 'maps':
+        this.active = 10;
+        break;
+      case 'ruleset':
+        this.active = 11;
+        break;
+      default:
+        this.active = 1;
+        break;
+    }
+  }
+
   public setActiveProperty(number: number) {
     this.active = number;
   }

+ 138 - 95
src/app/journal/journal-inventory/journal-inventory.component.html

@@ -1,4 +1,5 @@
 <div class="inventory-container">
+  <!-- ITEMS -->
   <div class="item-container">
     <div class="tab-row">
       <button
@@ -12,13 +13,6 @@
         class="tab-button"
         (click)="active = 2"
         [class]="active === 2 ? 'active' : ''"
-      >
-        Verbrauchsgegenstände
-      </button>
-      <button
-        class="tab-button"
-        (click)="active = 3"
-        [class]="active === 3 ? 'active' : ''"
       >
         Sonstiges
       </button>
@@ -34,106 +28,155 @@
     @switch(active) { @case(1){
     <ng-container [ngTemplateOutlet]="weaponTemplate"></ng-container>
     } @case(2){
-    <ng-container [ngTemplateOutlet]="consumablesTemplate"></ng-container>
-    } @case(3){
     <ng-container [ngTemplateOutlet]="miscTemplate"></ng-container>
     }}
-    <ui-button
-      [type]="'add'"
-      [size]="'xlarge'"
-      [color]="'primary'"
-      class="button-margin"
-      (click)="addItem()"
-    ></ui-button>
+    <!-- TODO: Überarbeiten -->
+
+    <div class="button-container">
+      <button class="add-button" (click)="addItem('items')">
+        Eintrag hinzufügen
+      </button>
+    </div>
   </div>
+  <div class="right-column">
+    <!-- FOOD -->
 
-  <div class="money-container" (change)="updateMoney()">
-    <div class="money-title">Münzen</div>
-    <div class="money-row">
-      <div class="money-label">Platin</div>
-      <div class="money-box">
-        <input class="money-input" type="number" [(ngModel)]="money.platinum" />
+    <div class="food-container">
+      <div class="tab-row">
+        <button
+          class="tab-button"
+          (click)="foodActive = 1"
+          [class]="foodActive === 1 ? 'active' : ''"
+        >
+          Nahrung
+        </button>
+        <button
+          class="tab-button"
+          (click)="foodActive = 2"
+          [class]="foodActive === 2 ? 'active' : ''"
+        >
+          Verbrauchsgegenstände
+        </button>
+      </div>
+      <div class="heading-row">
+        <div class="heading">Name</div>
+        <div class="heading">Fertig</div>
+        <div class="heading">Gewicht</div>
+        <div class="heading">Anzahl</div>
+      </div>
+      @switch(foodActive) { @case(1){
+      <ng-container [ngTemplateOutlet]="foodTemplate"></ng-container>
+      } @case(2){
+      <ng-container [ngTemplateOutlet]="consumablesTemplate"></ng-container>
+      } }
+      <!-- <div
+        cdkDropList
+        class="item-list table-content"
+        (cdkDropListDropped)="drop($event, food, 'food')"
+      >
+        @for (item of food; let index = $index; track item) {
+        <div class="item" cdkDrag (click)="openFoodDetails(index)">
+          <div class="item-property">{{ item.name }}</div>
+          <div class="item-property">@if(item.isReady){Ja} @else {Nein}</div>
+          <div class="item-property">{{ item.weight }} lb.</div>
+          <div class="item-property">{{ item.quantity }}</div>
+        </div>
+        } @empty {
+        <div class="empty-list">Kein Eintrag</div>
+        }
+      </div>-->
+      <div class="button-container">
+        <button class="add-button" (click)="addItem('consumables')">
+          Eintrag hinzufügen
+        </button>
       </div>
     </div>
 
-    <div class="money-row">
-      <div class="money-label">Gold</div>
+    <!-- MONEY -->
+    <div class="money-container" (change)="updateMoney()">
       <div class="money-box">
-        <input class="money-input" type="number" [(ngModel)]="money.gold" />
+        <div class="money-input-box">
+          <img src="assets/icons/UIIcons/platinum.svg" class="money-icon" />
+          <input
+            class="money-input"
+            type="number"
+            [(ngModel)]="money.platinum"
+          />
+        </div>
       </div>
-    </div>
-
-    <div class="money-row">
-      <div class="money-label">Elektrum</div>
       <div class="money-box">
-        <input class="money-input" type="number" [(ngModel)]="money.electrum" />
+        <div class="money-input-box">
+          <img src="assets/icons/UIIcons/gold.svg" class="money-icon" />
+          <input class="money-input" type="number" [(ngModel)]="money.gold" />
+        </div>
       </div>
-    </div>
-
-    <div class="money-row">
-      <div class="money-label">Silber</div>
       <div class="money-box">
-        <input class="money-input" type="number" [(ngModel)]="money.silver" />
+        <div class="money-input-box">
+          <img src="assets/icons/UIIcons/silver.svg" class="money-icon" />
+          <input class="money-input" type="number" [(ngModel)]="money.silver" />
+        </div>
       </div>
-    </div>
-
-    <div class="money-row">
-      <div class="money-label">Kupfer</div>
       <div class="money-box">
-        <input class="money-input" type="number" [(ngModel)]="money.copper" />
+        <div class="money-input-box">
+          <img src="assets/icons/UIIcons/copper.svg" class="money-icon" />
+          <input class="money-input" type="number" [(ngModel)]="money.copper" />
+        </div>
       </div>
     </div>
-  </div>
 
-  <!-- FOOD -->
-  <div class="food-container">
-    <div class="heading-row">
-      <div class="heading">Name</div>
-      <div class="heading">Fertig</div>
-      <div class="heading">Gewicht</div>
-      <div class="heading">Anzahl</div>
+    <!-- WEIGHT -->
+    <div class="weight-container">
+      <div style="font-size: 1.5rem; font-weight: bold">Gesamtlast:</div>
+      <div class="weight-box">{{ totalWeight }} / {{ maximumWeight }} lb.</div>
     </div>
-    <div
-      cdkDropList
-      class="example-list table-content"
-      (cdkDropListDropped)="drop($event, food, 'food')"
-    >
-      @for (item of food; let index = $index; track item) {
-      <div class="example-box" cdkDrag (click)="openFoodDetails(index)">
-        <div class="item">{{ item.name }}</div>
-        <div class="item">@if(item.isReady){Ja} @else {Nein}</div>
-        <div class="item">{{ item.weight }} Kg.</div>
-        <div class="item">{{ item.quantity }}</div>
-      </div>
-      }
-    </div>
-    <ui-button
-      style="margin: 1rem"
-      [type]="'add'"
-      [size]="'xlarge'"
-      [color]="'primary'"
-      (click)="openFoodModal(false)"
-    ></ui-button>
   </div>
 
+  <!-- TEMPLATES -->
+
   <!-- WEAPONS -->
   <ng-template #weaponTemplate>
     <div
       cdkDropList
-      class="example-list table-content"
+      class="item-list table-content"
       (cdkDropListDropped)="drop($event, weaponsAndArmor, 'weaponsAndArmor')"
     >
       @for (item of weaponsAndArmor; let index = $index; track item) {
       <div
-        class="example-box"
+        class="item"
         cdkDrag
         (click)="openItemsDetails(weaponsAndArmor, index, 'weaponsAndArmor')"
       >
-        <div class="item">{{ item.name }}</div>
-        <div class="item">{{ item.value }} Gold</div>
-        <div class="item">{{ item.weight }} Kg.</div>
-        <div class="item">{{ item.quantity }}</div>
+        <div class="item-property">{{ item.name }}</div>
+        <div class="item-property">{{ item.value }} Gold</div>
+        <div class="item-property">{{ item.weight }} lb.</div>
+        <div class="item-property">{{ item.quantity }}</div>
       </div>
+      } @empty {
+      <div class="empty-list">Kein Eintrag</div>
+      }
+    </div>
+  </ng-template>
+
+  <!-- MISCELLANEOUS -->
+  <ng-template #miscTemplate>
+    <div
+      cdkDropList
+      class="item-list table-content"
+      (cdkDropListDropped)="drop($event, miscellaneous, 'miscellaneous')"
+    >
+      @for (item of miscellaneous; let index = $index; track item) {
+      <div
+        class="item"
+        cdkDrag
+        (click)="openItemsDetails(miscellaneous, index, 'miscellaneous')"
+      >
+        <div class="item-property">{{ item.name }}</div>
+        <div class="item-property">{{ item.value }} Gold</div>
+        <div class="item-property">{{ item.weight }} lb.</div>
+        <div class="item-property">{{ item.quantity }}</div>
+      </div>
+      } @empty {
+      <div class="empty-list">Kein Eintrag</div>
       }
     </div>
   </ng-template>
@@ -142,42 +185,42 @@
   <ng-template #consumablesTemplate>
     <div
       cdkDropList
-      class="example-list table-content"
+      class="item-list table-content"
       (cdkDropListDropped)="drop($event, consumables, 'consumables')"
     >
       @for (item of consumables; let index = $index; track item) {
       <div
-        class="example-box"
+        class="item"
         cdkDrag
         (click)="openItemsDetails(consumables, index, 'consumables')"
       >
-        <div class="item">{{ item.name }}</div>
-        <div class="item">{{ item.value }} Gold</div>
-        <div class="item">{{ item.weight }} Kg.</div>
-        <div class="item">{{ item.quantity }}</div>
+        <div class="item-property">{{ item.name }}</div>
+        <div class="item-property">{{ item.value }} Gold</div>
+        <div class="item-property">{{ item.weight }} lb.</div>
+        <div class="item-property">{{ item.quantity }}</div>
       </div>
+      } @empty {
+      <div class="empty-list">Kein Eintrag</div>
       }
     </div>
   </ng-template>
 
-  <!-- MISCELLANEOUS -->
-  <ng-template #miscTemplate>
+  <!-- FOOD -->
+  <ng-template #foodTemplate>
     <div
       cdkDropList
-      class="example-list table-content"
-      (cdkDropListDropped)="drop($event, miscellaneous, 'miscellaneous')"
+      class="item-list table-content"
+      (cdkDropListDropped)="drop($event, food, 'food')"
     >
-      @for (item of miscellaneous; let index = $index; track item) {
-      <div
-        class="example-box"
-        cdkDrag
-        (click)="openItemsDetails(miscellaneous, index, 'miscellaneous')"
-      >
-        <div class="item">{{ item.name }}</div>
-        <div class="item">{{ item.value }} Gold</div>
-        <div class="item">{{ item.weight }} Kg.</div>
-        <div class="item">{{ item.quantity }}</div>
+      @for (item of food; let index = $index; track item) {
+      <div class="item" cdkDrag (click)="openFoodDetails(index)">
+        <div class="item-property">{{ item.name }}</div>
+        <div class="item-property">@if(item.isReady){Ja} @else {Nein}</div>
+        <div class="item-property">{{ item.weight }} lb.</div>
+        <div class="item-property">{{ item.quantity }}</div>
       </div>
+      } @empty {
+      <div class="empty-list">Kein Eintrag</div>
       }
     </div>
   </ng-template>

+ 244 - 159
src/app/journal/journal-inventory/journal-inventory.component.scss

@@ -1,207 +1,297 @@
-.inventory-container{
-    width: 90vw;
-    height: 85vh;
-    margin: 3rem auto;
-    display: grid;
-    grid-template-rows: repeat(10, 1fr);
-    grid-template-columns: repeat(10, 1fr);
+.inventory-container {
+  width: 100%;
+  height: 100%;
+  padding: 2rem;
+  display: flex;
+  justify-content: space-between;
 }
 
 // Tabbar
-.tab-row{
-    display: flex;
-    flex: 0 0 3rem;
-    > *{
-        flex: 1 1 0;
-    }
-    > :first-child{
-      border-radius: 10px 0 0 0
-    }
-    > :last-child{
-      border-radius: 0 10px 0 0
-    }
+.tab-row {
+  display: flex;
+  flex: 0 0 3rem;
+  > * {
+    flex: 1 1 0;
+  }
+  > :first-child {
+    border-radius: 10px 0 0 0;
+  }
+  > :last-child {
+    border-radius: 0 10px 0 0;
+  }
 }
 
-.tab-button{
-    height: 2.25rem;
-    font-size: 1.375rem;
-    font-weight: 600;
-    color: black;
-    border: solid 1px var(--border-color);
-    transition: all 0.25s ease-in-out;
-    background-color: var(--primary-color-light);
-
-    &.active{
-        height: 2.75rem;
-        background-color: var(--primary-color);
-    }
+.tab-button {
+  height: 3rem;
+  font-size: 1.375rem;
+  font-weight: 600;
+  color: black;
+  border: solid 1px var(--border-color);
+  transition: all 0.25s ease-in-out;
+  background-color: var(--tab);
+
+  &.active {
+    border-bottom: 3px solid var(--border-color);
+    background-color: var(--tab-active);
+  }
 }
 
 // Item container
-.item-container{
-    grid-area: 1 / 1 / 11 / 7;
-    border: 1px solid var(--border-color);
-    border-radius: 10px;
-    display: flex;
-    flex-direction: column;
-    background-color: var(--field-background-color);
-    box-shadow: var(--shadow-small);
+.item-container {
+  width: 60%;
+  height: 100%;
+  border: 1px solid var(--border-color);
+  border-radius: 10px;
+  display: flex;
+  flex-direction: column;
+  background-color: var(--field-background-color);
+  box-shadow: var(--shadow-small);
+
+  .heading-row {
+    flex: 0 0 3rem;
+    display: grid;
+    grid-template-columns: 2fr 1fr 1fr 1fr;
+    padding: 10px 20px;
+    border-bottom: 1px solid var(--border-color);
+    box-shadow: var(--shadow);
+  }
+
+  .table-content {
+    overflow: auto;
+    padding-top: 1rem;
+    flex: 0 0 calc(100% - 11rem);
+  }
+
+  .button-margin {
+    margin: 1rem 0rem;
+  }
+
+  .heading {
+    font-size: 1.5rem;
+    font-weight: 600;
+    padding-left: 2rem;
+  }
 
-    .heading-row{
-      flex: 0 0 3rem;
-      display: grid;
-      grid-template-columns: 2fr 1fr 1fr 1fr;
-      padding: 0 10px;;
+  .item {
+    padding: 10px 10px;
+    margin: 0 0.5rem;
+    display: grid;
+    grid-template-columns: 2fr 1fr 1fr 1fr;
+    align-items: center;
+    box-sizing: border-box;
+    cursor: move;
+    background-color: var(--items);
+    border-radius: 10px;
+    box-shadow: var(--shadow);
+    transition: all 0.2s ease-in-out;
+    &:hover {
+      background-color: var(--items-hover);
     }
+  }
 
-    .table-content{
-      overflow: auto;
-      flex: 0 0 calc(100% - 11rem);
-    }
+  .item-property {
+    font-size: 1.25rem;
+    font-weight: 600;
+    padding-left: 2rem;
+  }
+}
 
-    .button-margin{
-      margin: 1rem 0rem;
-    }
+.right-column {
+  width: 35%;
+  display: flex;
+  flex-direction: column;
+  gap: 2rem;
+}
 
-    .heading{
-      font-size: 1.5rem;
-      font-weight: 600;
-      padding-left: 2rem;
-    }
+// Food Container
 
+.food-container {
+  height: calc(100% - 16rem);
+  width: 100%;
+  border: 1px solid var(--border-color);
+  border-radius: 10px;
+  display: flex;
+  flex-direction: column;
+  background-color: var(--field-background-color);
+  box-shadow: var(--shadow-small);
+
+  .heading-row {
+    flex: 0 0 3rem;
+    display: grid;
+    grid-template-columns: 2fr 1.5fr 1.5fr 1.5fr;
+    padding: 10px 10px;
+    border-bottom: 1px solid var(--border-color);
+    box-shadow: var(--shadow);
+  }
 
-    .item{
-      font-size: 1.25rem;
-      font-weight: 600;
-      padding-left: 2rem;
+  .heading {
+    font-size: 1.375rem;
+    font-weight: 600;
+    padding-left: 1rem;
+  }
+
+  .table-content {
+    overflow: auto;
+    padding-top: 1rem;
+    flex: 0 0 calc(100% - 11rem);
+  }
+
+  .item {
+    grid-template-columns: 2fr 1.5fr 1.5fr 1.5fr;
+    padding: 10px 10px;
+    margin: 0 0.5rem;
+    display: grid;
+    align-items: center;
+    box-sizing: border-box;
+    cursor: move;
+    background-color: var(--items);
+    border-radius: 10px;
+    box-shadow: var(--shadow);
+    transition: all 0.2s ease-in-out;
+    &:hover {
+      background-color: var(--items-hover);
     }
+  }
+
+  .item-property {
+    font-size: 1.25rem;
+    font-weight: 600;
+    padding-left: 1rem;
+  }
 }
 
 //  MONEY CONTAINER
 
-.money-container{
-    grid-area: 1 / 8 / 5 / 11;
-     border: 1px solid var(--border-color);
+.money-container {
+  display: flex;
+  justify-content: space-evenly;
+  align-items: center;
+  height: 6rem;
+  width: 100%;
+  border: 1px solid var(--border-color);
+  border-radius: 10px;
+  background-color: var(--field-background-color);
+  box-shadow: var(--shadow);
+
+  .money-box {
+    width: 6rem;
+    height: 3rem;
+  }
+
+  .money-input-box {
+    width: 6rem;
+    height: 3rem;
+    font-size: 1.5rem;
+    position: relative;
     border-radius: 10px;
-    background-color: var(--field-background-color);
+    background-color: white;
     box-shadow: var(--shadow-small);
-}
+  }
 
-.money-title{
-  font-size: 1.75rem;
-  font-weight: 700;
-  text-align: center;
-  margin: 1rem 0;
-}
+  .money-icon {
+    position: absolute;
+    width: 3rem;
+    height: 3rem;
+    left: 0.25rem;
+  }
 
-.money-row{
-  display:flex;
-}
+  .money-input {
+    border: none;
+    outline: none;
+    width: 100%;
+    height: 100%;
+    text-align: right;
+    padding-right: 1rem;
+    background-color: transparent;
 
-.money-label{
-  flex: 0 0 8rem;
-  font-size: 1.25rem;
-  font-weight: 600;
-  padding: 0.5rem;
+    &::-webkit-outer-spin-button,
+    &::-webkit-inner-spin-button {
+      -webkit-appearance: none;
+      appearance: none;
+      margin: 0;
+    }
+  }
 }
 
-.money-box{
-  flex: 0 0 3rem;
-  width: 3.5rem;
-    height: 2rem;
+// WEIGHT
+.weight-container {
+  height: 6rem;
+  width: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 2rem;
+  border: 1px solid var(--border-color);
+  border-radius: 10px;
+  background-color: var(--field-background-color);
+  box-shadow: var(--shadow);
+
+  .weight-box {
+    width: 10rem;
+    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);
+  }
 }
 
-.money-input{
-  border: none;
-    outline: none;
-    text-align: center;
-    background-color: transparent;
-
-    &::-webkit-outer-spin-button,
-    &::-webkit-inner-spin-button {
-        -webkit-appearance: none;
-        appearance: none;
-        margin: 0;
-    }   
+// SHARED
+.empty-list {
+  text-align: center;
+  margin: 5rem auto;
+  font-size: 1.5rem;
+  font-weight: 600;
 }
 
-// Food Container
-
-.food-container{
-    grid-area: 6 / 8 / 11 / 11;
-    border: 1px solid var(--border-color);
-    border-radius: 10px;
-    display: flex;
-    flex-direction: column;
-    background-color: var(--field-background-color);
-    box-shadow: var(--shadow-small);
-
-    .heading-row{
-      flex: 0 0 3rem;
-      display: grid;
-      grid-template-columns: 2fr 1.5fr 1.5fr 1.5fr;
-      padding: 0 10px;;
-    }
-
-    .heading{
-      font-size: 1.375rem;
-      font-weight: 600;
-      padding-left: 1rem;
-    }
-
-    .table-content{
-      overflow: auto;
-      flex: 0 0 calc(100% - 8rem);
-    }
-
-    .example-box {
-      grid-template-columns: 2fr 1.5fr 1.5fr 1.5fr;
-    }
-
-    .item{
-      font-size: 1.25rem;
-      font-weight: 600;
-      padding-left: 1rem;
-    }
+.button-container {
+  height: 5rem;
+  display: flex;
+  justify-content: center;
+  align-items: center;
 }
 
+.add-button {
+  width: 18rem;
+  height: 3rem;
+  font-size: 1.25rem;
+  font-weight: 600;
+  border-radius: 10px;
+  border: var(--border-color);
+  background-color: var(--accept);
+  box-shadow: var(--shadow);
+  transition: all 0.25s ease-in-out;
+  &:hover {
+    background-color: var(--accept-hover);
+  }
+}
 // Drag and Drop
-.example-list {
+.item-list {
   max-width: 100%;
-  border: solid 1px #ccc;
   min-height: 60px;
-  display: block;
-  background: white;
-  border-radius: 4px;
-  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  gap: 0.75rem;
+  overflow: auto;
 }
 
-.example-box {
+.cdk-drag-preview {
   padding: 10px 10px;
-  border-bottom: solid 1px #ccc;
-  color: rgba(0, 0, 0, 0.87);
+  margin: 0 0.5rem;
   display: grid;
   grid-template-columns: 2fr 1fr 1fr 1fr;
   align-items: center;
   box-sizing: border-box;
   cursor: move;
-  background: white;
-}
-
-.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);
+  background-color: var(--background-color);
+  border-radius: 10px;
+  box-shadow: var(--shadow);
+  font-size: 1.25rem;
+  font-weight: 600;
+  padding-left: 2.625rem;
 }
 
 .cdk-drag-placeholder {
@@ -212,11 +302,6 @@
   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) {
+.item-list.cdk-drop-list-dragging .item:not(.cdk-drag-placeholder) {
   transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
 }
-

+ 81 - 19
src/app/journal/journal-inventory/journal-inventory.component.ts

@@ -20,19 +20,38 @@ import { FoodDetailsComponent } from './food-details/food-details.component';
   styleUrls: ['./journal-inventory.component.scss'],
 })
 export class JournalInventoryComponent {
-  constructor(
-    private detailsAccessor: DetailsService,
-    private dataAccessor: DataService,
-    private modalAccessor: ModalService
-  ) {}
-
   public active: number = 1;
+  public foodActive: number = 1;
 
   public weaponsAndArmor: SimpleItem[] = [];
   public consumables: SimpleItem[] = [];
   public miscellaneous: SimpleItem[] = [];
   public money: any = {};
   public food: Food[] = [];
+  public totalWeight: number = 0;
+  public maximumWeight: number = 0;
+  private strength: number = 0;
+  private weightModifier: number = 15;
+
+  private speciesWeightModifierTable: any = {
+    Dwarf: 15,
+    Elf: 15,
+    Eladrin: 15,
+    HalfElf: 15,
+    HalfElfDetection: 15,
+    HalfOrc: 15,
+    Human: 15,
+    Halfling: 7.5,
+    Gnome: 7.5,
+    Orc: 15,
+    Tiefling: 15,
+  };
+
+  constructor(
+    private detailsAccessor: DetailsService,
+    private dataAccessor: DataService,
+    private modalAccessor: ModalService
+  ) {}
 
   public ngOnInit(): void {
     this.weaponsAndArmor = this.dataAccessor.weaponsAndArmor;
@@ -40,6 +59,13 @@ export class JournalInventoryComponent {
     this.miscellaneous = this.dataAccessor.miscellaneous;
     this.food = this.dataAccessor.food;
     this.money = this.dataAccessor.money;
+    this.updateWeight();
+    this.weightModifier =
+      this.speciesWeightModifierTable[this.dataAccessor.characterData.race];
+    this.dataAccessor.strength$.subscribe((strength) => {
+      this.strength = strength.value;
+      this.maximumWeight = this.strength * this.weightModifier;
+    });
   }
 
   drop(event: CdkDragDrop<string[]>, list: any[], listName: string) {
@@ -149,19 +175,29 @@ export class JournalInventoryComponent {
     );
   }
 
-  public addItem(): void {
-    switch (this.active) {
-      case 1:
-        this.openItemModal(false, 'weaponsAndArmor', this.weaponsAndArmor);
-        break;
-      case 2:
-        this.openItemModal(false, 'consumables', this.consumables);
-        break;
-      case 3:
-        this.openItemModal(false, 'miscellaneous', this.miscellaneous);
-        break;
-      default:
-        throw new Error('Unknown active tab: ' + this.active);
+  public addItem(table: string): void {
+    if (table === 'items') {
+      switch (this.active) {
+        case 1:
+          this.openItemModal(false, 'weaponsAndArmor', this.weaponsAndArmor);
+          break;
+        case 2:
+          this.openItemModal(false, 'miscellaneous', this.miscellaneous);
+          break;
+        default:
+          throw new Error('Unknown active tab: ' + this.active);
+      }
+    } else if (table === 'consumables') {
+      switch (this.foodActive) {
+        case 1:
+          this.openFoodModal(false);
+          break;
+        case 2:
+          this.openItemModal(false, 'consumables', this.consumables);
+          break;
+        default:
+          throw new Error('Unknown food active tab: ' + this.foodActive);
+      }
     }
   }
 
@@ -177,13 +213,39 @@ export class JournalInventoryComponent {
     } else {
       throw new Error('DND-ERROR: Unknown list name: ' + listname);
     }
+    this.updateWeight();
   }
 
   public updateMoney(): void {
     this.dataAccessor.money = this.money;
+    this.updateWeight();
   }
 
   public updateFood(): void {
     this.dataAccessor.food = this.food;
+    this.updateWeight();
+  }
+
+  private updateWeight(): void {
+    let totalWeight = 0;
+    this.weaponsAndArmor.forEach((item) => {
+      totalWeight += item.weight * item.quantity;
+    });
+    this.consumables.forEach((item) => {
+      totalWeight += item.weight * item.quantity;
+    });
+    this.miscellaneous.forEach((item) => {
+      totalWeight += item.weight * item.quantity;
+    });
+    this.food.forEach((item) => {
+      totalWeight += item.weight * item.quantity;
+    });
+    const numberOfCoins =
+      this.money.copper +
+      this.money.silver +
+      this.money.gold +
+      this.money.platinum;
+    totalWeight += Math.floor(numberOfCoins / 50);
+    this.totalWeight = totalWeight;
   }
 }

+ 1 - 0
src/assets/icons/UIIcons/copper.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8 10.07 19.3 35.53 30.4 71.22 30.4 35.69.1 80.29-11.2 124.19-34 44-22.9 78.8-53 99.2-82.2 20.5-29.2 25.9-56.4 15.9-75.8-10.1-19.3-35.5-30.49-71.2-30.49zm91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3-22.6 32.3-59.5 63.8-105.7 87.8-46.2 24.1-93.1 36.2-132.5 36.2-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5 35.7 0 80.3-11.2 124.2-34.1 44-22.8 78.8-52.9 99.2-82.2 20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7-18.9 27.1-47.8 53.4-83.6 75.4 11.1 1.2 22.7 1.8 34.5 1.8 49.5 0 94.3-10.6 125.9-27.1 31.7-16.5 49.1-38.1 49.1-59.9 0-21.8-17.4-43.4-49.1-59.9-16.1-8.4-35.7-15.3-57.6-20zm106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31-35 18.2-82.2 29.1-134.3 29.1-21.2 0-41.6-1.8-60.7-5.2-23.2 11.7-46.5 20.4-68.9 26.1 1.2.7 2.4 1.3 3.7 2 31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z" fill="#b87333" fill-opacity="1"></path></g></svg>

+ 1 - 0
src/assets/icons/UIIcons/gold.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8 10.07 19.3 35.53 30.4 71.22 30.4 35.69.1 80.29-11.2 124.19-34 44-22.9 78.8-53 99.2-82.2 20.5-29.2 25.9-56.4 15.9-75.8-10.1-19.3-35.5-30.49-71.2-30.49zm91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3-22.6 32.3-59.5 63.8-105.7 87.8-46.2 24.1-93.1 36.2-132.5 36.2-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5 35.7 0 80.3-11.2 124.2-34.1 44-22.8 78.8-52.9 99.2-82.2 20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7-18.9 27.1-47.8 53.4-83.6 75.4 11.1 1.2 22.7 1.8 34.5 1.8 49.5 0 94.3-10.6 125.9-27.1 31.7-16.5 49.1-38.1 49.1-59.9 0-21.8-17.4-43.4-49.1-59.9-16.1-8.4-35.7-15.3-57.6-20zm106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31-35 18.2-82.2 29.1-134.3 29.1-21.2 0-41.6-1.8-60.7-5.2-23.2 11.7-46.5 20.4-68.9 26.1 1.2.7 2.4 1.3 3.7 2 31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z" fill="#e3c203" fill-opacity="1"></path></g></svg>

+ 1 - 0
src/assets/icons/UIIcons/platinum.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8 10.07 19.3 35.53 30.4 71.22 30.4 35.69.1 80.29-11.2 124.19-34 44-22.9 78.8-53 99.2-82.2 20.5-29.2 25.9-56.4 15.9-75.8-10.1-19.3-35.5-30.49-71.2-30.49zm91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3-22.6 32.3-59.5 63.8-105.7 87.8-46.2 24.1-93.1 36.2-132.5 36.2-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5 35.7 0 80.3-11.2 124.2-34.1 44-22.8 78.8-52.9 99.2-82.2 20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7-18.9 27.1-47.8 53.4-83.6 75.4 11.1 1.2 22.7 1.8 34.5 1.8 49.5 0 94.3-10.6 125.9-27.1 31.7-16.5 49.1-38.1 49.1-59.9 0-21.8-17.4-43.4-49.1-59.9-16.1-8.4-35.7-15.3-57.6-20zm106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31-35 18.2-82.2 29.1-134.3 29.1-21.2 0-41.6-1.8-60.7-5.2-23.2 11.7-46.5 20.4-68.9 26.1 1.2.7 2.4 1.3 3.7 2 31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z" fill="#d3d6d8" fill-opacity="1"></path></g></svg>

+ 1 - 0
src/assets/icons/UIIcons/silver.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M264.4 95.01c-35.6-.06-80.2 11.19-124.2 34.09C96.27 152 61.45 182 41.01 211.3c-20.45 29.2-25.98 56.4-15.92 75.8 10.07 19.3 35.53 30.4 71.22 30.4 35.69.1 80.29-11.2 124.19-34 44-22.9 78.8-53 99.2-82.2 20.5-29.2 25.9-56.4 15.9-75.8-10.1-19.3-35.5-30.49-71.2-30.49zm91.9 70.29c-3.5 15.3-11.1 31-21.8 46.3-22.6 32.3-59.5 63.8-105.7 87.8-46.2 24.1-93.1 36.2-132.5 36.2-18.6 0-35.84-2.8-50.37-8.7l10.59 20.4c10.08 19.4 35.47 30.5 71.18 30.5 35.7 0 80.3-11.2 124.2-34.1 44-22.8 78.8-52.9 99.2-82.2 20.4-29.2 26-56.4 15.9-75.7zm28.8 16.8c11.2 26.7 2.2 59.2-19.2 89.7-18.9 27.1-47.8 53.4-83.6 75.4 11.1 1.2 22.7 1.8 34.5 1.8 49.5 0 94.3-10.6 125.9-27.1 31.7-16.5 49.1-38.1 49.1-59.9 0-21.8-17.4-43.4-49.1-59.9-16.1-8.4-35.7-15.3-57.6-20zm106.7 124.8c-10.2 11.9-24.2 22.4-40.7 31-35 18.2-82.2 29.1-134.3 29.1-21.2 0-41.6-1.8-60.7-5.2-23.2 11.7-46.5 20.4-68.9 26.1 1.2.7 2.4 1.3 3.7 2 31.6 16.5 76.4 27.1 125.9 27.1s94.3-10.6 125.9-27.1c31.7-16.5 49.1-38.1 49.1-59.9z" fill="#c0c0c0" fill-opacity="1"></path></g></svg>

+ 23 - 25
src/styles.scss

@@ -19,8 +19,6 @@
     --quaternary-color-light: #7a9e65;
     --quaternary-color-dark: #6eae52;
 
-    --background-color: #fff2e9;
-
     --field-background-color: #efc8af;
 
     --border-color: #8d8c8c;
@@ -34,14 +32,6 @@
 
     --text: #000000;
 
-    // OFFICIAL COLORS
-    --accept: #84a36f;
-    --accept-hover: #6f9158;
-    --delete: #a45a52;
-    --delete-hover: #8f4a42;
-    --edit: #86a5b7;
-    --edit-hover: #6f8e9f;
-
     // shadows
     --shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.5);
     --shadow-hover: 0px 5px 10px 0px rgba(0, 0, 0, 0.7);
@@ -49,26 +39,34 @@
     --shadow-medium: 4px 4px 10px 6px rgba(0, 0, 0, 0.2);
     --shadow-large: 4px 4px 10px 8px rgba(0, 0, 0, 0.2);
 
-    // MIXINS
+    // OFFICIAL COLORS
 
-    @mixin field-styling {
-        border: solid 1px var(--border-color);
-        background-color: var(--field-background-color);
-        box-shadow: var(--shadow-small);
-        border-radius: 10px;
-    }
+    // Buttons
+    --accept: #84a36f;
+    --accept-hover: #6f9158;
+    --delete: #a45a52;
+    --delete-hover: #8f4a42;
+    --edit: #86a5b7;
+    --edit-hover: #6f8e9f;
+    --neutral: #b9835d;
+    --neutral-hover: #a46e4a;
+    --tab: #efc8af;
+    --tab-active: #e0ad91;
 
-    @mixin button-styling {
-        border: solid 1px var(--border-color);
-        box-shadow: var(--shadow);
-        border-radius: 10px;
-    }
+    // General
 
-    //
+    --primary-color: #d8ac96;
 
-    // input {
+    --shadow: 0px 5px 10px 0px rgba(0, 0, 0, 0.5);
+    --background-color: #fff2e9;
+    --field-background-color: #efc8af;
+    --border-color: #8d8c8c;
+    --modal-background: antiquewhite;
+    --header: #ffdec6;
+    --text: #000000;
+    --items: #fff2e9;
+    --items-hover: #f7e3d7;
 
-    // }
     .responsive-small {
         display: none;
     }