Ver código fonte

added a general modal with service and implemented the inventory

Christopher Giese 1 ano atrás
pai
commit
1e092507a3
27 arquivos alterados com 860 adições e 67 exclusões
  1. 112 0
      .nx/cache/d/daemon.log
  2. 1 1
      .nx/cache/d/server-process.json
  3. 2 0
      src/app/journal/journal-home/journal-home.component.html
  4. 8 0
      src/app/journal/journal-home/modal/modal.component.html
  5. 37 0
      src/app/journal/journal-home/modal/modal.component.scss
  6. 23 0
      src/app/journal/journal-home/modal/modal.component.spec.ts
  7. 36 0
      src/app/journal/journal-home/modal/modal.component.ts
  8. 132 16
      src/app/journal/journal-inventory/journal-inventory.component.html
  9. 26 6
      src/app/journal/journal-inventory/journal-inventory.component.scss
  10. 99 44
      src/app/journal/journal-inventory/journal-inventory.component.ts
  11. 41 0
      src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.html
  12. 0 0
      src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.scss
  13. 23 0
      src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.spec.ts
  14. 23 0
      src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.ts
  15. 26 0
      src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.html
  16. 0 0
      src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.scss
  17. 23 0
      src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.spec.ts
  18. 20 0
      src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.ts
  19. 6 0
      src/app/journal/journal.module.ts
  20. 7 0
      src/interfaces/consumable.ts
  21. 6 0
      src/interfaces/food.ts
  22. 7 0
      src/interfaces/misc.ts
  23. 7 0
      src/interfaces/simple-item.ts
  24. 130 0
      src/services/data/data.service.ts
  25. 16 0
      src/services/modal/modal.service.spec.ts
  26. 30 0
      src/services/modal/modal.service.ts
  27. 19 0
      src/styles.scss

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

@@ -460043,3 +460043,115 @@ To fix this, set a unique name for each project in a project.json inside the pro
 [NX Daemon Server] - 2023-11-25T17:58:52.039Z - [WATCHER]: .nx/cache/d/daemon.log was modified
 [NX Daemon Server] - 2023-11-25T17:58:52.040Z - [WATCHER]: Processing file changes in outputs
 [NX Daemon Server] - 2023-11-25T17:58:52.040Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-26T12:39:36.111Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\e6a479e02f1047051806\d.sock
