Переглянути джерело

finished implementing the character Page

Warafear 1 рік тому
батько
коміт
529962c0ad
37 змінених файлів з 1199 додано та 332 видалено
  1. 325 0
      .nx/cache/d/daemon.log
  2. 1 1
      .nx/cache/d/server-process.json
  3. 41 23
      src/app/character/character-creator/character-creator.component.ts
  4. 3 3
      src/app/character/character-picker/character-card/character-card.component.html
  5. 9 1
      src/app/character/character-picker/character-card/character-card.component.ts
  6. 1 0
      src/app/journal/journal-character/class/class.component.ts
  7. 98 104
      src/app/journal/journal-character/general/general.component.html
  8. 51 21
      src/app/journal/journal-character/general/general.component.scss
  9. 13 5
      src/app/journal/journal-character/general/general.component.ts
  10. 11 54
      src/app/journal/journal-character/species/species.component.ts
  11. 19 46
      src/app/journal/journal-character/subclass/subclass.component.ts
  12. 2 2
      src/app/journal/journal-home/navigation-panel/navigation-panel.component.html
  13. 16 18
      src/app/journal/journal-home/navigation-panel/navigation-panel.component.scss
  14. 10 10
      src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.html
  15. 46 0
      src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.ts
  16. 8 5
      src/app/journal/journal-stats/life-container/life/life.component.html
  17. 55 15
      src/app/journal/journal-stats/life-container/life/life.component.scss
  18. 2 2
      src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.ts
  19. 2 1
      src/app/journal/journal.module.ts
  20. 0 1
      src/assets/icons/UIIcons/character.svg
  21. 1 0
      src/assets/icons/UIIcons/characters.svg
  22. 1 0
      src/assets/icons/UIIcons/damage.svg
  23. 1 0
      src/assets/icons/UIIcons/heal.svg
  24. 1 0
      src/assets/icons/UIIcons/image.svg
  25. 0 1
      src/assets/icons/UIIcons/life-minus.svg
  26. 0 1
      src/assets/icons/UIIcons/life-plus.svg
  27. 0 1
      src/assets/icons/UIIcons/life-temporary.svg
  28. 1 1
      src/assets/icons/UIIcons/settings.svg
  29. 1 0
      src/assets/icons/UIIcons/temporary.svg
  30. 109 14
      src/services/class/class.service.ts
  31. 1 0
      src/services/data/data.service.ts
  32. 117 2
      src/services/species/species.service.ts
  33. 29 0
      src/services/spells/spells.service.ts
  34. 16 0
      src/services/subclass/subclass.service.spec.ts
  35. 115 0
      src/services/subclass/subclass.service.ts
  36. 16 0
      src/services/translator/translator.service.spec.ts
  37. 77 0
      src/services/translator/translator.service.ts

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

