feat: NCS-69 Challenge request (#3)

- create challange window
- challanges view page
- decline and accept
- notif tab (wip)
- active game window (wip)

---------

Co-authored-by: shahdlala66 <shahd.lala66@gmail.com>
Co-authored-by: Lala, Shahd <Shahd.Lala@sybit.de>
Reviewed-on: #3
This commit was merged in pull request #3.
This commit is contained in:
2026-05-12 22:38:57 +02:00
parent 3c1f5c76e0
commit bad7366bdb
16 changed files with 1683 additions and 1 deletions
@@ -0,0 +1,102 @@
<div class="challenges-container">
<div class="challenges-header">
<h1>Active Challenges</h1>
<button type="button" class="back-btn" (click)="goBack()">← Back</button>
</div>
<div *ngIf="errorMessage" class="error-banner">
{{ errorMessage }}
</div>
<div class="challenges-grid">
<!-- Incoming Challenges -->
<div class="challenges-section">
<h2>Incoming Challenges</h2>
<div *ngIf="loading" class="loading-spinner">Loading...</div>
<div *ngIf="!loading && incomingChallenges.length === 0" class="empty-state">
<p>No incoming challenges</p>
</div>
<div *ngIf="!loading && incomingChallenges.length > 0" class="challenge-list">
<div *ngFor="let challenge of incomingChallenges" class="challenge-card">
<div class="challenge-header">
<span class="challenger-name">{{ getChallengerDisplay(challenge) }}</span>
<span class="time-control">{{ getTimeControlDisplay(challenge) }}</span>
</div>
<div class="challenge-details">
<div class="detail">
<span class="label">Status:</span>
<span class="value" [class]="'status-' + challenge.status">
{{ challenge.status | uppercase }}
</span>
</div>
<div class="detail">
<span class="label">Expires in:</span>
<span class="value">{{ getExpirationInfo(challenge) }}</span>
</div>
</div>
<div class="challenge-actions" *ngIf="challenge.status === 'created'">
<button type="button" class="btn btn-decline" (click)="declineChallenge(challenge)">
Decline
</button>
<button type="button" class="btn btn-accept" (click)="acceptChallenge(challenge)">
Accept
</button>
</div>
<div class="challenge-actions" *ngIf="challenge.status === 'accepted' && challenge.gameId">
<button type="button" class="btn btn-accept" (click)="openGame(challenge)">
Play
</button>
</div>
</div>
</div>
</div>
<!-- Outgoing Challenges -->
<div class="challenges-section">
<h2>Outgoing Challenges</h2>
<div *ngIf="!loading && outgoingChallenges.length === 0" class="empty-state">
<p>No outgoing challenges</p>
</div>
<div *ngIf="!loading && outgoingChallenges.length > 0" class="challenge-list">
<div *ngFor="let challenge of outgoingChallenges" class="challenge-card">
<div class="challenge-header">
<span class="challenger-name">→ {{ getOpponentDisplay(challenge) }}</span>
<span class="time-control">{{ getTimeControlDisplay(challenge) }}</span>
</div>
<div class="challenge-details">
<div class="detail">
<span class="label">Status:</span>
<span class="value" [class]="'status-' + challenge.status">
{{ challenge.status | uppercase }}
</span>
</div>
<div class="detail">
<span class="label">Expires in:</span>
<span class="value">{{ getExpirationInfo(challenge) }}</span>
</div>
</div>
<div class="challenge-actions" *ngIf="challenge.status === 'created'">
<button type="button" class="btn btn-cancel" (click)="cancelChallenge(challenge)">
Cancel
</button>
</div>
<div class="challenge-actions" *ngIf="challenge.status === 'accepted' && challenge.gameId">
<button type="button" class="btn btn-accept" (click)="openGame(challenge)">
Play
</button>
</div>
</div>
</div>
</div>
</div>
</div>