+[NX Daemon Server] - 2023-11-26T12:39:36.125Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\Test\DnDTools (native)
+[NX Daemon Server] - 2023-11-26T12:39:36.126Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-26T12:39:36.128Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2023-11-26T12:39:36.129Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-26T12:39:36.132Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-26T12:39:36.726Z - 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-26T12:39:36.726Z - [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-26T12:39:36.728Z - Time taken for 'hash changed files from watcher' 65.50829994678497ms
+[NX Daemon Server] - 2023-11-26T12:39:36.728Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-26T12:39:36.729Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-26T18:52:26.321Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\e6a479e02f1047051806\d.sock
+[NX Daemon Server] - 2023-11-26T18:52:26.323Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\Test\DnDTools (native)
+[NX Daemon Server] - 2023-11-26T18:52:26.331Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-26T18:52:26.333Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2023-11-26T18:52:26.333Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-26T18:52:26.336Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-26T18:52:26.871Z - 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-26T18:52:26.871Z - [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-26T18:52:26.872Z - Time taken for 'hash changed files from watcher' 21.05649995803833ms
+[NX Daemon Server] - 2023-11-26T18:52:26.873Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-26T18:52:26.873Z - Done responding to the client null
+[NX Daemon Server] - 2023-11-27T15:52:37.929Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\e6a479e02f1047051806\d.sock
+[NX Daemon Server] - 2023-11-27T15:52:37.938Z - [WATCHER]: Subscribed to changes within: c:\Users\chris\Softwareprojekte\Test\DnDTools (native)
+[NX Daemon Server] - 2023-11-27T15:52:37.939Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-27T15:52:37.940Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2023-11-27T15:52:37.941Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2023-11-27T15:52:37.942Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2023-11-27T15:52:38.587Z - 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-27T15:52:38.587Z - [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-27T15:52:38.589Z - Time taken for 'hash changed files from watcher' 226.9858000278473ms
+[NX Daemon Server] - 2023-11-27T15:52:38.589Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2023-11-27T15:52:38.590Z - [WATCHER]: .nx/cache/d/daemon.log was modified
+[NX Daemon Server] - 2023-11-27T15:52:38.591Z - Done responding to the client null

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

@@ -1 +1 @@
-{"processId":10332}
+{"processId":10316}

+ 2 - 0
src/app/journal/journal-home/journal-home.component.html

@@ -8,4 +8,6 @@
   <navigation-panel
     [showAdditionalNavigation]="hideTabbar()"
   ></navigation-panel>
+
+  <modal></modal>
 </div>

+ 8 - 0
src/app/journal/journal-home/modal/modal.component.html

@@ -0,0 +1,8 @@
+<div id="myModal" class="modal-backdrop">
+  <!-- Modal content -->
+  <div class="modal-content">
+    <ng-template
+      *ngComponentOutlet="modalComponent; inputs: inputData"
+    ></ng-template>
+  </div>
+</div>

+ 37 - 0
src/app/journal/journal-home/modal/modal.component.scss

@@ -0,0 +1,37 @@
+/* The Modal (background) */
+.modal-backdrop {
+  display: none; 
+  position: fixed; 
+  z-index: 991; 
+  left: 0;
+  top: 0;
+  width: 100%; 
+  height: 100%; 
+  overflow: auto; 
+  background-color: rgb(0,0,0); 
+  background-color: rgba(0,0,0,0.4); 
+}
+
+/* Modal Content/Box */
+.modal-content {
+  background-color: #fefefe;
+  margin: 15% auto; /* 15% from the top and centered */
+  padding: 20px;
+  border: 1px solid #888;
+  width: 80%; /* Could be more or less, depending on screen size */
+}
+
+/* The Close Button */
+.close {
+  color: #aaa;
+  float: right;
+  font-size: 28px;
+  font-weight: bold;
+}
+
+.close:hover,
+.close:focus {
+  color: black;
+  text-decoration: none;
+  cursor: pointer;
+}

+ 23 - 0
src/app/journal/journal-home/modal/modal.component.spec.ts

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

+ 36 - 0
src/app/journal/journal-home/modal/modal.component.ts

@@ -0,0 +1,36 @@
+import { Component } from '@angular/core';
+import { ModalService } from 'src/services/modal/modal.service';
+
+@Component({
+  selector: 'modal',
+  templateUrl: './modal.component.html',
+  styleUrl: './modal.component.scss',
+})
+export class ModalComponent {
+  constructor(private modal: ModalService) {}
+  public modalComponent: any;
+  public inputData: any;
+  public modalRef: any;
+
+  public open(): void {
+    console.log(this.modalRef);
+    this.modalRef!.style.display = 'block';
+  }
+
+  public close(): void {
+    this.modalRef!.style.display = 'none';
+  }
+
+  ngOnInit() {
+    this.modalRef = document.getElementById('myModal');
+    this.modal.modal$.subscribe((data) => {
+      console.log('modal component', data);
+      this.modalComponent = data.component;
+      this.inputData = data.data;
+      this.open();
+    });
+    this.modal.closeModal$.subscribe(() => {
+      this.close();
+    });
+  }
+}

+ 132 - 16
src/app/journal/journal-inventory/journal-inventory.component.html

@@ -1,23 +1,55 @@
 <div class="inventory-container">
-  <div class="items-container">
-    <div
-      cdkDropList
-      class="example-list"
-      (cdkDropListDropped)="drop($event, weaponsAndArmor)"
-    >
-      @for (item of weaponsAndArmor; track item) {
-      <div class="example-box" cdkDrag>{{ item.name }}</div>
-      }
-    </div>
+  <div class="item-container">
+    <ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs">
+      <li [ngbNavItem]="1">
+        <button ngbNavLink>Waffen und Rüstungen</button>
+        <ng-template ngbNavContent>
+          <ng-container [ngTemplateOutlet]="weaponTemplate"></ng-container>
+        </ng-template>
+      </li>
+      <li [ngbNavItem]="2">
+        <button ngbNavLink>Verbrauchsgegenstände</button>
+        <ng-template ngbNavContent
+          ><ng-container [ngTemplateOutlet]="consumablesTemplate"></ng-container
+        ></ng-template>
+      </li>
+      <li [ngbNavItem]="3">
+        <button ngbNavLink>Sonstiges</button>
+        <ng-template ngbNavContent
+          ><ng-container [ngTemplateOutlet]="miscTemplate"></ng-container
+        ></ng-template>
+      </li>
+    </ul>
+
+    <div [ngbNavOutlet]="nav" class="mt-2"></div>
   </div>
 
   <div class="money-container">
     Geld
-    <div>
-      <input type="number" placeholder="Platin" /><br />
-      <input type="number" placeholder="Gold" /><br />
-      <input type="number" placeholder="Silber" /><br />
-      <input type="number" placeholder="Kupfer" /><br />
+    <div (change)="updateMoney()">
+      <input
+        type="number"
+        [(ngModel)]="money.platinum"
+        placeholder="Platin"
+      /><label>Platin</label><br />
+      <input type="number" [(ngModel)]="money.gold" placeholder="Gold" /><label
+        >Gold</label
+      ><br />
+      <input
+        type="number"
+        [(ngModel)]="money.electrum"
+        placeholder="Elektrum"
+      /><label>Elektrum</label> <br />
+      <input
+        type="number"
+        [(ngModel)]="money.silver"
+        placeholder="Silber"
+      /><label>Silber</label><br />
+      <input
+        type="number"
+        [(ngModel)]="money.copper"
+        placeholder="Kupfer"
+      /><label>Kupfer</label><br />
     </div>
   </div>
 
@@ -26,7 +58,7 @@
     <div
       cdkDropList
       class="example-list"
-      (cdkDropListDropped)="drop($event, food)"
+      (cdkDropListDropped)="drop($event, food, 'food')"
     >
       @for (item of food; track item) {
       <div class="example-box" cdkDrag>{{ item.name }}</div>
@@ -34,3 +66,87 @@
     </div>
   </div>
 </div>
+
+<!-- WEAPONS -->
+<ng-template #weaponTemplate>
+  <div
+    cdkDropList
+    class="example-list"
+    (cdkDropListDropped)="drop($event, weaponsAndArmor, 'weaponsAndArmor')"
+  >
+    <div class="heading-row">
+      <div class="heading">Name</div>
+      <div class="heading">Wert</div>
+      <div class="heading">Gewicht</div>
+      <div class="heading">Anzahl</div>
+    </div>
+    @for (item of weaponsAndArmor; let index = $index; track item) {
+    <div
+      class="example-box"
+      cdkDrag
+      (click)="openDetails(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>
+    }
+  </div>
+</ng-template>
+
+<!-- CONSUMABLES -->
+<ng-template #consumablesTemplate>
+  <div
+    cdkDropList
+    class="example-list"
+    (cdkDropListDropped)="drop($event, consumables, 'consumables')"
+  >
+    <div class="heading-row">
+      <div class="heading">Name</div>
+      <div class="heading">Wert</div>
+      <div class="heading">Gewicht</div>
+      <div class="heading">Anzahl</div>
+    </div>
+    @for (item of consumables; let index = $index; track item) {
+    <div
+      class="example-box"
+      cdkDrag
+      (click)="openDetails(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>
+    }
+  </div>
+</ng-template>
+
+<!-- MISCELLANEOUS -->
+<ng-template #miscTemplate>
+  <div
+    cdkDropList
+    class="example-list"
+    (cdkDropListDropped)="drop($event, miscellaneous, 'miscellaneous')"
+  >
+    <div class="heading-row">
+      <div class="heading">Name</div>
+      <div class="heading">Wert</div>
+      <div class="heading">Gewicht</div>
+      <div class="heading">Anzahl</div>
+    </div>
+    @for (item of miscellaneous; let index = $index; track item) {
+    <div
+      class="example-box"
+      cdkDrag
+      (click)="openDetails(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>
+    </div>
+    }
+  </div>
+</ng-template>

+ 26 - 6
src/app/journal/journal-inventory/journal-inventory.component.scss

@@ -9,23 +9,45 @@
 
 .item-container{
     grid-area: 1 / 1 / 11 / 7;
+    border: 1px solid black;
 }
 
 .money-container{
     grid-area: 1 / 8 / 6 / 11;
+     border: 1px solid black;
 }
 
 .food-container{
     grid-area: 7 / 8 / 11 / 11;
+     border: 1px solid black;
 }
 
+.heading-row{
+  display: grid;
+  grid-template-columns: 2fr 1fr 1fr 1fr;
+  padding: 0 10px;;
+}
+
+.heading{
+  font-size: 1.5rem;
+  font-weight: 600;
+  padding-left: 2rem;
+}
+
+.item{
+  font-size: 1.25rem;
+  font-weight: 600;
+  padding-left: 2rem;
+}
+
+
+
 
 
 
 
 
 .example-list {
-  width: 500px;
   max-width: 100%;
   border: solid 1px #ccc;
   min-height: 60px;
@@ -36,17 +58,15 @@
 }
 
 .example-box {
-  padding: 20px 10px;
+  padding: 10px 10px;
   border-bottom: solid 1px #ccc;
   color: rgba(0, 0, 0, 0.87);
-  display: flex;
-  flex-direction: row;
+  display: grid;
+  grid-template-columns: 2fr 1fr 1fr 1fr;
   align-items: center;
-  justify-content: space-between;
   box-sizing: border-box;
   cursor: move;
   background: white;
-  font-size: 14px;
 }
 
 .cdk-drag-preview {

+ 99 - 44
src/app/journal/journal-inventory/journal-inventory.component.ts

@@ -5,6 +5,13 @@ import {
   CdkDrag,
   moveItemInArray,
 } from '@angular/cdk/drag-drop';
+import { DetailsService } from 'src/services/details/details.service';
+import { DataService } from 'src/services/data/data.service';
+import { SimpleItem } from 'src/interfaces/simple-item';
+import { Food } from 'src/interfaces/food';
+import { SimpleItemDetailsComponent } from './simple-item-details/simple-item-details.component';
+import { ModalService } from 'src/services/modal/modal.service';
+import { SimpleItemModalComponent } from './simple-item-modal/simple-item-modal.component';
 
 @Component({
   selector: 'app-journal-inventory',
@@ -12,50 +19,98 @@ import {
   styleUrls: ['./journal-inventory.component.scss'],
 })
 export class JournalInventoryComponent {
-  movies = [
-    'Episode I - The Phantom Menace',
-    'Episode II - Attack of the Clones',
-    'Episode III - Revenge of the Sith',
-    'Episode IV - A New Hope',
-    'Episode V - The Empire Strikes Back',
-    'Episode VI - Return of the Jedi',
-    'Episode VII - The Force Awakens',
-    'Episode VIII - The Last Jedi',
-    'Episode IX – The Rise of Skywalker',
-  ];
-
-  public food = [
-    { name: 'Ration', ready: true, amount: 7 },
-    { name: 'Ration', ready: true, amount: 4 },
-    { name: 'Ration', ready: true, amount: 3 },
-  ];
-
-  public weaponsAndArmor = [
-    {
-      name: 'Kurzschwert',
-      weight: 40,
-      value: 50,
-      quantity: 1,
-      description: 'Hallo',
-    },
-    {
-      name: 'Helebade',
-      weight: 40,
-      value: 50,
-      quantity: 1,
-      description: 'Hallo',
-    },
-    {
-      name: 'Armbrust',
-      weight: 40,
-      value: 50,
-      quantity: 1,
-      description: 'Hallo',
-    },
-  ];
-
-  drop(event: CdkDragDrop<string[]>, list: any[]) {
+  constructor(
+    private detailsAccessor: DetailsService,
+    private dataAccessor: DataService,
+    private modalAccessor: ModalService
+  ) {}
+
+  public active: number = 1;
+
+  public weaponsAndArmor: SimpleItem[] = [];
+  public consumables: SimpleItem[] = [];
+  public miscellaneous: SimpleItem[] = [];
+  public money: any = {};
+  public food: Food[] = [];
+
+  public ngOnInit(): void {
+    this.weaponsAndArmor = this.dataAccessor.items;
+    this.consumables = this.dataAccessor.consumables;
+    this.miscellaneous = this.dataAccessor.miscellaneous;
+    this.food = this.dataAccessor.food;
+    this.money = this.dataAccessor.money;
+  }
+
+  drop(event: CdkDragDrop<string[]>, list: any[], listName: string) {
     moveItemInArray(list, event.previousIndex, event.currentIndex);
-    console.log(list);
+    if (listName === 'weaponsAndArmor') {
+      this.dataAccessor.items = list;
+    } else if (listName === 'food') {
+      this.dataAccessor.food = list;
+    } else if (listName === 'consumables') {
+      this.dataAccessor.consumables = list;
+    } else if (listName === 'miscellaneous') {
+      this.dataAccessor.miscellaneous = list;
+    } else {
+      throw new Error('Unknown list name: ' + listName);
+    }
+  }
+
+  public openDetails(list: any, index: number, listName: string): void {
+    this.detailsAccessor.openPanel(SimpleItemDetailsComponent, {
+      item: list[index],
+    });
+    const resultSubscription = this.detailsAccessor.result$.subscribe(
+      (result) => {
+        console.log(result);
+        if (result.state === 'delete') {
+          list.splice(index, 1);
+          this.updateDatabase(listName);
+        } else if (result.state === 'update') {
+          this.openModal(list, index, listName);
+        }
+        resultSubscription.unsubscribe();
+      }
+    );
+  }
+
+  public updateDatabase(listname: string): void {
+    if (listname === 'weaponsAndArmor') {
+      this.dataAccessor.items = this.weaponsAndArmor;
+    } else if (listname === 'consumables') {
+      this.dataAccessor.consumables = this.consumables;
+    } else if (listname === 'miscellaneous') {
+      this.dataAccessor.miscellaneous = this.miscellaneous;
+    } else {
+      throw new Error('Unknown list name: ' + listname);
+    }
+  }
+
+  public updateMoney(): void {
+    this.dataAccessor.money = this.money;
+  }
+
+  public openModal(list: SimpleItem[], index: number, listname: string): void {
+    this.modalAccessor.openModal(SimpleItemModalComponent, {
+      item: JSON.parse(JSON.stringify(list[index])),
+    });
+    const resultSubscription = this.modalAccessor.result$.subscribe(
+      (result) => {
+        console.log(result);
+        if (result.state === 'update') {
+          list[index] = result.data;
+          if (listname === 'weaponsAndArmor') {
+            this.updateDatabase('weaponsAndArmor');
+          } else if (listname === 'consumables') {
+            this.updateDatabase('consumables');
+          } else if (listname === 'miscellaneous') {
+            this.updateDatabase('miscellaneous');
+          } else {
+            throw new Error('Unknown list name: ' + listname);
+          }
+        }
+        resultSubscription.unsubscribe();
+      }
+    );
   }
 }

+ 41 - 0
src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.html

@@ -0,0 +1,41 @@
+<div class="details-title">{{ item.name }}</div>
+
+<div class="details-flex-row top-2">
+  <div>
+    <div class="details-value">{{ item.value }}</div>
+    <div class="details-label">Wert</div>
+  </div>
+
+  <div>
+    <div class="details-value">{{ item.weight }}</div>
+    <div class="details-label">Gewicht</div>
+  </div>
+
+  <div>
+    <div class="details-value">{{ item.quantity }}</div>
+    <div class="details-label">Anzahl</div>
+  </div>
+</div>
+
+<div class="details-content">{{ item.description }}</div>
+
+<div class="vertical-button-wrapper-3">
+  <ui-button
+    [type]="'edit'"
+    [size]="'xlarge'"
+    [color]="'primary'"
+    (click)="close('update')"
+  ></ui-button>
+  <ui-button
+    [type]="'delete'"
+    [size]="'xlarge'"
+    [color]="'primary'"
+    (click)="close('delete')"
+  ></ui-button>
+  <ui-button
+    [type]="'dismiss'"
+    [size]="'xlarge'"
+    [color]="'primary'"
+    (click)="close('dismiss')"
+  ></ui-button>
+</div>

+ 0 - 0
src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.scss


+ 23 - 0
src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.spec.ts

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

+ 23 - 0
src/app/journal/journal-inventory/simple-item-details/simple-item-details.component.ts

@@ -0,0 +1,23 @@
+import { Component, Input } from '@angular/core';
+import { SimpleItem } from 'src/interfaces/simple-item';
+import { DetailsService } from 'src/services/details/details.service';
+
+@Component({
+  selector: 'simple-item-details',
+  templateUrl: './simple-item-details.component.html',
+  styleUrl: './simple-item-details.component.scss',
+})
+export class SimpleItemDetailsComponent {
+  public constructor(public detailsAccessor: DetailsService) {}
+  @Input() item: SimpleItem = {
+    name: '',
+    weight: 0,
+    value: 0,
+    quantity: 0,
+    description: '',
+  };
+
+  public close(result: string): void {
+    this.detailsAccessor.closePanel(result);
+  }
+}

+ 26 - 0
src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.html

@@ -0,0 +1,26 @@
+<div style="padding-bottom: 10rem">
+  <input type="text" placeholder="Name" [(ngModel)]="item.name" />
+  <label>Name</label><br />
+  <input type="number" placeholder="Wert" [(ngModel)]="item.value" />
+  <label>Wert</label><br />
+  <input type="number" placeholder="Gewicht" [(ngModel)]="item.weight" />
+  <label>Gewicht</label><br />
+  <input type="number" placeholder="Anzahl" [(ngModel)]="item.quantity" />
+  <label>Anzahl</label><br />
+  <textarea placeholder="Beschreibung" [(ngModel)]="item.description"></textarea
+  ><label>Beschreibung</label>
+</div>
+<div class="vertical-button-wrapper-2">
+  <ui-button
+    [type]="'update'"
+    [size]="'xlarge'"
+    [color]="'primary'"
+    (click)="update()"
+  ></ui-button>
+  <ui-button
+    [type]="'dismiss'"
+    [size]="'xlarge'"
+    [color]="'primary'"
+    (click)="cancel()"
+  ></ui-button>
+</div>

+ 0 - 0
src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.scss


+ 23 - 0
src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.spec.ts

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

+ 20 - 0
src/app/journal/journal-inventory/simple-item-modal/simple-item-modal.component.ts

@@ -0,0 +1,20 @@
+import { Component, Input } from '@angular/core';
+import { ModalService } from 'src/services/modal/modal.service';
+
+@Component({
+  selector: 'app-simple-item-modal',
+  templateUrl: './simple-item-modal.component.html',
+  styleUrl: './simple-item-modal.component.scss',
+})
+export class SimpleItemModalComponent {
+  public constructor(private modalAccessor: ModalService) {}
+  @Input() public item: any;
+
+  public cancel(): void {
+    this.modalAccessor.handleModalClosing('cancel', undefined);
+  }
+
+  public update(): void {
+    this.modalAccessor.handleModalClosing('update', this.item);
+  }
+}

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

@@ -41,6 +41,8 @@ import { SpellslotsModalComponent } from './journal-stats/ability-panel/spellslo
 import { InfoRowComponent } from './journal-stats/info-row/info-row.component';
 import { ConditionsComponent } from './journal-stats/info-row/conditions/conditions.component';
 import { AttributeDetailsComponent } from './journal-stats/attribute-skill-container/attribute-panel/attribute-field/attribute-details/attribute-details.component';
+import { SimpleItemDetailsComponent } from './journal-inventory/simple-item-details/simple-item-details.component';
+import { ModalComponent } from './journal-home/modal/modal.component';
 
 import { SharedComponentsModule } from '../shared-components/shared-components.module';
 import { ProficienciesTableComponent } from './journal-stats/ability-panel/proficiencies-table/proficiencies-table.component';
@@ -72,6 +74,7 @@ import { JournalPlacesComponent } from './journal-places/journal-places.componen
 import { JournalMapsComponent } from './journal-maps/journal-maps.component';
 import { JournalRulesetComponent } from './journal-ruleset/journal-ruleset.component';
 import { JournalSettingsComponent } from './journal-settings/journal-settings.component';
+import { SimpleItemModalComponent } from './journal-inventory/simple-item-modal/simple-item-modal.component';
 
 @NgModule({
   declarations: [
@@ -138,6 +141,9 @@ import { JournalSettingsComponent } from './journal-settings/journal-settings.co
     JournalMapsComponent,
     JournalRulesetComponent,
     JournalSettingsComponent,
+    SimpleItemDetailsComponent,
+    ModalComponent,
+    SimpleItemModalComponent,
   ],
   imports: [
     CommonModule,

+ 7 - 0
src/interfaces/consumable.ts

@@ -0,0 +1,7 @@
+export interface Consumable {
+  name: string;
+  weight: number;
+  value: number;
+  quantity: number;
+  description: string;
+}

+ 6 - 0
src/interfaces/food.ts

@@ -0,0 +1,6 @@
+export interface Food {
+  name: string;
+  ready: boolean;
+  quantity: number;
+  description?: string;
+}

+ 7 - 0
src/interfaces/misc.ts

@@ -0,0 +1,7 @@
+export interface Misc {
+  name: string;
+  weight: number;
+  value: number;
+  quantity: number;
+  description?: string;
+}

+ 7 - 0
src/interfaces/simple-item.ts

@@ -0,0 +1,7 @@
+export interface SimpleItem {
+  name: string;
+  weight: number;
+  value: number;
+  quantity: number;
+  description?: string;
+}

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

@@ -9,6 +9,8 @@ import { Weapon } from 'src/interfaces/weapon';
 import { Spell } from 'src/interfaces/spell';
 import { Ability } from 'src/interfaces/ability';
 import { Trait } from 'src/interfaces/traits';
+import { SimpleItem } from 'src/interfaces/simple-item';
+import { Food } from 'src/interfaces/food';
 
 @Injectable({
   providedIn: 'root',
@@ -722,6 +724,134 @@ export class DataService {
 
   // #endregion
 
+  // #region inventory
+
+  private _items: SimpleItem[] = [
+    {
+      name: 'Kurzbogen +1',
+      weight: 5,
+      value: 50,
+      quantity: 1,
+      description: 'Hallo',
+    },
+    {
+      name: 'Helebade',
+      weight: 10,
+      value: 5,
+      quantity: 1,
+      description: 'Hallo',
+    },
+    {
+      name: 'Armbrust',
+      weight: 8,
+      value: 6,
+      quantity: 1,
+      description: 'Hallo',
+    },
+  ];
+
+  public get items(): SimpleItem[] {
+    return this._items;
+  }
+
+  public set items(newValue: SimpleItem[]) {
+    console.log('items: ', newValue);
+    this._items = newValue;
+  }
+
+  private _food: Food[] = [
+    {
+      name: 'Brot',
+      quantity: 7,
+      ready: true,
+    },
+    {
+      name: 'Suppe',
+      quantity: 4,
+      ready: true,
+    },
+  ];
+
+  public get food(): Food[] {
+    return this._food;
+  }
+
+  public set food(newValue: Food[]) {
+    console.log('food: ', newValue);
+    this._food = newValue;
+  }
+
+  private _money: any = {
+    copper: 100,
+    silver: 100,
+    electrum: 100,
+    gold: 100,
+    platinum: 100,
+  };
+
+  public get money(): any {
+    return this._money;
+  }
+
+  public set money(newValue: any) {
+    console.log('money: ', newValue);
+    this._money = newValue;
+  }
+
+  private _consumbales: SimpleItem[] = [
+    {
+      name: 'Heiltrank',
+      weight: 0.5,
+      value: 50,
+      quantity: 1,
+      description: 'Heilt 1W8 + 2 Trefferpunkte',
+    },
+    {
+      name: 'Öl',
+      weight: 1,
+      value: 1,
+      quantity: 1,
+      description: 'Brennt',
+    },
+  ];
+
+  public get consumables(): SimpleItem[] {
+    return this._consumbales;
+  }
+
+  public set consumables(newValue: SimpleItem[]) {
+    console.log('consumables: ', newValue);
+    this._consumbales = newValue;
+  }
+
+  private _miscellaneous: SimpleItem[] = [
+    {
+      name: 'Rucksack',
+      weight: 5,
+      value: 2,
+      quantity: 1,
+      description: 'Hallo',
+    },
+    {
+      name: 'Seil',
+      weight: 5,
+      value: 2,
+      quantity: 1,
+      description: 'Hallo',
+    },
+  ];
+
+  public get miscellaneous(): SimpleItem[] {
+    return this._miscellaneous;
+  }
+
+  public set miscellaneous(newValue: SimpleItem[]) {
+    console.log('misc: ', newValue);
+    this._miscellaneous = newValue;
+  }
+
+  // #endregion
+
   // #region database calls
 
   public async addData(

+ 16 - 0
src/services/modal/modal.service.spec.ts

@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { ModalService } from './modal.service';
+
+describe('ModalService', () => {
+  let service: ModalService;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({});
+    service = TestBed.inject(ModalService);
+  });
+
+  it('should be created', () => {
+    expect(service).toBeTruthy();
+  });
+});

+ 30 - 0
src/services/modal/modal.service.ts

@@ -0,0 +1,30 @@
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs';
+import { SimpleItem } from 'src/interfaces/simple-item';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class ModalService {
+  private _modalSubject = new Subject<any>();
+  modal$ = this._modalSubject.asObservable();
+
+  private _closeModalSubject = new Subject<any>();
+  closeModal$ = this._closeModalSubject.asObservable();
+
+  private _resultSubject = new Subject<any>();
+  result$ = this._resultSubject.asObservable();
+
+  public openModal(component: any, data: any) {
+    console.log('openModal in modal accessor');
+    this._modalSubject.next({ component, data });
+  }
+
+  // Is called from the dynamic component to close the offcanvas
+  public handleModalClosing(result: any, data?: SimpleItem) {
+    console.log('closePanel', result);
+    // Is listened to in the host component where the panel was opened, to initiate further steps
+    this._resultSubject.next({ state: result, data: data });
+    this._closeModalSubject.next('close');
+  }
+}

+ 19 - 0
src/styles.scss

@@ -216,6 +216,25 @@ input[type="checkbox"]:checked {
     margin-top: 2rem;
 }
 
+
+.details-flex-row{
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.top-1{
+    margin-top: 1rem;
+}
+
+.top-2{
+    margin-top: 2rem;
+}
+
+.top-3{
+    margin-top: 3rem;
+}
+
 .details-value{
     width: 3.5rem;
     height: 3rem;