95eff42dfe
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de> Co-authored-by: shahdlala66 <shahd.lala66@gmail.com> Reviewed-on: #8
108 lines
3.3 KiB
TypeScript
108 lines
3.3 KiB
TypeScript
import { Component, DestroyRef, OnInit, inject } from '@angular/core';
|
|
import { Router, RouterLink } from '@angular/router';
|
|
import { forkJoin, of } from 'rxjs';
|
|
import { catchError } from 'rxjs/operators';
|
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
import { AuthService } from '../../services/auth.service';
|
|
import { GameApiService } from '../../services/game-api.service';
|
|
import { GameHistoryService } from '../../services/game-history.service';
|
|
import { GameFull, GameStatus } from '../../models/game.models';
|
|
|
|
type GamesTab = 'active' | 'history';
|
|
|
|
const FINISHED_STATUSES: GameStatus[] = [
|
|
'checkmate', 'stalemate', 'resign', 'draw', 'insufficientMaterial'
|
|
];
|
|
|
|
@Component({
|
|
selector: 'app-games',
|
|
standalone: true,
|
|
imports: [RouterLink],
|
|
templateUrl: './games.component.html',
|
|
styleUrl: './games.component.css'
|
|
})
|
|
export class GamesComponent implements OnInit {
|
|
private readonly destroyRef = inject(DestroyRef);
|
|
private readonly router = inject(Router);
|
|
private readonly authService = inject(AuthService);
|
|
private readonly gameApi = inject(GameApiService);
|
|
private readonly gameHistory = inject(GameHistoryService);
|
|
|
|
tab: GamesTab = 'active';
|
|
loading = true;
|
|
activeGames: GameFull[] = [];
|
|
finishedGames: GameFull[] = [];
|
|
|
|
ngOnInit(): void {
|
|
this.authService.currentUser$
|
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
.subscribe((user) => {
|
|
if (!user) void this.router.navigate(['/']);
|
|
});
|
|
|
|
this.loadGames();
|
|
}
|
|
|
|
setTab(tab: GamesTab): void {
|
|
this.tab = tab;
|
|
}
|
|
|
|
resumeGame(gameId: string): void {
|
|
void this.router.navigate(['/game', gameId]);
|
|
}
|
|
|
|
removeGame(gameId: string): void {
|
|
this.gameHistory.removeGame(gameId);
|
|
this.activeGames = this.activeGames.filter((g) => g.gameId !== gameId);
|
|
this.finishedGames = this.finishedGames.filter((g) => g.gameId !== gameId);
|
|
}
|
|
|
|
statusLabel(status: GameStatus): string {
|
|
const labels: Record<GameStatus, string> = {
|
|
started: 'In Progress',
|
|
check: 'Check',
|
|
checkmate: 'Checkmate',
|
|
stalemate: 'Stalemate',
|
|
resign: 'Resigned',
|
|
draw: 'Draw',
|
|
drawOffered: 'Draw Offered',
|
|
fiftyMoveAvailable: 'In Progress',
|
|
promotionPending: 'In Progress',
|
|
insufficientMaterial: 'Draw'
|
|
};
|
|
return labels[status] ?? status;
|
|
}
|
|
|
|
isFinished(status: GameStatus): boolean {
|
|
return FINISHED_STATUSES.includes(status);
|
|
}
|
|
|
|
private loadGames(): void {
|
|
const ids = this.gameHistory.getGameIds();
|
|
if (ids.length === 0) {
|
|
this.loading = false;
|
|
return;
|
|
}
|
|
|
|
const requests = ids.map((id) =>
|
|
this.gameApi.getGame(id).pipe(
|
|
catchError((err: unknown) => {
|
|
if (typeof err === 'object' && err !== null && (err as { status: number }).status === 404) {
|
|
this.gameHistory.removeGame(id);
|
|
}
|
|
return of(null);
|
|
})
|
|
)
|
|
);
|
|
|
|
forkJoin(requests)
|
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
.subscribe((results) => {
|
|
const valid = results.filter((g): g is GameFull => g !== null);
|
|
this.activeGames = valid.filter((g) => !FINISHED_STATUSES.includes(g.state.status));
|
|
this.finishedGames = valid.filter((g) => FINISHED_STATUSES.includes(g.state.status));
|
|
this.loading = false;
|
|
});
|
|
}
|
|
}
|