feat: join pervious game added

This commit is contained in:
shahdlala66
2026-04-19 11:14:14 +02:00
parent bc644c16e3
commit fdc0f1d73b
3 changed files with 162 additions and 4 deletions
@@ -204,6 +204,93 @@ p {
color: white; color: white;
} }
.join-game-form {
grid-column: 1 / -1;
background: var(--color-bg-card);
border: var(--border-width) solid var(--color-border);
border-radius: var(--border-radius-md);
padding: var(--size-lg-padding);
margin: var(--size-md) 0;
}
.join-game-form p {
margin: 0 0 var(--size-md);
font-weight: 600;
}
.join-game-input-group {
display: flex;
gap: var(--size-md-gap);
flex-wrap: wrap;
}
.join-game-input {
flex: 1;
min-width: 150px;
padding: var(--size-md-padding);
border: var(--border-width) solid var(--color-border);
border-radius: var(--border-radius-md);
background: white;
color: var(--color-text-primary);
font-family: inherit;
font-size: 1rem;
transition: border-color 0.3s ease;
}
.join-game-input:focus {
outline: none;
border-color: var(--color-secondary-mint);
box-shadow: 0 0 0 3px rgba(185, 218, 209, 0.2);
}
.join-game-input:disabled {
background: var(--color-bg-card);
opacity: 0.6;
}
.join-game-btn {
padding: var(--size-md-padding) var(--size-lg);
border: var(--border-width) solid var(--color-border);
border-radius: var(--border-radius-md);
cursor: pointer;
font-weight: 600;
font-size: 0.95rem;
transition: all 0.3s ease;
}
.join-game-btn.join {
background: var(--color-secondary-mint);
color: var(--color-text-primary);
}
.join-game-btn.join:hover:enabled {
background: var(--color-secondary-blue);
}
.join-game-btn.join:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.join-game-btn.cancel {
background: var(--color-bg-card);
color: var(--color-text-primary);
}
.join-game-btn.cancel:hover:enabled {
background: var(--color-border);
}
.join-game-btn.cancel:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.difficulty-btn.hard:hover:enabled {
background: var(--color-danger, #dc3545);
color: white;
}
.difficulty-btn:disabled { .difficulty-btn:disabled {
opacity: 0.6; opacity: 0.6;
cursor: not-allowed; cursor: not-allowed;
+35 -3
View File
@@ -31,12 +31,44 @@
<small>{{ creating ? 'Creating game...' : 'Start now' }}</small> <small>{{ creating ? 'Creating game...' : 'Start now' }}</small>
</button> </button>
<button type="button" class="mode mode-disabled" disabled> <button type="button" class="mode mode-active" (click)="toggleJoinGameForm()" [disabled]="joiningGame">
<span>Future Technique</span> <span>Join Game</span>
<small>Placeholder</small> <small>{{ joiningGame ? 'Joining...' : 'Enter game ID' }}</small>
</button> </button>
</div> </div>
@if (showJoinGameForm) {
<div class="join-game-form">
<p>Enter the game ID:</p>
<div class="join-game-input-group">
<input
type="text"
class="join-game-input"
[(ngModel)]="gameIdInput"
placeholder="Paste game ID here"
[disabled]="joiningGame"
(keyup.enter)="joinGame()"
/>
<button
type="button"
class="join-game-btn join"
(click)="joinGame()"
[disabled]="joiningGame || !gameIdInput.trim()"
>
{{ joiningGame ? 'Joining...' : 'Join' }}
</button>
<button
type="button"
class="join-game-btn cancel"
(click)="clearJoinGameForm()"
[disabled]="joiningGame"
>
Cancel
</button>
</div>
</div>
}
@if (errorMessage) { @if (errorMessage) {
<p class="error">{{ errorMessage }}</p> <p class="error">{{ errorMessage }}</p>
} }
+40 -1
View File
@@ -1,5 +1,6 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { finalize } from 'rxjs'; import { finalize } from 'rxjs';
import { getErrorMessage } from '../../core/http/error-message.util'; import { getErrorMessage } from '../../core/http/error-message.util';
@@ -8,7 +9,7 @@ import { GameApiService } from '../../services/game-api.service';
@Component({ @Component({
selector: 'app-welcome', selector: 'app-welcome',
standalone: true, standalone: true,
imports: [CommonModule], imports: [CommonModule, FormsModule],
templateUrl: './welcome.component.html', templateUrl: './welcome.component.html',
styleUrl: './welcome.component.css' styleUrl: './welcome.component.css'
}) })
@@ -16,6 +17,9 @@ export class WelcomeComponent {
creating = false; creating = false;
errorMessage = ''; errorMessage = '';
showDifficultySelector = false; showDifficultySelector = false;
showJoinGameForm = false;
gameIdInput = '';
joiningGame = false;
constructor( constructor(
private readonly router: Router, private readonly router: Router,
@@ -67,6 +71,41 @@ export class WelcomeComponent {
toggleDifficultySelector(): void { toggleDifficultySelector(): void {
this.showDifficultySelector = !this.showDifficultySelector; this.showDifficultySelector = !this.showDifficultySelector;
this.showJoinGameForm = false;
this.errorMessage = '';
}
toggleJoinGameForm(): void {
this.showJoinGameForm = !this.showJoinGameForm;
this.showDifficultySelector = false;
this.errorMessage = '';
this.gameIdInput = '';
}
joinGame(): void {
if (this.joiningGame || !this.gameIdInput.trim()) {
return;
}
this.errorMessage = '';
this.joiningGame = true;
this.gameApi
.getGame(this.gameIdInput.trim())
.pipe(finalize(() => (this.joiningGame = false)))
.subscribe({
next: (game) => {
void this.router.navigate(['/game', game.gameId]);
},
error: (error) => {
this.errorMessage = getErrorMessage(error, 'Unable to find or join the game.');
}
});
}
clearJoinGameForm(): void {
this.showJoinGameForm = false;
this.gameIdInput = '';
this.errorMessage = ''; this.errorMessage = '';
} }
} }