Files
NowChess-Frontend/src/app/components/challenge-notification/challenge-notification.component.ts
T
shosho996 c02414ea40 fix: NCWF-2 bugs and desing fixes (#7)
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de>
Reviewed-on: #7
2026-05-15 02:16:43 +02:00

109 lines
3.5 KiB
TypeScript

import { Component, Input, Output, EventEmitter, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Router } from '@angular/router';
import { Challenge } from '../../models/challenge.models';
import { ChallengeService } from '../../services/challenge.service';
import { finalize } from 'rxjs';
import { getErrorMessage } from '../../core/http/error-message.util';
@Component({
selector: 'app-challenge-notification',
standalone: true,
imports: [CommonModule],
templateUrl: './challenge-notification.component.html',
styleUrls: ['./challenge-notification.component.css']
})
export class ChallengeNotificationComponent {
@Input() challenge!: Challenge;
@Output() accept = new EventEmitter<Challenge>();
@Output() decline = new EventEmitter<Challenge>();
@Output() close = new EventEmitter<void>();
private readonly challengeService = inject(ChallengeService);
private readonly router = inject(Router);
acceptingChallenge = false;
decliningChallenge = false;
errorMessage = '';
onAccept(): void {
if (this.acceptingChallenge || this.decliningChallenge) {
return;
}
this.acceptingChallenge = true;
this.errorMessage = '';
this.challengeService.acceptChallenge(this.challenge.id)
.pipe(finalize(() => (this.acceptingChallenge = false)))
.subscribe({
next: (acceptedChallenge) => {
this.accept.emit(acceptedChallenge);
if (acceptedChallenge.gameId) {
void this.router.navigate(['/game', acceptedChallenge.gameId]);
} else {
this.errorMessage = 'Challenge accepted, but no game was created.';
}
},
error: (error) => {
this.errorMessage = getErrorMessage(error, 'Failed to accept challenge');
}
});
}
onDecline(): void {
if (this.acceptingChallenge || this.decliningChallenge) {
return;
}
this.decliningChallenge = true;
this.errorMessage = '';
this.challengeService.declineChallenge(this.challenge.id, { reason: 'generic' })
.pipe(finalize(() => (this.decliningChallenge = false)))
.subscribe({
next: () => {
this.decline.emit(this.challenge);
},
error: (error) => {
this.errorMessage = getErrorMessage(error, 'Failed to decline challenge');
}
});
}
onClose(): void {
this.close.emit();
}
getTimeControlDisplay(): string {
const { limit, increment } = this.challenge.timeControl;
if (!limit || !increment) {
return 'Unlimited';
}
const minutes = Math.floor(limit / 60);
return `${minutes}+${increment}`;
}
getCreatedByDisplay(): string {
return this.challenge.challenger.name;
}
getExpirationInfo(): string {
const expiresAt = new Date(this.challenge.expiresAt);
const now = new Date();
const diffMs = expiresAt.getTime() - now.getTime();
if (diffMs <= 0) {
return 'Expired';
}
const minutes = Math.floor(diffMs / 60000);
if (minutes > 60) {
const hours = Math.floor(minutes / 60);
return `Expires in ${hours}h`;
}
return `Expires in ${minutes}m`;
}
}