From 1bc97df0dac7503e41a0738f6bd26a94acf7445e Mon Sep 17 00:00:00 2001 From: eneller Date: Sat, 31 Jan 2026 15:52:06 +0100 Subject: [PATCH] feat: deduplicated player adding --- src/app/app.component.html | 2 +- src/app/app.component.ts | 3 +- src/app/model.ts | 11 ++++ .../screen-edit/screen-edit.component.html | 30 +++++++++ .../screen-edit/screen-edit.component.less | 0 .../screen-edit/screen-edit.component.spec.ts | 23 +++++++ src/app/screen-edit/screen-edit.component.ts | 63 +++++++++++++++++++ .../screen-rotations.component.html | 31 +-------- .../screen-rotations.component.ts | 26 -------- 9 files changed, 131 insertions(+), 58 deletions(-) create mode 100644 src/app/screen-edit/screen-edit.component.html create mode 100644 src/app/screen-edit/screen-edit.component.less create mode 100644 src/app/screen-edit/screen-edit.component.spec.ts create mode 100644 src/app/screen-edit/screen-edit.component.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index f5ecf24..71dc3f4 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,5 +1,5 @@
- +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 64981c6..5ad76e4 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -8,10 +8,11 @@ import { filter, take } from 'rxjs'; import { ScreenBasicComponent } from "./screen-basic/screen-basic.component"; import { ScreenRotationsComponent } from './screen-rotations/screen-rotations.component'; import { Player } from './model'; +import { ScreenEditComponent } from './screen-edit/screen-edit.component'; @Component({ selector: 'app-root', - imports: [NgbModule, RouterOutlet, CommonModule, FormsModule, ScreenBasicComponent, ScreenRotationsComponent], + imports: [NgbModule, RouterOutlet, CommonModule, FormsModule, ScreenBasicComponent, ScreenRotationsComponent, ScreenEditComponent], templateUrl: './app.component.html', styleUrl: './app.component.less' }) diff --git a/src/app/model.ts b/src/app/model.ts index e9cc6e3..2608e7f 100644 --- a/src/app/model.ts +++ b/src/app/model.ts @@ -25,7 +25,18 @@ export class Player{ const values = 'OOOO' return [this.name, values]; } + + valueOf(): string{ + return this.name; + } static deSerialize(name: string, values: string): Player{ return new Player(name); } + static isNew(newplayer:Player, players: Player[]): boolean { + const seen = new Set(players.map(p => p.name)); + if (seen.has(newplayer.name)){ + return false + } + return true +} } diff --git a/src/app/screen-edit/screen-edit.component.html b/src/app/screen-edit/screen-edit.component.html new file mode 100644 index 0000000..0d26edb --- /dev/null +++ b/src/app/screen-edit/screen-edit.component.html @@ -0,0 +1,30 @@ +
+

Players: {{ players.length }}

+
+ + +
+ @if (alertMessage) { + {{ alertMessage }} + } +
+ + +
+ + +
\ No newline at end of file diff --git a/src/app/screen-edit/screen-edit.component.less b/src/app/screen-edit/screen-edit.component.less new file mode 100644 index 0000000..e69de29 diff --git a/src/app/screen-edit/screen-edit.component.spec.ts b/src/app/screen-edit/screen-edit.component.spec.ts new file mode 100644 index 0000000..bf13f40 --- /dev/null +++ b/src/app/screen-edit/screen-edit.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ScreenEditComponent } from './screen-edit.component'; + +describe('ScreenEditComponent', () => { + let component: ScreenEditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ScreenEditComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ScreenEditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/screen-edit/screen-edit.component.ts b/src/app/screen-edit/screen-edit.component.ts new file mode 100644 index 0000000..54ca885 --- /dev/null +++ b/src/app/screen-edit/screen-edit.component.ts @@ -0,0 +1,63 @@ +import { Component, Input, ViewChild } from '@angular/core'; +import { NgbAlert, NgbModal } from '@ng-bootstrap/ng-bootstrap'; +import { Player } from '../model'; +import { ModalRotationsComponent } from '../modal-rotations/modal-rotations.component'; +import { FormsModule } from '@angular/forms'; +import { Subject } from 'rxjs/internal/Subject'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { debounceTime, tap } from 'rxjs/operators'; + +@Component({ + selector: 'app-screen-edit', + imports: [FormsModule, NgbAlert], + templateUrl: './screen-edit.component.html', + styleUrl: './screen-edit.component.less' +}) +export class ScreenEditComponent { + @Input() players!: Player[]; + @ViewChild('selfClosingAlert', { static: false })selfClosingAlert!: NgbAlert; + private _message$ = new Subject(); + newItem: string = ""; + alertMessage = ''; + + constructor(private modalService: NgbModal) { + this._message$ + .pipe( + takeUntilDestroyed(), + tap((message) => (this.alertMessage = message)), + debounceTime(5000), + ) + .subscribe(() => this.selfClosingAlert?.close()); + } + + addItem() { + const name = this.newItem.trim() + if (name) { + let newPlayer = new Player(name); + if (Player.isNew(newPlayer, this.players)){ + this.players.push(newPlayer); + this.newItem = ''; + } + else{ + this.setAlertMessage(newPlayer.name); + } + } + } + + openPlayerModal(player: Player){ + const modalRef = this.modalService.open(ModalRotationsComponent); + modalRef.componentInstance.player = player; + /* + modalRef.result.then((updatedPlayer) => { + // Handle the updated player data if needed + console.log('Player updated:', updatedPlayer); + }).catch((error) => { + console.log('Modal dismissed'); + }); + */ + } + public setAlertMessage(s: string) { + this._message$.next(`"${s}" already exists. Please choose a unique name.`); + } + +} diff --git a/src/app/screen-rotations/screen-rotations.component.html b/src/app/screen-rotations/screen-rotations.component.html index b2f2cf5..a02d7b2 100644 --- a/src/app/screen-rotations/screen-rotations.component.html +++ b/src/app/screen-rotations/screen-rotations.component.html @@ -1,30 +1 @@ -
-
-

Players

-
    - @for (player of players; track $index) { -
  • {{ player.name }}
  • - - } -
-
- - -
-
- -
+

rotations!

\ No newline at end of file diff --git a/src/app/screen-rotations/screen-rotations.component.ts b/src/app/screen-rotations/screen-rotations.component.ts index 7987d2e..3f8c3fb 100644 --- a/src/app/screen-rotations/screen-rotations.component.ts +++ b/src/app/screen-rotations/screen-rotations.component.ts @@ -2,8 +2,6 @@ import { Component, Input } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { Player } from '../model'; -import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { ModalRotationsComponent } from '../modal-rotations/modal-rotations.component'; @Component({ selector: 'app-screen-rotations', @@ -13,28 +11,4 @@ import { ModalRotationsComponent } from '../modal-rotations/modal-rotations.comp }) export class ScreenRotationsComponent { @Input() players!: Player[]; - newItem: string = ""; - - constructor(private modalService: NgbModal) {} - - addItem() { - if (this.newItem.trim()) { - this.players.push( new Player(this.newItem)); - this.newItem = ""; - } - } - - openPlayerModal(player: Player){ - const modalRef = this.modalService.open(ModalRotationsComponent); - modalRef.componentInstance.player = player; - /* - modalRef.result.then((updatedPlayer) => { - // Handle the updated player data if needed - console.log('Player updated:', updatedPlayer); - }).catch((error) => { - console.log('Modal dismissed'); - }); - */ - } - } \ No newline at end of file