@@ -462158,3 +462158,328 @@ 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-09T09:03:38.951Z - Time taken for 'hash changed files from watcher' 15.533100128173828ms
 [NX Daemon Server] - 2024-01-09T09:03:38.951Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-12T06:51:44.854Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-12T06:51:44.857Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-12T06:51:44.861Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-12T06:51:44.863Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-12T06:51:44.864Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-12T06:51:44.866Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-12T06:51:45.652Z - 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-12T06:51:45.652Z - [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-12T06:51:45.654Z - Time taken for 'hash changed files from watcher' 18.79670000076294ms
+[NX Daemon Server] - 2024-01-12T06:51:45.654Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-12T08:54:53.951Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-12T08:54:53.956Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-12T08:54:53.958Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-12T08:54:53.960Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-12T08:54:53.960Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-12T08:54:53.962Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-12T08:54:54.838Z - 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-12T08:54:54.838Z - [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-12T08:54:54.839Z - Time taken for 'hash changed files from watcher' 43.397900104522705ms
+[NX Daemon Server] - 2024-01-12T08:54:54.840Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-13T08:50:08.268Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-13T08:50:08.272Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-13T08:50:08.274Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-13T08:50:08.276Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-13T08:50:08.276Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-13T08:50:08.278Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-13T08:50:08.807Z - 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-13T08:50:08.807Z - [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-13T08:50:08.809Z - Time taken for 'hash changed files from watcher' 43.34740000002785ms
+[NX Daemon Server] - 2024-01-13T08:50:08.809Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-13T11:42:37.268Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-13T11:42:37.272Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-13T11:42:37.283Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-13T11:42:37.295Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-13T11:42:37.295Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-13T11:42:37.307Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-13T11:42:37.854Z - 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-13T11:42:37.855Z - [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-13T11:42:37.856Z - Time taken for 'hash changed files from watcher' 48.85109999962151ms
+[NX Daemon Server] - 2024-01-13T11:42:37.857Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-15T16:14:40.922Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-15T16:14:40.925Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-15T16:14:40.933Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-15T16:14:40.935Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-15T16:14:40.935Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-15T16:14:40.937Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-15T16:14:41.712Z - 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-15T16:14:41.713Z - [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-15T16:14:41.714Z - Time taken for 'hash changed files from watcher' 51.3518999999942ms
+[NX Daemon Server] - 2024-01-15T16:14:41.714Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-16T06:25:33.169Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-16T06:25:33.173Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-16T06:25:33.177Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-16T06:25:33.179Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-16T06:25:33.179Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-16T06:25:33.182Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-16T06:25:33.675Z - 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-16T06:25:33.675Z - [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-16T06:25:33.676Z - Time taken for 'hash changed files from watcher' 15.80629999935627ms
+[NX Daemon Server] - 2024-01-16T06:25:33.676Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-17T16:54:49.384Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-17T16:54:49.393Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-17T16:54:49.394Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-17T16:54:49.395Z - Established a connection. Number of open connections: 2
+[NX Daemon Server] - 2024-01-17T16:54:49.396Z - Closed a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-17T16:54:49.398Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-17T16:54:50.146Z - 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-17T16:54:50.146Z - [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-17T16:54:50.147Z - Time taken for 'hash changed files from watcher' 36.4316000000108ms
+[NX Daemon Server] - 2024-01-17T16:54:50.148Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-18T14:42:11.819Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-18T14:42:11.824Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-18T14:42:11.826Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-18T14:42:11.827Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-18T14:42:11.827Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-18T14:42:11.829Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-18T14:42:11.978Z - 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-18T14:42:11.979Z - [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-18T14:42:11.980Z - Time taken for 'hash changed files from watcher' 62.82770000398159ms
+[NX Daemon Server] - 2024-01-18T14:42:11.980Z - Done responding to the client null
+[NX Daemon Server] - 2024-01-19T18:24:40.739Z - Started listening on: \\.\pipe\nx\C:\Users\chris\AppData\Local\Temp\83d14e7134fc08a15480\d.sock
+[NX Daemon Server] - 2024-01-19T18:24:40.743Z - [WATCHER]: Subscribed to changes within: c:\Softwareprojekte\DnD (native)
+[NX Daemon Server] - 2024-01-19T18:24:40.754Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-19T18:24:40.756Z - Closed a connection. Number of open connections: 0
+[NX Daemon Server] - 2024-01-19T18:24:40.756Z - Established a connection. Number of open connections: 1
+[NX Daemon Server] - 2024-01-19T18:24:40.758Z - [REQUEST]: Client Request for Project Graph Received
+[NX Daemon Server] - 2024-01-19T18:24:41.390Z - 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-19T18:24:41.390Z - [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-19T18:24:41.391Z - Time taken for 'hash changed files from watcher' 12.50719999987632ms
+[NX Daemon Server] - 2024-01-19T18:24:41.391Z - [WATCHER]: Processing file changes in outputs
+[NX Daemon Server] - 2024-01-19T18:24:41.392Z - Done responding to the client null

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

@@ -1 +1 @@
-{"processId":15032}
+{"processId":21480}

+ 41 - 23
src/app/character/character-creator/character-creator.component.ts

@@ -17,30 +17,31 @@ export class CharacterCreatorComponent {
 
   // TODO: Implement the species
   public species: characterData[] = [
-    { view: 'Mensch', value: 'human' },
-    { view: 'Zwerg', value: 'dwarf' },
-    { view: 'Elf', value: 'elf' },
-    { view: 'Halbelf', value: 'halfelf' },
-    { view: 'Halbling', value: 'halfling' },
-    { view: 'Gnom', value: 'gnome' },
-    { view: 'Halbork', value: 'halforc' },
-    { view: 'Tiefling', value: 'tiefling' },
+    { view: 'Mensch', value: 'Human' },
+    { view: 'Zwerg', value: 'Dwarf' },
+    { view: 'Elf', value: 'Elf' },
+    { view: 'Halbelf', value: 'HalfElf' },
+    { view: 'Halbelf (Mal des Entdeckens)', value: 'HalfElfDetection' },
+    { view: 'Halbling', value: 'Halfling' },
+    { view: 'Gnom', value: 'Gnome' },
+    { view: 'Halbork', value: 'HalfOrc' },
+    { view: 'Tiefling', value: 'Tiefling' },
   ];
 
   // TODO: Implement the classes
   public classes: characterData[] = [
-    { view: 'Barbar', value: 'barbarian' },
-    { view: 'Barde', value: 'bard' },
-    { view: 'Druide', value: 'druid' },
-    { view: 'Hexenmeister', value: 'warlock' },
-    { view: 'Kämpfer', value: 'fighter' },
-    { view: 'Kleriker', value: 'cleric' },
-    { view: 'Magier', value: 'wizard' },
-    { view: 'Mönch', value: 'monk' },
-    { view: 'Paladin', value: 'paladin' },
-    { view: 'Schurke', value: 'rogue' },
-    { view: 'Waldläufer', value: 'ranger' },
-    { view: 'Zauberer', value: 'sorcerer' },
+    { view: 'Barbar', value: 'Barbarian' },
+    { view: 'Barde', value: 'Bard' },
+    { view: 'Druide', value: 'Druid' },
+    { view: 'Hexenmeister', value: 'Warlock' },
+    { view: 'Kämpfer', value: 'Fighter' },
+    { view: 'Kleriker', value: 'Cleric' },
+    { view: 'Magier', value: 'Wizard' },
+    { view: 'Mönch', value: 'Monk' },
+    { view: 'Paladin', value: 'Paladin' },
+    { view: 'Schurke', value: 'Rogue' },
+    { view: 'Waldläufer', value: 'Ranger' },
+    { view: 'Zauberer', value: 'Sorcerer' },
   ];
 
   public backgrounds: characterData[] = [
@@ -64,11 +65,26 @@ export class CharacterCreatorComponent {
   ];
 
   public genders: characterData[] = [
-    { view: 'Weiblich', value: 'female' },
-    { view: 'Männlich', value: 'male' },
-    { view: 'Divers', value: 'diverse' },
+    { view: 'Weiblich', value: 'Female' },
+    { view: 'Männlich', value: 'Male' },
+    { view: 'Divers', value: 'Diverse' },
   ];
 
+  public spellcastingAttributes: any = {
+    Barbarian: null,
+    Bard: 'Charisma',
+    Cleric: 'Wisdom',
+    Druid: 'Wisdom',
+    Fighter: null,
+    Monk: 'Wisdom',
+    Paladin: 'Charisma',
+    Ranger: 'Wisdom',
+    Rogue: 'Intelligence',
+    Sorcerer: 'Charisma',
+    Warlock: 'Charisma',
+    Wizard: 'Intelligence',
+  };
+
   public characterName: string = '';
   public characterClass: string = '';
   public characterSpecies: string = '';
@@ -240,6 +256,8 @@ export class CharacterCreatorComponent {
         {
           spellslots: [],
           showSpellslots: false,
+          spellcastingAttribute:
+            this.spellcastingAttributes[this.characterClass],
         },
         'spellslots'
       ),

+ 3 - 3
src/app/character/character-picker/character-card/character-card.component.html

@@ -21,8 +21,8 @@
   <div class="content">
     <div class="name">{{ character }}</div>
     <div class="level">Stufe {{ characterData.level }}</div>
-    <div class="species">{{ characterData.race }}</div>
-    <div class="class">{{ characterData.class }}</div>
-    <div class="subclass">{{ characterData.class }}</div>
+    <div class="species">{{ races[characterData.race].display }}</div>
+    <div class="class">{{ classes[characterData.class].display }}</div>
+    <!-- <div class="subclass">{{ characterData.class }}</div> -->
   </div>
 </div>

+ 9 - 1
src/app/character/character-picker/character-card/character-card.component.ts

@@ -1,5 +1,6 @@
 import { Component, Input, Output, EventEmitter } from '@angular/core';
 import { DataService } from 'src/services/data/data.service';
+import { TranslatorService } from 'src/services/translator/translator.service';
 
 @Component({
   selector: 'character-card',
@@ -12,10 +13,17 @@ export class CharacterCardComponent {
   @Output() select: EventEmitter<string> = new EventEmitter<string>();
   public characterData: any = {};
   public image: any;
+  public races: any;
+  public classes: any;
 
-  constructor(private dataAccessor: DataService) {}
+  constructor(
+    private dataAccessor: DataService,
+    private translator: TranslatorService
+  ) {}
 
   ngOnInit() {
+    this.races = this.translator.races;
+    this.classes = this.translator.classes;
     this.dataAccessor
       .getData(this.character, 'characterData')
       .then((characterData: any) => {

+ 1 - 0
src/app/journal/journal-character/class/class.component.ts

@@ -18,5 +18,6 @@ export class ClassComponent {
   public ngOnInit(): void {
     this.className = this.dataAccessor.characterData.class;
     this.class = this.classAccessor.getClassDetails(this.className);
+    console.log(this.class);
   }
 }

+ 98 - 104
src/app/journal/journal-character/general/general.component.html

@@ -1,117 +1,111 @@
 <div class="general-container">
-  <div class="image-container" (click)="onPortraitClicked()">
-    <input
-      id="fileInput"
-      class="upload-input"
-      type="file"
-      (change)="onImageUpload($event)"
-    />
-    <img
-      class="portrait"
-      *ngIf="image"
-      [src]="image"
-      alt="portrait"
-      (click)="onPortraitClicked()"
-    />
-    <img
-      class="upload-icon"
-      src="assets/icons/UIIcons/upload.svg"
-      alt="upload"
-    />
-  </div>
-  <div class="looks">
-    <div class="looks-entry">
-      <div class="looks-label">Volk</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.species"
-        (change)="updateData()"
-      />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Klasse</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.class"
-        (change)="updateData()"
-      />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Geschlecht</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.gender"
-        (change)="updateData()"
-      />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Alter</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.age"
-        (change)="updateData()"
-      />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Größe</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.height"
-        (change)="updateData()"
+  <div class="first-row">
+    <div class="image-container">
+      <img
+        class="image-icon"
+        *ngIf="!image"
+        src="assets/icons/UIIcons/image.svg"
+        alt="Bild"
       />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Gewicht</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.weight"
-        (change)="updateData()"
+      <img class="portrait" *ngIf="image" [src]="image" alt="portrait" />
+      <img
+        class="upload-icon"
+        src="assets/icons/UIIcons/upload.svg"
+        alt="upload"
       />
-    </div>
-    <div class="looks-entry">
-      <div class="looks-label">Haarfarbe</div>
       <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.hair"
-        (change)="updateData()"
+        id="fileInput"
+        class="upload-input"
+        type="file"
+        (change)="onImageUpload($event)"
       />
     </div>
-    <div class="looks-entry">
-      <div class="looks-label">Augenfarbe</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.eyes"
-        (change)="updateData()"
-      />
+    <!-- LOOKS -->
+    <div class="looks">
+      <div class="looks-entry">
+        <label class="looks-label">Volk</label>
+        <div class="looks-field">
+          {{ races[data.race].display }}
+        </div>
+      </div>
+      <div class="looks-entry">
+        <label class="looks-label">Klasse</label>
+        <div class="looks-field">
+          {{ classes[data.class].display }}
+        </div>
+      </div>
+      <div class="looks-entry">
+        <label class="looks-label">Geschlecht</label>
+        <div class="looks-field">
+          {{ genders[data.gender].display }}
+        </div>
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Alter</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.age"
+          (change)="updateData()"
+        />
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Größe</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.height"
+          (change)="updateData()"
+        />
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Gewicht</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.weight"
+          (change)="updateData()"
+        />
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Haarfarbe</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.hair"
+          (change)="updateData()"
+        />
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Augenfarbe</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.eyes"
+          (change)="updateData()"
+        />
+      </div>
+      <div class="looks-entry">
+        <div class="looks-label">Hautfarbe</div>
+        <input
+          type="text"
+          class="looks-input"
+          [(ngModel)]="data.skin"
+          (change)="updateData()"
+        />
+      </div>
     </div>
-    <div class="looks-entry">
-      <div class="looks-label">Hautfarbe</div>
-      <input
-        type="text"
-        class="looks-input"
-        [(ngModel)]="data.skin"
+    <!-- DESCRIPTION -->
+    <div class="description">
+      <textarea
+        class="description-area"
+        [(ngModel)]="data.description"
         (change)="updateData()"
-      />
+      ></textarea>
+      <label class="description-label">Beschreibung</label>
     </div>
   </div>
-
-  <div class="description">
-    <textarea
-      class="description-area"
-      [(ngModel)]="data.description"
-      (change)="updateData()"
-    ></textarea>
-    <label class="description-label">Beschreibung</label>
-  </div>
-
+  <!-- PERSONALITY -->
   <div class="personality">
     <div class="personality-box">
       <textarea

+ 51 - 21
src/app/journal/journal-character/general/general.component.scss

@@ -1,19 +1,32 @@
 .general-container {
     height: 100%;
-    display: grid;
-    grid-template-columns: repeat(20, 1fr);
-    grid-template-rows: repeat(20, 1fr);
+    display: flex;
+    flex-direction: column;
+    row-gap: 2rem;
+}
+
+.first-row {
+    display: flex;
+    justify-content: space-between;
 }
 
 .image-container {
-    grid-column: 1 / 8;
-    grid-row: 1 / 12;
+    width: 24rem;
+    height: 24rem;
     position: relative;
-    cursor: pointer;
+    border: 1px solid var(--border-color);
+    border-radius: 10px;
+    box-shadow: var(--shadow);
+    border-radius: 10px;
+    overflow: hidden;
+
     &:hover {
         .upload-icon {
             opacity: 1;
         }
+        .image-icon {
+            opacity: 0;
+        }
         .portrait {
             filter: brightness(0.8);
         }
@@ -23,8 +36,6 @@
         width: 24rem;
         height: 24rem;
         object-fit: cover;
-        border-radius: 10px;
-        box-shadow: var(--shadow);
         transition: all 0.2s ease-in-out;
     }
 
@@ -41,19 +52,31 @@
         border-radius: 10px;
     }
 
+    .image-icon {
+        position: absolute;
+        opacity: 1;
+        left: 12rem;
+        top: 12rem;
+        width: 3rem;
+        height: 3rem;
+        transform: translate(-50%, -50%);
+        transition: all 0.2s ease-in-out;
+    }
+
     .upload-input {
-        width: 0rem;
-        height: 0rem;
+        width: 100%;
+        height: 100%;
         position: absolute;
+        opacity: 0;
         top: 0;
         left: 0;
+        cursor: pointer;
     }
 }
 
 .looks {
+    width: 25rem;
     padding: 0 2rem;
-    grid-column: 8 / 14;
-    grid-row: 1 / 12;
     display: flex;
     flex-direction: column;
     gap: 1rem;
@@ -68,19 +91,27 @@
             box-shadow: var(--shadow);
             padding-left: 1rem;
         }
+
+        .looks-field {
+            width: 12.5rem;
+            height: 1.75rem;
+            background-color: white;
+            border-radius: 4px;
+            border: 1px solid var(--border-color);
+            box-shadow: var(--shadow);
+            padding-left: 1rem;
+        }
     }
 }
 
 .description {
-    grid-column: 14 / 21;
-    grid-row: 1 / 12;
     display: flex;
     flex-direction: column;
     align-items: center;
     gap: 1rem;
 
     .description-area {
-        width: 75%;
+        width: 20rem;
         height: 90%;
         border: 1px solid var(--border-color);
         border-radius: 10px;
@@ -95,15 +126,14 @@
 }
 
 .personality {
-    grid-column: 1 / 21;
-    grid-row: 13 / 21;
     display: flex;
-    justify-content: space-around;
+    justify-content: space-between;
     align-items: center;
+    gap: 3rem;
 
     .personality-box {
         width: 25%;
-        height: 100%;
+        height: 15rem;
         display: flex;
         flex-direction: column;
         align-items: center;
@@ -111,8 +141,8 @@
         margin-top: 1rem;
 
         .personality-area {
-            width: 85%;
-            height: 70%;
+            width: 100%;
+            height: 100%;
             border: 1px solid var(--border-color);
             border-radius: 10px;
             box-shadow: var(--shadow);

+ 13 - 5
src/app/journal/journal-character/general/general.component.ts

@@ -1,5 +1,6 @@
 import { Component } from '@angular/core';
 import { DataService } from 'src/services/data/data.service';
+import { TranslatorService } from 'src/services/translator/translator.service';
 
 @Component({
   selector: 'general',
@@ -9,15 +10,26 @@ import { DataService } from 'src/services/data/data.service';
 export class GeneralComponent {
   public data: any;
   public image: any;
+  public races: any;
+  public classes: any;
+  public genders: any;
 
-  public constructor(public dataAccessor: DataService) {}
+  public constructor(
+    public dataAccessor: DataService,
+    private translator: TranslatorService
+  ) {}
 
   ngOnInit(): void {
     this.data = this.dataAccessor.characterData;
     this.image = this.dataAccessor.image.value;
+    this.races = this.translator.races;
+    this.classes = this.translator.classes;
+    this.genders = this.translator.genders;
   }
 
   public updateData(): void {
+    console.log(this.data);
+
     this.dataAccessor.characterData = this.data;
   }
 
@@ -30,8 +42,4 @@ export class GeneralComponent {
     };
     reader.readAsDataURL(file);
   }
-
-  public onPortraitClicked(): void {
-    document.getElementById('fileInput')?.click();
-  }
 }

+ 11 - 54
src/app/journal/journal-character/species/species.component.ts

@@ -1,4 +1,6 @@
 import { Component } from '@angular/core';
+import { DataService } from 'src/services/data/data.service';
+import { SpeciesService } from 'src/services/species/species.service';
 
 @Component({
   selector: 'species',
@@ -6,59 +8,14 @@ import { Component } from '@angular/core';
   styleUrl: './species.component.scss',
 })
 export class SpeciesComponent {
-  species: any = {
-    title: 'Eladrin',
-    description: `
-    Eladrin are elves of the Feywild, a realm of perilous beauty and boundless magic. Using that magic, eladrin can step from one place to another in the blink of an eye, and each eladrin resonates with emotions captured in the Feywild in the form of seasons — affinities that affect the eladrin’s mood and appearance. An eladrin’s season can change, though some remain in one season forever. Like other elves, eladrin can live to be over 750 years old.
+  species: any;
+  speciesName: string = '';
 
-    #### Eladrin Seasons
-
-    1. **Autumn:** peace and goodwill, when summer's harvest is shared with all.
-    2. **Winter:** contemplation and dolor, when the vibrant energy of the world slumbers.
-    3. **Spring:** cheerfulness and celebration, marked by merriment and hope as winter's sorrow passes.
-    4. **Summer:** boldness and aggression, a time of unfettered energy and calls to action.
-
-    **Ability Score Increase:** When determining your character’s ability scores, increase one score by 2 and increase a different score by 1, or increase three different scores by 1. You can't raise any of your scores above 20.
-    
-    **Creature Type:** You are a Humanoid. You are also considered an elf for any prerequisite or effect that requires you to be an elf.
-    
-    **Size:** You are Medium.
-    
-    **Speed:** Your walking speed is 30 feet.
-    
-    **Darkvision:** You can see in dim light within 60 feet of you as if it were bright light and in darkness as if it were dim light. You discern colors in that darkness only as shades of gray.
-    
-    **Fey Ancestry:** You have advantage on saving throws you make to avoid or end the charmed condition on yourself.
-    
-    **Fey Step:** As a bonus action, you can magically teleport up to 30 feet to an unoccupied space you can see. You can use this trait a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
-    When you reach 3rd level, your Fey Step gains an additional effect based on your season; if the effect requires a saving throw, the DC equals 8 + your proficiency bonus + your Intelligence, Wisdom, or Charisma modifier (choose when you select this race):
-    - **Autumn** Immediately after you use your Fey Step, up to two creatures of your choice that you can see within 10 feet of you must succeed on a Wisdom saving throw or be charmed by you for 1 minute, or until you or your companions deal any damage to the creatures.
-    - **Winter** When you use your Fey Step, one creature of your choice that you can see within 5 feet of you before you teleport must succeed on a Wisdom saving throw or be frightened of you until the end of your next turn.
-    - **Spring** When you use your Fey Step, you can touch one willing creature within 5 feet of you. That creature then teleports instead of you, appearing in an unoccupied space of your choice that you can see within 30 feet of you.
-    - **Summer** Immediately after you use your Fey Step, each creature of your choice that you can see within 5 feet of you takes fire damage equal to your proficiency bonus.
-   
-    **Keen Senses** You have proficiency in the Perception skill.
-   
-    **Trance** You don’t need to sleep, and magic can’t put you to sleep. You can finish a long rest in 4 hours if you spend those hours in a trancelike meditation, during which you retain consciousness.
-    - Whenever you finish this trance, you can change your season, and you can gain two proficiencies that you don’t have, each one with a weapon or a tool of your choice selected from the Player’s Handbook. You mystically acquire these proficiencies by drawing them from shared elven memory, and you retain them until you finish your next long rest.
-   
-    **Languages** Your character can speak, read, and write Common and one other language that you and your DM agree is appropriate for the character. The Player’s Handbook offers a list of languages to choose from. The DM is free to modify that list for a campaign.
-    
-    `,
-    abilities: [
-      {
-        name: 'Fey Step',
-        level: 0,
-        description: `
-        **Fey Step:** As a bonus action, you can magically teleport up to 30 feet to an unoccupied space you can see. You can use this trait a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
-        When you reach 3rd level, your Fey Step gains an additional effect based on your season; if the effect requires a saving throw, the DC equals 8 + your proficiency bonus + your Intelligence, Wisdom, or Charisma modifier (choose when you select this race):
-        - **Autumn** Immediately after you use your Fey Step, up to two creatures of your choice that you can see within 10 feet of you must succeed on a Wisdom saving throw or be charmed by you for 1 minute, or until you or your companions deal any damage to the creatures.
-        - **Winter** When you use your Fey Step, one creature of your choice that you can see within 5 feet of you before you teleport must succeed on a Wisdom saving throw or be frightened of you until the end of your next turn.
-        - **Spring** When you use your Fey Step, you can touch one willing creature within 5 feet of you. That creature then teleports instead of you, appearing in an unoccupied space of your choice that you can see within 30 feet of you.
-        - **Summer** Immediately after you use your Fey Step, each creature of your choice that you can see within 5 feet of you takes fire damage equal to your proficiency bonus.
-   
-        `,
-      },
-    ],
-  };
+  public constructor(
+    public speciesAccessor: SpeciesService,
+    public dataAccessor: DataService
+  ) {
+    this.speciesName = this.dataAccessor.characterData.race;
+    this.species = speciesAccessor.getSpeciesDetails(this.speciesName);
+  }
 }

+ 19 - 46
src/app/journal/journal-character/subclass/subclass.component.ts

@@ -6,68 +6,41 @@ import { Component } from '@angular/core';
   styleUrl: './subclass.component.scss',
 })
 export class SubclassComponent {
-  public subclass = {
-    title: 'Echo Knight',
+  public subclass: any = {
+    title: 'Peace Domain',
     description: `
-     A mysterious and feared frontline warrior of the Kryn Dynasty, the Echo Knight has mastered the art of using dunamis to summon the fading shades of unrealized timelines to aid them in battle. Surrounded by echoes of their own might, they charge into the fray as a cycling swarm of shadows and strikes.
+      The balm of peace thrives at the heart of healthy communities, between friendly nations, and in the souls of the kindhearted. The gods of peace inspire people of all sorts to resolve conflict and to stand up against those forces that try to prevent peace from flourishing. See the Peace Deities table for a list of some of the gods associated with this domain.
+
+      Clerics of the Peace Domain preside over the signing of treaties, and they are often asked to arbitrate in disputes. These clerics' blessings draw people together and help them shoulder one another's burdens, and the clerics' magic aids those who are driven to fight for the way of peace.
     `,
     features: [
       {
-        name: 'Manifest Echo',
-        level: 3,
-        description: `
-          At 3rd level, you can use a bonus action to magically manifest an echo of yourself in an unoccupied space you can see within 15 feet of you. This echo is a magical, translucent, gray image of you that lasts until it is destroyed, until you dismiss it as a bonus action, until you manifest another echo, or until you're incapacitated.
-
-          Your echo has AC 14 + your proficiency bonus, 1 hit point, and immunity to all conditions. If it has to make a saving throw, it uses your saving throw bonus for the roll. It is the same size as you, and it occupies its space. On your turn, you can mentally command the echo to move up to 30 feet in any direction (no action required). If your echo is ever more than 30 feet from you at the end of your turn, it is destroyed.
-
-          - As a bonus action, you can teleport, magically swapping places with your echo at a cost of 15 feet of your movement, regardless of the distance between the two of you.
-          - When you take the Attack action on your turn, any attack you make with that action can originate from your space or the echo's space. You make this choice for each attack.
-          - When a creature that you can see within 5 feet of your echo moves at least 5 feet away from it, you can use your reaction to make an opportunity attack against that creature as if you were in the echo's space.
-        `,
-      },
-      {
-        name: 'Unleash Incarnation',
-        level: 3,
-        description: `
-          At 3rd level, you can heighten your echo's fury. Whenever you take the Attack action, you can make one additional melee attack from the echo's position.
-
-          You can use this feature a number of times equal to your Constitution modifier (a minimum of once). You regain all expended uses when you finish a long rest.
-        `,
-      },
-      {
-        name: 'Echo Avatar',
-        level: 7,
-        description: `
-          Starting at 7th level, you can temporarily transfer your consciousness to your echo. As an action, you can see through your echo's eyes and hear through its ears. During this time, you are deafened and blinded. You can sustain this effect for up to 10 minutes, and you can end it at any time (requires no action). While your echo is being used in this way, it can be up to 1,000 feet away from you without being destroyed.
-        `,
-      },
-      {
-        name: 'Shadow Martyr',
-        level: 10,
+        name: 'Implement of Peace',
+        level: 1,
         description: `
-          Starting at 10th level, you can make your echo throw itself in front of an attack directed at another creature that you can see. Before the attack roll is made, you can use your reaction to teleport the echo to an unoccupied space within 5 feet of the targeted creature. The attack roll that triggered the reaction is instead made against your echo.
-
-          Once you use this feature, you can't use it again until you finish a short or long rest.
+          When you choose this domain at 1st level, you gain proficiency in the Insight, Performance, or Persuasion skill (your choice).
         `,
       },
       {
-        name: 'Reclaim Potential',
-        level: 15,
+        name: 'Emboldening Bond',
+        level: 1,
         description: `
-          By 15th level, you've learned to absorb the fleeting magic of your echo. When an echo of yours is destroyed by taking damage, you can gain a number of temporary hit points equal to 2d6 + your Constitution modifier, provided you don't already have temporary hit points.
+          Starting at 1st level, you can forge an empowering bond among people who are at peace with one another. As an action, you choose a number of willing creatures within 30 feet of you (this can include yourself) equal to your proficiency bonus. You create a magical bond among them for 10 minutes or until you use this feature again. While any bonded creature is within 30 feet of another, the creature can roll a d4 and add the number rolled to an attack roll, an ability check, or a saving throw it makes. Each creature can add the d4 no more than once per turn.
 
-          You can use this feature a number of times equal to your Constitution modifier (a minimum of once). You regain all expended uses when you finish a long rest.
+          You can use this feature a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
         `,
       },
       {
-        name: 'Legion of One',
-        level: 15,
+        name: 'Channel Divinity: Balm of Peace',
+        level: 2,
         description: `
-          At 18th level, you can use a bonus action to create two echos with your Manifest Echo feature, and these echoes can co-exist. If you try to create a third echo, the previous two echoes are destroyed. Anything you can do from one echo's position can be done from the other's instead.
-
-          In addition, when you roll initiative and have no uses of your Unleash Incarnation feature left, you regain one use of that feature.
+          Starting at 2nd level, you can use your Channel Divinity to make your very presence a soothing balm. As an action, you can move up to your speed, without provoking opportunity attacks, and when you move within 5 feet of any other creature during this action, you can restore a number of hit points to that creature equal to 2d6 + your Wisdom modifier (minimum of 1 hit point). A creature can receive this healing only once whenever you take this action.
         `,
       },
     ],
   };
+
+  public subClassName: string = '';
+
+  // public constru
 }

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

@@ -108,8 +108,8 @@
 
   <div class="settings-container">
     <button class="settings-button" [routerLink]="'../'">
-      <icon [size]="'s'" [type]="'UI'" [icon]="'character'"></icon>
-      <div>Charakterauswahl</div>
+      <icon [size]="'s'" [type]="'UI'" [icon]="'characters'"></icon>
+      <div>Charaktere</div>
     </button>
 
     <button class="settings-button">

+ 16 - 18
src/app/journal/journal-home/navigation-panel/navigation-panel.component.scss

@@ -1,20 +1,20 @@
-.backdrop{
+.backdrop {
     position: fixed;
     top: 0;
     left: 0;
-    right:0;
+    right: 0;
     bottom: 0;
     visibility: hidden;
-    background: rgba(0,0,0,0.2);
+    background: rgba(0, 0, 0, 0.2);
     z-index: 1000;
     cursor: pointer;
 }
 
-.backdrop--open{
+.backdrop--open {
     visibility: visible;
 }
 
-.panel{
+.panel {
     position: fixed;
     top: 0;
     left: 0;
@@ -25,21 +25,19 @@
     padding: 1.5rem;
     transform: translateX(-100%);
     transition: transform 0.3s ease-in-out;
+    overflow: hidden;
 }
 
-.panel--open{
-    transform: translateX(0)
+.panel--open {
+    transform: translateX(0);
 }
 
-.li{
-}
-
-ul{
+ul {
     padding: 0;
     list-style: none;
 }
 
-.navigation-entry{
+.navigation-entry {
     font-size: 1.25rem;
     font-weight: 500;
     margin-bottom: 1rem;
@@ -52,22 +50,23 @@ ul{
     border-radius: 10px;
     transition: transform 0.2s ease-in-out;
 }
-.navigation-entry:hover{
+.navigation-entry:hover {
     background-color: var(--primary-color);
     transform: scale(1.05);
     cursor: pointer;
 }
 
-.settings-container{
+.settings-container {
     display: flex;
     justify-content: space-between;
     position: absolute;
     bottom: 2rem;
-    width: calc(25vw - 3rem)
+    width: calc(25vw - 3rem);
 }
 
-.settings-button{
+.settings-button {
     font-size: 1.25rem;
+    width: 9rem;
     font-weight: 500;
     padding: 0.5rem;
     border: solid 1px var(--border-color);
@@ -77,8 +76,7 @@ ul{
     transition: transform 0.2s ease-in-out;
 }
 
-.settings-button:hover{
+.settings-button:hover {
     background-color: var(--primary-color);
     transform: scale(1.05);
 }
-

+ 10 - 10
src/app/journal/journal-stats/ability-panel/spellslots/spellslots.component.html

@@ -29,6 +29,16 @@
         />
       </ng-container>
     </div>
+    <div style="display: flex; justify-content: space-around; margin-top: 2rem">
+      <div>
+        <div class="value-box">{{ spellSaveDC }}</div>
+        <div class="value-label">Rettungswurf-SG</div>
+      </div>
+      <div>
+        <div class="value-box">{{ spellAttackModifier }}</div>
+        <div class="value-label">Zauber-Angriffsbonus</div>
+      </div>
+    </div>
   </div>
   @if(!kiPoints.showKiPoints && !showSpellslots){
   <div
@@ -42,14 +52,4 @@
     Weder KI-Punkte noch Zauberplätze hinzugefügt
   </div>
   }
-  <div style="display: flex; justify-content: space-around; margin-top: 2rem">
-    <div>
-      <div class="value-box">14</div>
-      <div class="value-label">Rettungswurf-SG</div>
-    </div>
-    <div>
-      <div class="value-box">+6</div>
-      <div class="value-label">Zauber-Angriffsbonus</div>
-    </div>
-  </div>
 </div>

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

@@ -12,6 +12,12 @@ export class SpellslotsComponent {
   public spellslots: any[] = [];
   public showSpellslots: boolean = false;
   public kiPoints: any;
+  public spellcastingAttribute: string | undefined = undefined;
+  public proficiencyBonus: number = 2;
+  public attributeValue: number = 0;
+
+  public spellAttackModifier: number = 0;
+  public spellSaveDC: number = 0;
 
   public slotNumber: number = 1;
 
@@ -20,7 +26,11 @@ export class SpellslotsComponent {
     const kiPoints = this.dataAccessor.kiPoints;
     this.spellslots = spells.spellslots;
     this.showSpellslots = spells.showSpellslots;
+    this.spellcastingAttribute = spells.spellcastingAttribute;
     this.kiPoints = kiPoints;
+    // this.calculateModifiers();
+    this.subscribeToProficiency();
+    this.subscribeToAttribute();
   }
 
   public ngAfterViewInit(): void {
@@ -57,6 +67,41 @@ export class SpellslotsComponent {
     );
   }
 
+  private calculateModifiers(): void {
+    const spellcastingAttribute = this.spellcastingAttribute;
+    console.log('calculateModifiers wurde aufgerufen');
+    console.log('Proficiency: ', this.proficiencyBonus);
+
+    console.log('Attribute: ', this.spellcastingAttribute);
+    console.log('Value: ', this.attributeValue);
+
+    if (spellcastingAttribute !== undefined) {
+      const modifier = (this.attributeValue - 10) / 2;
+      this.spellAttackModifier = modifier + this.proficiencyBonus;
+      this.spellSaveDC = 8 + modifier + this.proficiencyBonus;
+      console.log('Attack: ', this.spellAttackModifier);
+      console.log('Save: ', this.spellSaveDC);
+    }
+  }
+
+  private subscribeToAttribute(): void {
+    if (this.spellcastingAttribute !== undefined) {
+      const command =
+        'this.dataAccessor.' +
+        this.spellcastingAttribute.toLowerCase() +
+        '$.subscribe((attribute) => {this.attributeValue = attribute.value; this.calculateModifiers();});';
+      console.log(command);
+      eval(command);
+    }
+  }
+
+  private subscribeToProficiency(): void {
+    this.dataAccessor.proficiency$.subscribe((value) => {
+      this.proficiencyBonus = value;
+      this.calculateModifiers();
+    });
+  }
+
   // ki points
 
   public handleUsedKiPoints(pointIndex: number, eventTarget: any): void {
@@ -152,6 +197,7 @@ export class SpellslotsComponent {
     this.dataAccessor.spellslots = {
       spellslots: this.spellslots,
       showSpellslots: this.showSpellslots,
+      spellcastingAttribute: this.spellcastingAttribute,
     };
   }
 

+ 8 - 5
src/app/journal/journal-stats/life-container/life/life.component.html

@@ -1,7 +1,6 @@
 <div class="life-box">
   <div class="life-box-name" (click)="openDetailsPanel()">Trefferpunkte</div>
   <div class="life-box-bar" (click)="openDetailsPanel()">
-    <!-- FIXME: The percentages are not shown correctly when using the details panel -->
     <div
       class="life-box-bar-current"
       [style.width.%]="currentHitPointsPercentage"
@@ -20,10 +19,14 @@
     </div>
   </div>
   <div class="life-box-buttons">
-    <button class="life-button" (click)="addHitPoints()">Heilung +</button>
-    <button class="life-button" (click)="addTemporaryHitPoints()">
-      Temporäre Trefferpunkte +
+    <button class="life-button add" (click)="addHitPoints()">
+      <img src="assets/icons/UIIcons/heal.svg" alt="heal" />
+    </button>
+    <button class="life-button temp" (click)="addTemporaryHitPoints()">
+      <img src="assets/icons/UIIcons/temporary.svg" alt="temporary" />
+    </button>
+    <button class="life-button remove" (click)="removeHitPoints()">
+      <img src="assets/icons/UIIcons/damage.svg" alt="damage" />
     </button>
-    <button class="life-button" (click)="removeHitPoints()">Schaden -</button>
   </div>
 </div>

+ 55 - 15
src/app/journal/journal-stats/life-container/life/life.component.scss

@@ -1,4 +1,4 @@
-.life-box{
+.life-box {
     width: 100%;
     height: 100%;
     border: solid 1px var(--border-color);
@@ -7,14 +7,14 @@
     border-radius: 10px;
 }
 
-.life-box-name{
+.life-box-name {
     font-size: 1.4rem;
     font-weight: bold;
     text-align: center;
     cursor: pointer;
 }
 
-.life-box-bar{
+.life-box-bar {
     position: relative;
     display: flex;
     flex-direction: row;
@@ -23,21 +23,37 @@
     border-radius: 10px;
     overflow: hidden;
     cursor: pointer;
+    &:hover {
+        .life-box-bar-current {
+            background-color: var(--accept-hover);
+        }
+
+        .life-box-bar-temporary {
+            background-color: var(--edit-hover);
+        }
+
+        .life-box-bar-missing {
+            background-color: var(--delete-hover);
+        }
+    }
 }
 
-.life-box-bar-current{
-    background-color: rgba(12, 105, 1, 0.4);
+.life-box-bar-current {
+    background-color: var(--accept);
+    transition: all 0.2s ease-in-out;
 }
 
-.life-box-bar-temporary{
-    background-color: rgba(140, 254, 125, 0.4);
+.life-box-bar-temporary {
+    background-color: var(--edit);
+    transition: all 0.2s ease-in-out;
 }
 
-.life-box-bar-missing{
-    background-color: rgba(111, 0, 0, 0.5);
+.life-box-bar-missing {
+    background-color: var(--delete);
+    transition: all 0.2s ease-in-out;
 }
 
-.life-box-bar-label{
+.life-box-bar-label {
     font-size: 1.5rem;
     font-weight: bold;
     position: absolute;
@@ -46,19 +62,43 @@
     transform: translate(-50%, -50%);
 }
 
-.life-box-buttons{
+.life-box-buttons {
     display: flex;
     justify-content: space-between;
     margin: 1rem;
     // flex-direction: column;
 }
 
-.life-button{
-    min-height: 2rem;
+.life-button {
+    height: 2.5rem;
+    width: 6rem;
     font-size: 1.25rem;
     font-weight: 500;
-    border: solid 1px var(--border-color);
-    background-color: var(--quaternary-color-light);
+    border: none;
     box-shadow: var(--shadow-small);
     border-radius: 10px;
 }
+
+.add {
+    background-color: var(--accept);
+    transition: all 0.2s ease-in-out;
+    &:hover {
+        background-color: var(--accept-hover);
+    }
+}
+
+.temp {
+    background-color: var(--edit);
+    transition: all 0.2s ease-in-out;
+    &:hover {
+        background-color: var(--edit-hover);
+    }
+}
+
+.remove {
+    background-color: var(--delete);
+    transition: all 0.2s ease-in-out;
+    &:hover {
+        background-color: var(--delete-hover);
+    }
+}

+ 2 - 2
src/app/journal/journal-stats/weapons-container/spell-table/spell-table.component.ts

@@ -179,7 +179,7 @@ export class SpellTableComponent {
 
   private subscribeToData(): void {
     // TODO: this.dataAccessor.getSpellcastingAttribute() oder so
-    this.spellcastingAttribute = 'intelligence';
+    this.spellcastingAttribute = 'wisdom';
 
     this.dataAccessor.proficiency$.subscribe((value) => {
       this.proficiencyBonus = value;
@@ -188,7 +188,7 @@ export class SpellTableComponent {
       }
     });
     // TODO: Modify depending on the actual spellcasting attribute
-    this.dataAccessor.intelligence$.subscribe((value) => {
+    this.dataAccessor.wisdom$.subscribe((value) => {
       this.spellcastingAttributeModifier = Math.floor((value.value - 10) / 2);
       this.computeSpellAttackBonusAndSaveDC();
     });

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

@@ -1,6 +1,6 @@
 import { NgModule } from '@angular/core';
 import { CommonModule } from '@angular/common';
-import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
+import { NgbModule, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
 import { FormsModule } from '@angular/forms';
 import { CdkTableModule } from '@angular/cdk/table';
 import { DragDropModule } from '@angular/cdk/drag-drop';
@@ -175,6 +175,7 @@ import { StoryComponent } from './journal-character/story/story.component';
     CommonModule,
     JournalRoutingModule,
     NgbModule,
+    NgbDropdownModule,
     FormsModule,
     CdkTableModule,
     DragDropModule,

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

@@ -1 +0,0 @@
-<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="M255 45.4c-24.5 0-47 11.8-63.9 33.4-16.9 21.5-27.1 52.6-27.1 86.5 0 36 12.1 67.5 31 89.5l13.5 15-19.6 4.6c-52.3 11.9-77.4 36.9-91.75 75.2-13.7 35.7-15.6 84.8-16.1 143.3H431c-.2-58.7-.5-109.3-13-145.5-13.4-39.4-37.9-64.3-94-75.4l-19.9-3.7 12.9-15.7c17.7-21.9 28.8-52.6 28.8-87.5 0-33.9-10.3-64.9-27.2-86.3-16.8-21.7-39.3-33.6-63.6-33.4z" fill="#000000" fill-opacity="1"></path></g></svg>

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

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-480q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47ZM160-160v-112q0-34 17.5-62.5T224-378q62-31 126-46.5T480-440q66 0 130 15.5T736-378q29 15 46.5 43.5T800-272v112H160Zm80-80h480v-32q0-11-5.5-20T700-306q-54-27-109-40.5T480-360q-56 0-111 13.5T260-306q-9 5-14.5 14t-5.5 20v32Zm240-320q33 0 56.5-23.5T560-640q0-33-23.5-56.5T480-720q-33 0-56.5 23.5T400-640q0 33 23.5 56.5T480-560Zm0-80Zm0 400Z"/></svg>

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

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-501Zm0 381L313-234q-72-65-123.5-116t-85-96q-33.5-45-49-87T40-621q0-94 63-156.5T260-840q52 0 99 22t81 62q34-40 81-62t99-22q84 0 153 59t69 160q0 14-2 29.5t-6 31.5h-85q5-18 8-34t3-30q0-75-50-105.5T620-760q-51 0-88 27.5T463-660h-46q-31-45-70.5-72.5T260-760q-57 0-98.5 39.5T120-621q0 33 14 67t50 78.5q36 44.5 98 104T440-228q26-23 61-53t56-50l9 9 19.5 19.5L605-283l9 9q-22 20-56 49.5T498-172l-58 52Zm160-280v-80h320v80H600Z"/></svg>

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

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-501Zm0 381L313-234q-72-65-123.5-116t-85-96q-33.5-45-49-87T40-621q0-94 63-156.5T260-840q52 0 99 22t81 62q34-40 81-62t99-22q81 0 136 45.5T831-680h-85q-18-40-53-60t-73-20q-51 0-88 27.5T463-660h-46q-31-45-70.5-72.5T260-760q-57 0-98.5 39.5T120-621q0 33 14 67t50 78.5q36 44.5 98 104T440-228q26-23 61-53t56-50l9 9 19.5 19.5L605-283l9 9q-22 20-56 49.5T498-172l-58 52Zm280-160v-120H600v-80h120v-120h80v120h120v80H800v120h-80Z"/></svg>

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

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm40-80h480L570-480 450-320l-90-120-120 160Zm-40 80v-560 560Z"/></svg>

+ 0 - 1
src/assets/icons/UIIcons/life-minus.svg

@@ -1 +0,0 @@
-<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="M372.48 31.215c-77.65 0-116.48 65.73-116.48 65.73s-38.83-65.72-116.48-65.72c-37.14 0-107.77 33.72-107.77 125.13 0 161.24 224.25 324.43 224.25 324.43s224.25-163.19 224.25-324.43c0-91.42-70.63-125.13-107.77-125.14zM146.924 225.65h220v60.7h-220z" fill="#060606" fill-opacity="1"></path></g></svg>

+ 0 - 1
src/assets/icons/UIIcons/life-plus.svg

@@ -1 +0,0 @@
-<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="M372.48 31.215c-77.65 0-116.48 65.73-116.48 65.73s-38.83-65.72-116.48-65.72c-37.14 0-107.77 33.72-107.77 125.13 0 161.24 224.25 324.43 224.25 324.43s224.25-163.19 224.25-324.43c0-91.42-70.63-125.13-107.77-125.14zm-145.492 115.02h60.698v79.415h79.238v60.7h-79.238v79.884h-60.698V286.35h-80.064v-60.7h80.064z" fill="#060606" fill-opacity="1"></path></g></svg>

+ 0 - 1
src/assets/icons/UIIcons/life-temporary.svg

@@ -1 +0,0 @@
-<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="M256 32c-64 48-128 64-224 96 0 128 160 320 224 368 64-48 224-240 224-368-96-32-160-48-224-96zm0 34.75l5.4 4.05c49.7 37.3 99.6 49.9 176.7 75.6l6.2 2v6.5c0 55-33.1 119.7-72 176.4-38.9 56.8-83.6 105-110.9 125.5l-5.4 4.1-5.4-4.1c-27.3-20.5-72-68.7-110.9-125.5-38.9-56.7-72-121.4-72-176.4v-6.5l6.15-2C150.9 120.7 200.9 108 250.6 70.8l5.4-4.05zm0 22.18c-49.4 35.37-99.8 49.17-170.05 72.37 2.58 46.7 32.35 107 68.65 159.9 35.3 51.5 76.6 96.3 101.4 116.8 24.8-20.5 66.1-65.3 101.4-116.8 36.3-52.9 66.1-113.2 68.6-159.9-70.3-23.2-120.6-37-170-72.37zm-45.5 54.97c19.7.5 38.1 14.4 45.5 48.1 18-86.3 110-42.5 110 22.5-1 63.9-92 107.7-110 162.1-19-54.4-108-98.2-110-162.1 0-39.6 33.8-71.3 64.5-70.6z" fill="#060606" fill-opacity="1"></path></g></svg>

+ 1 - 1
src/assets/icons/UIIcons/settings.svg

@@ -1 +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="M234.875 18.78c-26.087 2.367-51.557 8.56-74.875 18.782 15.37 32.763 14.222 66.706-6.72 82.407-20.835 15.617-54.055 7.965-81.124-15.69-16.246 19.452-29.336 41.36-38.875 65.626 33.83 12.333 56.635 37.665 52.94 63.5-3.698 25.835-32.697 43.74-68.626 46.094 2.338 25.796 8.91 50.778 18.937 73.875 17.81-8.182 35.793-11.09 51.095-8.938 13.032 1.87 23.927 7.015 31.156 16.657 15.817 21.097 7.603 54.713-16.78 81.97 19.516 16.35 42.216 29.444 66.594 39.03 12.33-33.828 37.655-56.634 63.5-52.938 25.844 3.697 43.74 32.696 46.094 68.625 26.087-2.365 51.557-8.555 74.875-18.78-15.766-32.997-14.26-67.588 6.843-83.406 9.64-7.23 22.568-9.022 35.594-7.125 15.112 2.16 31.19 10.25 45.563 22.78 16.088-19.345 29.4-41.51 38.875-65.594-33.83-12.332-56.635-37.653-52.938-63.5 3.697-25.846 32.665-43.772 68.594-46.125-2.36-25.944-8.774-50.663-18.906-73.874-32.612 15.117-66.66 13.145-82.282-7.687-15.696-20.944-7.252-53.86 16.688-81-19.52-16.352-42.248-29.447-66.625-39.032-12.332 33.828-37.657 56.66-63.5 52.968-25.846-3.693-43.744-32.696-46.095-68.625zm21.656 95.126c79.626 0 144.376 64.752 144.376 144.375 0 79.626-64.75 144.376-144.375 144.376-79.624 0-144.374-64.75-144.374-144.375 0-79.624 64.75-144.374 144.375-144.374zm0 18.688c-69.524 0-125.686 56.162-125.686 125.687 0 69.526 56.162 125.69 125.687 125.69 69.526 0 125.69-56.164 125.69-125.69 0-69.522-56.164-125.686-125.69-125.686zm.033 15.125c61.094 0 110.625 49.53 110.625 110.624 0 61.095-49.53 110.625-110.625 110.625s-110.625-49.53-110.625-110.626c0-61.095 49.53-110.625 110.625-110.625z" fill="#000000" fill-opacity="1"></path></g></svg>
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/></svg>

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

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-320q102-92 131-129.5t29-74.5q0-36-26-62t-62-26q-21 0-40.5 8.5T480-580q-12-15-31-23.5t-41-8.5q-36 0-62 26t-26 62q0 19 5 35t22 37.5q17 21.5 48.5 52.5t84.5 79Zm0 240q-139-35-229.5-159.5T160-516v-244l320-120 320 120v244q0 152-90.5 276.5T480-80Zm0-84q104-33 172-132t68-220v-189l-240-90-240 90v189q0 121 68 220t172 132Zm0-316Z"/></svg>

+ 109 - 14
src/services/class/class.service.ts

@@ -10,14 +10,14 @@ export class ClassService {
 
   public getClassDetails(className: string): any {
     switch (className) {
-      case 'fighter':
+      case 'Fighter':
         return this.fighter;
-      case 'barbarian':
+      case 'Barbarian':
         return this.barbarian;
-      case 'cleric':
+      case 'Cleric':
         return this.cleric;
       default:
-        throw new Error('DND-Error: Class not found in class.service.ts');
+        return this.notImplementedYet;
     }
   }
 
@@ -369,9 +369,9 @@ export class ClassService {
   };
 
   public cleric: any = {
-    title: 'Kleriker',
+    title: 'Cleric',
     description: `
-    Clerics act as conduits for that power, manifesting it as miraculous effects. The gods don't grant this power to everyone who seeks it, but only to those chosen to fulfill a high calling.
+    Clerics are intermediaries between the mortal world and the distant planes of the gods. As varied as the gods they serve, clerics strive to embody the handiwork of their deities. No ordinary priest, a cleric is imbued with divine magic.
 
     ### Class Features
 
@@ -402,26 +402,121 @@ export class ClassService {
     - (a) a light crossbow and 20 bolts or (b) any simple weapon
     - (a) a priest's pack or (b) an explorer's pack
     - A shield and a holy symbol
+
+    ### Spellcasting
+
+    As a conduit for divine power, you can cast cleric spells.
+
+    #### Cantrips
+
+    At 1st level, you know three cantrips of your choice from the cleric spell list. You learn additional cleric cantrips of your choice at higher levels, as shown in the Cantrips Known column of the Cleric table.
+
+    #### Spell Slots
+
+    The Cleric table shows how many spell slots you have to cast your cleric spells of 1st level and higher. To cast one of these spells, you must expend a slot of the spell's level or higher. You regain all expended spell slots when you finish a long rest.
+
+    You prepare the list of cleric spells that are available for you to cast, choosing from the cleric spell list. When you do so, choose a number of cleric spells equal to your Wisdom modifier + your cleric level (minimum of one spell). The spells must be of a level for which you have spell slots.
+
+    For example, if you are a 3rd-level cleric, you have four 1st-level and two 2nd-level spell slots. With a Wisdom of 16, your list of prepared spells can include six spells of 1st or 2nd level, in any combination. If you prepare the 1st-level spell Cure Wounds, you can cast it using a 1st-level or 2nd-level slot. Casting the spell doesn't remove it from your list of prepared spells.
+
+    You can change your list of prepared spells when you finish a long rest. Preparing a new list of cleric spells requires time spent in prayer and meditation: at least 1 minute per spell level for each spell on your list.
+
+    #### Spellcasting Ability
+
+    Wisdom is your spellcasting ability for your cleric spells. The power of your spells comes from your devotion to your deity. You use your Wisdom whenever a cleric spell refers to your spellcasting ability. In addition, you use your Wisdom modifier when setting the saving throw DC for a cleric spell you cast and when making an attack roll with one.
+
+    **Spell save DC:** 8 + your proficiency bonus + your Wisdom modifier
+
+    **Spell attack modifier:** your proficiency bonus + your Wisdom modifier
+
     `,
     features: [
       {
-        name: 'Spellcasting',
+        name: 'Divine Domain',
         level: 1,
         description: `
-          As a conduit for divine power, you can cast cleric spells.
+          At 1st level, you choose a domain shaped by your choice of Deity and the gifts they grant you. Your choice grants you domain spells and other features when you choose it at 1st level. It also grants you additional ways to use Channel Divinity when you gain that feature at 2nd level, and additional benefits at 6th, 8th, and 17th levels.
+          `,
+      },
+      {
+        name: 'Channel Divinity',
+        level: 2,
+        description: `
+          At 2nd level, you gain the ability to channel divine energy directly from your deity, using that energy to fuel magical effects. You start with two such effects: Turn Undead and an effect determined by your domain. Some domains grant you additional effects as you advance in levels, as noted in the domain description.
 
-          Cantrips
+          When you use your Channel Divinity, you choose which effect to create. You must then finish a short or long rest to use your Channel Divinity again.
 
-          At 1st level, you know three cantrips of your choice from the cleric spell list. You learn additional cleric cantrips of your choice at higher levels, as shown in the Cantrips Known column of the Cleric table.
+          Some Channel Divinity effects require saving throws. When you use such an effect from this class, the DC equals your cleric spell save DC.
 
-          Preparing and Casting Spells
+          Beginning at 6th level, you can use your Channel Divinity twice between rests, and beginning at 18th level, you can use it three times between rests. When you finish a short or long rest, you regain your expended uses.
+          `,
+      },
+      {
+        name: 'Channel Divinity Turn Undead',
+        level: 2,
+        description: `
+          As an action, you present your holy symbol and speak a prayer censuring the undead. Each undead that can see or hear you within 30 feet of you must make a Wisdom saving throw. If the creature fails its saving throw, it is turned for 1 minute or until it takes any damage.
 
-          The Cleric table shows how many spell slots you have to cast your cleric spells of 1st level and higher. To cast one of these spells, you must expend a slot of the spell's level or higher. You regain all expended spell slots when you finish a long rest.
+          A turned creature must spend its turns trying to move as far away from you as it can, and it can't willingly move to a space within 30 feet of you. It also can't take reactions. For its action, it can use only the Dash action or try to escape from an effect that prevents it from moving. If there's nowhere to move, the creature can use the Dodge action.
+          `,
+      },
+      {
+        name: 'Harness Divine Power',
+        level: 2,
+        description: `
+          At 2nd level, you can expend a use of your Channel Divinity to fuel your spells. As a bonus action, you touch your holy symbol, utter a prayer, and regain one expended spell slot, the level of which can be no higher than half your proficiency bonus (rounded up). The number of times you can use this feature is based on the level you've reached in this class: 2nd level, once; 6th level, twice; and 18th level, thrice. You regain all expended uses when you finish a long rest.
+          `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 4,
+        description: `
+          When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
+          `,
+      },
+      {
+        name: 'Destroy Undead',
+        level: 5,
+        description: `
+          Starting at 5th level, when an undead fails its saving throw against your Turn Undead feature, the creature is instantly destroyed if its challenge rating is at or below a certain threshold, as shown in the Cleric table above.          `,
+      },
+      {
+        name: 'Blessed Strikes',
+        level: 8,
+        description: `
+          Replaces the Divine Strike or Potent Spellcasting feature
 
-          You prepare the list of cleric spells that are available for you to cast, choosing from the cleric spell list. When you do so, choose a number of cleric spells equal to your Wisdom modifier + your cleric level (minimum of one spell).
-          The spells must be of a level for which you have spell slots.
+          When you reach 8th level, you are blessed with divine might in battle. When a creature takes damage from one of your cantrips or weapon attacks, you can also deal 1d8 radiant damage to that creature. Once you deal this damage, you can't use this feature again until the start of your next turn.
+        `,
+      },
+      {
+        name: 'Ability Score Improvement',
+        level: 8,
+        description: `
+          When you reach 4th level, and again at 8th, 12th, 16th, and 19th level, you can increase one ability score of your choice by 2, or you can increase two ability scores of your choice by 1. As normal, you can't increase an ability score above 20 using this feature.  
           `,
       },
+      {
+        name: 'Divine Intervention',
+        level: 10,
+        description: `
+          Beginning at 10th level, you can call on your deity to intervene on your behalf when your need is great.
+
+          Imploring your deity's aid requires you to use your action. Describe the assistance you seek, and roll percentile dice. If you roll a number equal to or lower than your cleric level, your deity intervenes. The GM chooses the nature of the intervention; the effect of any cleric spell or cleric domain spell would be appropriate.
+
+          If your deity intervenes, you can't use this feature again for 7 days. Otherwise, you can use it again after you finish a long rest.
+
+          At 20th level, your call for intervention succeeds automatically, no roll required.
+        `,
+      },
     ],
   };
+
+  private notImplementedYet: any = {
+    title: 'Not implemented yet',
+    description: `
+    This class is not implemented yet. Please check back later.
+    `,
+    features: [],
+  };
 }

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

@@ -338,6 +338,7 @@ export class DataService {
   private _spellslots: any = {
     spellslots: [],
     showSpellslots: true,
+    spellcastingAttribute: undefined,
   };
 
   public get spellslots(): any {

+ 117 - 2
src/services/species/species.service.ts

@@ -1,9 +1,124 @@
 import { Injectable } from '@angular/core';
 
 @Injectable({
-  providedIn: 'root'
+  providedIn: 'root',
 })
 export class SpeciesService {
+  constructor() {}
 
-  constructor() { }
+  public getSpeciesDetails(name: string): any {
+    switch (name) {
+      case 'Eladrin':
+        return this.eladrin;
+      case 'HalfElfDetection':
+        return this.halfElfDetection;
+      default:
+        // throw new Error(`DND-Error: Species ${name} not found`);
+        return this.notImplementedYet;
+    }
+  }
+
+  private eladrin: any = {
+    title: 'Eladrin',
+    description: `
+    Eladrin are elves of the Feywild, a realm of perilous beauty and boundless magic. Using that magic, eladrin can step from one place to another in the blink of an eye, and each eladrin resonates with emotions captured in the Feywild in the form of seasons — affinities that affect the eladrin’s mood and appearance. An eladrin’s season can change, though some remain in one season forever. Like other elves, eladrin can live to be over 750 years old.
+
+    #### Eladrin Seasons
+
+    1. **Autumn:** peace and goodwill, when summer's harvest is shared with all.
+    2. **Winter:** contemplation and dolor, when the vibrant energy of the world slumbers.
+    3. **Spring:** cheerfulness and celebration, marked by merriment and hope as winter's sorrow passes.
+    4. **Summer:** boldness and aggression, a time of unfettered energy and calls to action.
+
+    **Ability Score Increase:** When determining your character’s ability scores, increase one score by 2 and increase a different score by 1, or increase three different scores by 1. You can't raise any of your scores above 20.
+    
+    **Creature Type:** You are a Humanoid. You are also considered an elf for any prerequisite or effect that requires you to be an elf.
+    
+    **Size:** You are Medium.
+    
+    **Speed:** Your walking speed is 30 feet.
+    
+    **Darkvision:** You can see in dim light within 60 feet of you as if it were bright light and in darkness as if it were dim light. You discern colors in that darkness only as shades of gray.
+    
+    **Fey Ancestry:** You have advantage on saving throws you make to avoid or end the charmed condition on yourself.
+    
+    **Fey Step:** As a bonus action, you can magically teleport up to 30 feet to an unoccupied space you can see. You can use this trait a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
+    When you reach 3rd level, your Fey Step gains an additional effect based on your season; if the effect requires a saving throw, the DC equals 8 + your proficiency bonus + your Intelligence, Wisdom, or Charisma modifier (choose when you select this race):
+    - **Autumn** Immediately after you use your Fey Step, up to two creatures of your choice that you can see within 10 feet of you must succeed on a Wisdom saving throw or be charmed by you for 1 minute, or until you or your companions deal any damage to the creatures.
+    - **Winter** When you use your Fey Step, one creature of your choice that you can see within 5 feet of you before you teleport must succeed on a Wisdom saving throw or be frightened of you until the end of your next turn.
+    - **Spring** When you use your Fey Step, you can touch one willing creature within 5 feet of you. That creature then teleports instead of you, appearing in an unoccupied space of your choice that you can see within 30 feet of you.
+    - **Summer** Immediately after you use your Fey Step, each creature of your choice that you can see within 5 feet of you takes fire damage equal to your proficiency bonus.
+   
+    **Keen Senses** You have proficiency in the Perception skill.
+   
+    **Trance** You don’t need to sleep, and magic can’t put you to sleep. You can finish a long rest in 4 hours if you spend those hours in a trancelike meditation, during which you retain consciousness.
+    - Whenever you finish this trance, you can change your season, and you can gain two proficiencies that you don’t have, each one with a weapon or a tool of your choice selected from the Player’s Handbook. You mystically acquire these proficiencies by drawing them from shared elven memory, and you retain them until you finish your next long rest.
+   
+    **Languages** Your character can speak, read, and write Common and one other language that you and your DM agree is appropriate for the character. The Player’s Handbook offers a list of languages to choose from. The DM is free to modify that list for a campaign.
+    
+    `,
+    abilities: [
+      {
+        name: 'Fey Step',
+        level: 0,
+        description: `
+        **Fey Step:** As a bonus action, you can magically teleport up to 30 feet to an unoccupied space you can see. You can use this trait a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
+        When you reach 3rd level, your Fey Step gains an additional effect based on your season; if the effect requires a saving throw, the DC equals 8 + your proficiency bonus + your Intelligence, Wisdom, or Charisma modifier (choose when you select this race):
+        - **Autumn** Immediately after you use your Fey Step, up to two creatures of your choice that you can see within 10 feet of you must succeed on a Wisdom saving throw or be charmed by you for 1 minute, or until you or your companions deal any damage to the creatures.
+        - **Winter** When you use your Fey Step, one creature of your choice that you can see within 5 feet of you before you teleport must succeed on a Wisdom saving throw or be frightened of you until the end of your next turn.
+        - **Spring** When you use your Fey Step, you can touch one willing creature within 5 feet of you. That creature then teleports instead of you, appearing in an unoccupied space of your choice that you can see within 30 feet of you.
+        - **Summer** Immediately after you use your Fey Step, each creature of your choice that you can see within 5 feet of you takes fire damage equal to your proficiency bonus.
+   
+        `,
+      },
+    ],
+  };
+
+  private halfElfDetection: any = {
+    title: 'Half-Elf (Mark of Detection)',
+    description: `
+    Walking in two worlds but truly belonging to neither, half-elves combine what some say are the best qualities of their elf and human parents: human curiosity, inventiveness, and ambition tempered by the refined senses, love of nature, and artistic tastes of the elves.
+
+    **Ability Score Increase:** Your Wisdom score increases by 2, and one other Ability Score of your choice increases by 1.
+    
+    **Creature Type:** You are a Humanoid. You are also considered an elf for any prerequisite or effect that requires you to be an elf.
+    
+    **Size:** You are Medium.
+    
+    **Speed:** Your walking speed is 35 feet.
+    
+    **Darkvision:** You can see in dim light within 60 feet of you as if it were bright light and in darkness as if it were dim light. You discern colors in that darkness only as shades of gray.
+    
+    **Fey Ancestry:** You have advantage on saving throws you make to avoid or end the charmed condition on yourself.
+    
+    **Skill Versatility:** You gain proficiency in two skills of your choice.
+    
+    **Languages:** Your character can speak, read, and write Common, Elvish, and one extra language of your choice.
+    
+    **Deductive Intuition:** Whenever you make a Intelligence (Investigation) or a Wisdom (Insight) check, you can roll a d4 and add the number rolled to the total ability check.
+
+    **Magical Detection:** You can cast the Detect Magic and the Detect Poison and Disease spells with this trait. Starting at 3rd level, you can also cast the See Invisibility spell with it. Once you cast either spell with this trait, you can't cast that spell again until you finish a Long Rest. Intelligence is your Spellcasting Ability for these spells, and you don't require material components for them.
+
+    **Spells of the Mark:** If you have the Spellcasting or Pact Magic class feature, the spells on the Mark of Detection Spells table are added to the spell list of your Spellcasting class.
+
+    **Mark of Detection Spells**
+
+    | Spell Level | Spells |
+    | ----------- | ------ |
+    | 1st | Detect Magic, Detect Poison and Disease |
+    | 2nd | See Invisibility |
+    | 3rd | Clairvoyance, Tongues |
+    | 4th | Arcane Eye, Locate Creature |
+    | 5th | Legend Lore, Rary's Telepathic Bond |
+    
+    `,
+    abilities: [],
+  };
+
+  private notImplementedYet: any = {
+    title: 'Not Implemented Yet',
+    description: `
+    `,
+    abilities: [],
+  };
 }

+ 29 - 0
src/services/spells/spells.service.ts

@@ -25,6 +25,7 @@ export class SpellsService {
 
   private level1: string[] = [
     'Wunden Heilen (Cure Wounds)',
+    'Wunden hinzufügen (Inflict Wounds)',
     'Magie entdecken (Detect Magic)',
     'Gift und Krankheiten entdecken (Detect Poison and Disease)',
     'Segnen (Bless)',
@@ -87,6 +88,8 @@ export class SpellsService {
         return this.thaumaturgie;
       case 'Wunden Heilen (Cure Wounds)':
         return this.cureWounds;
+      case 'Wunden hinzufügen (Inflict Wounds)':
+        return this.inflictWounds;
       case 'Magie entdecken (Detect Magic)':
         return this.detectMagic;
       case 'Segnen (Bless)':
@@ -106,6 +109,32 @@ export class SpellsService {
     }
   }
 
+  private inflictWounds: Spell = {
+    name: 'Wunden hinzufügen',
+    level: 1,
+    cost: 'action',
+    duration: 0,
+    canRitual: false,
+    needsVerbal: true,
+    needsSomatic: true,
+    needsMaterial: false,
+    needsConcentration: false,
+    needsAttackRoll: true,
+    needsSavingThrow: false,
+    doesDamage: true,
+    damage: [{ diceNumber: '3', diceType: 'd10', damageType: 'necrotic' }],
+    doesHeal: false,
+    heal: { diceNumber: '', diceType: '', additionalHeal: 0 },
+    description:
+      'Mach einen Nahkampf-Zauberangriff gegen eine Kreatur deiner Wahl. Bei einem Erfolg erleidet das Ziel 3W10 Nekrotischen Schaden. Auf höheren Graden: Wirkst du diesen Zauber, indem du einen Zauberplatz des 2. Grades oder höher nutzt, steigt der Schaden für jeden Grad über dem 1. um 1W10.',
+    school: 'necromancy',
+    isRanged: false,
+    range: 5,
+    hasAreaOfEffect: false,
+    areaOfEffectType: '',
+    radius: 0,
+  };
+
   private guidance: Spell = {
     name: 'Göttliche Führung',
     level: 0,

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

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

+ 115 - 0
src/services/subclass/subclass.service.ts

@@ -0,0 +1,115 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class SubclassService {
+  public getSubclassDetails(subclass: string): any {
+    switch (subclass) {
+      case 'Echo Knight':
+        return this.echoKnight;
+      case 'PeaceDomain':
+        return this.peaceDomain;
+      default:
+        return null;
+    }
+  }
+
+  private peaceDomain: any = {
+    title: 'Peace Domain',
+    description: `
+      The balm of peace thrives at the heart of healthy communities, between friendly nations, and in the souls of the kindhearted. The gods of peace inspire people of all sorts to resolve conflict and to stand up against those forces that try to prevent peace from flourishing. See the Peace Deities table for a list of some of the gods associated with this domain.
+
+      Clerics of the Peace Domain preside over the signing of treaties, and they are often asked to arbitrate in disputes. These clerics' blessings draw people together and help them shoulder one another's burdens, and the clerics' magic aids those who are driven to fight for the way of peace.
+    `,
+    features: [
+      {
+        name: 'Implement of Peace',
+        level: 1,
+        description: `
+          When you choose this domain at 1st level, you gain proficiency in the Insight, Performance, or Persuasion skill (your choice).
+        `,
+      },
+      {
+        name: 'Emboldening Bond',
+        level: 1,
+        description: `
+          Starting at 1st level, you can forge an empowering bond among people who are at peace with one another. As an action, you choose a number of willing creatures within 30 feet of you (this can include yourself) equal to your proficiency bonus. You create a magical bond among them for 10 minutes or until you use this feature again. While any bonded creature is within 30 feet of another, the creature can roll a d4 and add the number rolled to an attack roll, an ability check, or a saving throw it makes. Each creature can add the d4 no more than once per turn.
+
+          You can use this feature a number of times equal to your proficiency bonus, and you regain all expended uses when you finish a long rest.
+        `,
+      },
+      {
+        name: 'Channel Divinity: Balm of Peace',
+        level: 2,
+        description: `
+          Starting at 2nd level, you can use your Channel Divinity to make your very presence a soothing balm. As an action, you can move up to your speed, without provoking opportunity attacks, and when you move within 5 feet of any other creature during this action, you can restore a number of hit points to that creature equal to 2d6 + your Wisdom modifier (minimum of 1 hit point). A creature can receive this healing only once whenever you take this action.
+        `,
+      },
+    ],
+  };
+  private echoKnight: any = {
+    title: 'Echo Knight',
+    description: `
+     A mysterious and feared frontline warrior of the Kryn Dynasty, the Echo Knight has mastered the art of using dunamis to summon the fading shades of unrealized timelines to aid them in battle. Surrounded by echoes of their own might, they charge into the fray as a cycling swarm of shadows and strikes.
+    `,
+    features: [
+      {
+        name: 'Manifest Echo',
+        level: 3,
+        description: `
+          At 3rd level, you can use a bonus action to magically manifest an echo of yourself in an unoccupied space you can see within 15 feet of you. This echo is a magical, translucent, gray image of you that lasts until it is destroyed, until you dismiss it as a bonus action, until you manifest another echo, or until you're incapacitated.
+
+          Your echo has AC 14 + your proficiency bonus, 1 hit point, and immunity to all conditions. If it has to make a saving throw, it uses your saving throw bonus for the roll. It is the same size as you, and it occupies its space. On your turn, you can mentally command the echo to move up to 30 feet in any direction (no action required). If your echo is ever more than 30 feet from you at the end of your turn, it is destroyed.
+
+          - As a bonus action, you can teleport, magically swapping places with your echo at a cost of 15 feet of your movement, regardless of the distance between the two of you.
+          - When you take the Attack action on your turn, any attack you make with that action can originate from your space or the echo's space. You make this choice for each attack.
+          - When a creature that you can see within 5 feet of your echo moves at least 5 feet away from it, you can use your reaction to make an opportunity attack against that creature as if you were in the echo's space.
+        `,
+      },
+      {
+        name: 'Unleash Incarnation',
+        level: 3,
+        description: `
+          At 3rd level, you can heighten your echo's fury. Whenever you take the Attack action, you can make one additional melee attack from the echo's position.
+
+          You can use this feature a number of times equal to your Constitution modifier (a minimum of once). You regain all expended uses when you finish a long rest.
+        `,
+      },
+      {
+        name: 'Echo Avatar',
+        level: 7,
+        description: `
+          Starting at 7th level, you can temporarily transfer your consciousness to your echo. As an action, you can see through your echo's eyes and hear through its ears. During this time, you are deafened and blinded. You can sustain this effect for up to 10 minutes, and you can end it at any time (requires no action). While your echo is being used in this way, it can be up to 1,000 feet away from you without being destroyed.
+        `,
+      },
+      {
+        name: 'Shadow Martyr',
+        level: 10,
+        description: `
+          Starting at 10th level, you can make your echo throw itself in front of an attack directed at another creature that you can see. Before the attack roll is made, you can use your reaction to teleport the echo to an unoccupied space within 5 feet of the targeted creature. The attack roll that triggered the reaction is instead made against your echo.
+
+          Once you use this feature, you can't use it again until you finish a short or long rest.
+        `,
+      },
+      {
+        name: 'Reclaim Potential',
+        level: 15,
+        description: `
+          By 15th level, you've learned to absorb the fleeting magic of your echo. When an echo of yours is destroyed by taking damage, you can gain a number of temporary hit points equal to 2d6 + your Constitution modifier, provided you don't already have temporary hit points.
+
+          You can use this feature a number of times equal to your Constitution modifier (a minimum of once). You regain all expended uses when you finish a long rest.
+        `,
+      },
+      {
+        name: 'Legion of One',
+        level: 15,
+        description: `
+          At 18th level, you can use a bonus action to create two echos with your Manifest Echo feature, and these echoes can co-exist. If you try to create a third echo, the previous two echoes are destroyed. Anything you can do from one echo's position can be done from the other's instead.
+
+          In addition, when you roll initiative and have no uses of your Unleash Incarnation feature left, you regain one use of that feature.
+        `,
+      },
+    ],
+  };
+}

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

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

+ 77 - 0
src/services/translator/translator.service.ts

@@ -0,0 +1,77 @@
+import { Injectable } from '@angular/core';
+
+@Injectable({
+  providedIn: 'root',
+})
+export class TranslatorService {
+  constructor() {}
+
+  public races: any = {
+    Aarakocra: { display: 'Aarakocra', value: 'Aarakocra' },
+    Aasimar: { display: 'Aasimar', value: 'Aasimar' },
+    Autognome: { display: 'Autognom', value: 'Autognome' },
+    Bugbear: { display: 'Grottenschrat', value: 'Bugbear' },
+    Centaur: { display: 'Zentaur', value: 'Centaur' },
+    Changeling: { display: 'Wechselbalg ', value: 'Changeling' },
+    Dragonborn: { display: 'Drachenblütiger', value: 'Dragonborn' },
+    Duergar: { display: 'Duergar', value: 'Duergar' },
+    Dwarf: { display: 'Zwerg', value: 'Dwarf' },
+    Fairy: { display: 'Fee', value: 'Fairy' },
+    Firbolg: { display: 'Firbolg', value: 'Firbolg' },
+    Genasi: { display: 'Genasi', value: 'Genasi' },
+    Gith: { display: 'Gedankenschinder', value: 'Gith' },
+    Gnome: { display: 'Gnom', value: 'Gnome' },
+    Goblin: { display: 'Goblin', value: 'Goblin' },
+    Goliath: { display: 'Goliath', value: 'Goliath' },
+    HalfElf: { display: 'Halbelf', value: 'HalfElf' },
+    HalfElfDetection: {
+      view: 'Halbelf (Mal des Entdeckens)',
+      value: 'HalfElfDetection',
+    },
+    HalfOrc: { display: 'Halbork', value: 'HalfOrc' },
+    Halfling: { display: 'Halbling', value: 'Halfling' },
+    Hobgoblin: { display: 'Hobgoblin', value: 'Hobgoblin' },
+    Human: { display: 'Mensch', value: 'Human' },
+    Kalashtar: { display: 'Kalashtar', value: 'Kalashtar' },
+    Kenku: { display: 'Kenku', value: 'Kenku' },
+    Kobold: { display: 'Kobold', value: 'Kobold' },
+    Leonin: { display: 'Leonin', value: 'Leonin' },
+    Lizardfolk: { display: 'Echsenmensch', value: 'Lizardfolk' },
+    Locathah: { display: 'Locathah', value: 'Locathah' },
+    Loxodon: { display: 'Loxodon', value: 'Loxodon' },
+    Minotaur: { display: 'Minotaurus', value: 'Minotaur' },
+    Orc: { display: 'Ork', value: 'Orc' },
+    Owlin: { display: 'Eulenmensch', value: 'Owlin' },
+    Satyr: { display: 'Satyr', value: 'Satyr' },
+    Shifter: { display: 'Wandler', value: 'Shifter' },
+    Tabaxi: { display: 'Tabaxi', value: 'Tabaxi' },
+    Tiefling: { display: 'Tiefling', value: 'Tiefling' },
+    Tortle: { display: 'Tortle', value: 'Tortle' },
+    Triton: { display: 'Triton', value: 'Triton' },
+    Vedalken: { display: 'Vedalken', value: 'Vedalken' },
+    Verdan: { display: 'Verdan', value: 'Verdan' },
+    Warforged: { display: 'Kriegsgeschmiedeter', value: 'Warforged' },
+    YuanTi: { display: 'Yuan-Ti', value: 'YuanTi' },
+  };
+
+  public classes: any = {
+    Barbarian: { display: 'Barbar', value: 'Barbarian' },
+    Bard: { display: 'Barde', value: 'Bard' },
+    Cleric: { display: 'Kleriker', value: 'Cleric' },
+    Druid: { display: 'Druide', value: 'Druid' },
+    Fighter: { display: 'Kämpfer', value: 'Fighter' },
+    Monk: { display: 'Mönch', value: 'Monk' },
+    Paladin: { display: 'Paladin', value: 'Paladin' },
+    Ranger: { display: 'Waldläufer', value: 'Ranger' },
+    Rogue: { display: 'Schurke', value: 'Rogue' },
+    Sorcerer: { display: 'Zauberer', value: 'Sorcerer' },
+    Warlock: { display: 'Hexenmeister', value: 'Warlock' },
+    Wizard: { display: 'Magier', value: 'Wizard' },
+  };
+
+  public genders: any = {
+    Male: { display: 'Männlich', value: 'Male' },
+    Female: { display: 'Weiblich', value: 'Female' },
+    Diverse: { display: 'Divers', value: 'Diverse' },
+  };
+}