import { Component } from '@angular/core'; import { DataService } from 'src/services/data/data.service'; import { ModalService } from 'src/services/modal/modal.service'; import { DetailsService } from 'src/services/details/details.service'; import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop'; import { Spell } from 'src/interfaces/spell'; import { SpellDetailsComponent } from './spell-details/spell-details.component'; import { SpellModalComponent } from 'src/app/journal/spell-modal/spell-modal.component'; import { FullSpellcardComponent } from 'src/app/shared-components/full-spellcard/full-spellcard.component'; import { Observable, OperatorFunction } from 'rxjs'; import { debounceTime, distinctUntilChanged, map } from 'rxjs/operators'; @Component({ selector: 'spell-table', templateUrl: './spell-table.component.html', styleUrls: ['./spell-table.component.scss'], }) export class SpellTableComponent { public spellAttackBonus: string = '0'; public spellSaveDC: number = 0; private spellcastingAttribute: string | undefined; private spellcastingAttributeModifier: number = 0; private proficiencyBonus: number = 2; public spells!: Spell[]; private preparedSpells!: Spell[]; private preparedSpellsNames: string[] = []; public newSpellName: string = ''; public showInput: boolean = false; public attributes: any = { strength: 'STR', dexterity: 'DEX', constitution: 'CON', intelligence: 'INT', wisdom: 'WIS', charisma: 'CHA', }; public areas: any = { cone: 'Kegel', sphere: 'Kugel', circle: 'Kreis', line: 'Linie', square: 'Quadrat', cube: 'Würfel', }; public constructor( public dataAccessor: DataService, private modalAccessor: ModalService, public detailsAccessor: DetailsService ) {} public ngOnInit(): void { this.spells = this.dataAccessor.favoriteSpells; this.preparedSpells = this.dataAccessor.getAllPreparedSpells(); this.preparedSpellsNames = this.preparedSpells.map((spell) => spell.name); console.log(this.preparedSpellsNames); this.subscribeToData(); } public showFullSpellcard(spellIndex: number): void { this.modalAccessor.openModal(FullSpellcardComponent, { spell: this.spells[spellIndex], isFromDashboard: true, }); const resultSubscription = this.modalAccessor.result$.subscribe( (result) => { resultSubscription.unsubscribe(); if (result.state === 'delete') { this.spells.splice(spellIndex, 1); } else if (result.state !== 'cancel') { console.log(result.state); throw new Error('Unexpected result state, please send a bug report.'); } } ); } // LEGACY CODE public openDetailsPanel(index: number): void { this.detailsAccessor.openPanel(SpellDetailsComponent, { spell: this.spells[index], modifiers: { attackBonus: this.spellAttackBonus, saveDC: this.spellSaveDC, }, }); const resultSubscription = this.detailsAccessor.result$.subscribe( (result) => { console.log(result); if (result.state === 'delete') { this.deleteSpell(index); } else if (result.state === 'update') { this.openModal(true, index); } resultSubscription.unsubscribe(); } ); } // public openModal(isUpdate: boolean, index?: number): void { this.modalAccessor.openModal(SpellModalComponent, { spell: index !== undefined ? JSON.parse(JSON.stringify(this.spells[index])) : undefined, isUpdate: isUpdate, }); const resultSubscription = this.modalAccessor.result$.subscribe( (result) => { if (result.state === 'update') { console.log(result.data); this.updateSpell(result.data, index!); } else if (result.state === 'add') { this.addSpell(result.data); } resultSubscription.unsubscribe(); } ); } public toggleInput(): void { this.showInput = !this.showInput; this.newSpellName = ''; } public onSpellSelect(spellname: any): void { const newSpell = this.preparedSpells.filter( (spell) => spell.name === spellname ); if (newSpell.length !== 1) { throw new Error('Spell not found.'); } else { this.addSpell(newSpell[0]); } this.newSpellName = ''; } public addSpell(spell: Spell) { this.spells.push(spell); this.updateSpellsInDatabase(); } public updateSpell(spell: Spell, index: number): void { this.spells[index] = spell; this.updateSpellsInDatabase(); } public deleteSpell(index: number): void { this.spells.splice(index, 1); this.updateSpellsInDatabase(); } // utils public dropSpells(event: CdkDragDrop): void { moveItemInArray(this.spells, event.previousIndex, event.currentIndex); this.updateSpellsInDatabase(); } public updateSpellsInDatabase(): void { this.dataAccessor.favoriteSpells = this.spells; } private computeSpellAttackBonusAndSaveDC(): void { let attackBonus = this.spellcastingAttributeModifier + this.proficiencyBonus; this.spellSaveDC = 8 + attackBonus; if (attackBonus >= 0) { this.spellAttackBonus = '+' + attackBonus; } else { this.spellAttackBonus = attackBonus.toString(); } } private subscribeToData(): void { // TODO: this.dataAccessor.getSpellcastingAttribute() oder so this.spellcastingAttribute = 'intelligence'; this.dataAccessor.proficiency$.subscribe((value) => { this.proficiencyBonus = value.value; if (this.spellcastingAttribute) { this.computeSpellAttackBonusAndSaveDC(); } }); // TODO: Modify depending on the actual spellcasting attribute this.dataAccessor.intelligence$.subscribe((value) => { this.spellcastingAttributeModifier = Math.floor((value.value - 10) / 2); this.computeSpellAttackBonusAndSaveDC(); }); } public search: OperatorFunction = ( text$: Observable ) => text$.pipe( debounceTime(200), distinctUntilChanged(), map((term) => term.length < 2 ? [] : this.preparedSpellsNames .filter((v) => v.toLowerCase().indexOf(term.toLowerCase()) > -1) .filter( (v) => !this.spells.some( (spell) => spell.name.toLowerCase() === v.toLowerCase() ) ) .slice(0, 5) ) ); }