fix: Make user not able to enter too much money
Some checks failed
CI / Get Changed Files (pull_request) Successful in 8s
CI / Checkstyle Main (pull_request) Has been skipped
CI / Docker backend validation (pull_request) Has been skipped
CI / oxlint (pull_request) Successful in 21s
CI / eslint (pull_request) Successful in 27s
CI / prettier (pull_request) Failing after 31s
CI / Docker frontend validation (pull_request) Successful in 54s
CI / test-build (pull_request) Successful in 50s

This commit is contained in:
Jan K9f 2025-05-21 10:58:35 +02:00
commit 8b6e026e0a
5 changed files with 79 additions and 17 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

View file

@ -102,15 +102,25 @@
<!-- Custom bet input -->
<div class="space-y-1">
<label for="bet" class="text-sm text-text-secondary">Bet Amount</label>
<div class="flex justify-between">
<label for="bet" class="text-sm text-text-secondary">Bet Amount</label>
<span *ngIf="isInvalidBet()" class="text-xs text-accent-red animate-pulse"
>Cannot exceed balance</span
>
</div>
<input
type="number"
id="bet"
class="w-full px-3 py-2 bg-deep-blue-light text-white rounded focus:outline-none focus:ring-2 focus:ring-emerald disabled:opacity-50"
class="w-full px-3 py-2 bg-deep-blue-light text-white rounded focus:outline-none focus:ring-2 disabled:opacity-50"
[ngClass]="{
'ring-accent-red': isInvalidBet(),
'ring-emerald': !isInvalidBet(),
}"
[min]="1"
[max]="balance()"
[ngModel]="betInputValue()"
(input)="updateBet($event)"
(keydown)="validateBetInput($event)"
step="1"
[disabled]="gameInProgress()"
[placeholder]="balance() | currency: 'EUR'"

View file

@ -1,4 +1,4 @@
import { CurrencyPipe } from '@angular/common';
import { NgClass, NgIf, CurrencyPipe, CommonModule } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { FormsModule } from '@angular/forms';
import {
@ -20,7 +20,14 @@ import { CoinflipGame, CoinflipRequest } from './models/coinflip.model';
@Component({
selector: 'app-coinflip',
standalone: true,
imports: [AnimatedNumberComponent, CurrencyPipe, FormsModule],
imports: [
AnimatedNumberComponent,
CurrencyPipe,
FormsModule,
CommonModule,
NgIf,
NgClass
],
templateUrl: './coinflip.component.html',
styleUrl: './coinflip.component.css',
changeDetection: ChangeDetectionStrategy.OnPush,
@ -33,6 +40,7 @@ export default class CoinflipComponent implements OnInit {
gameResult = signal<CoinflipGame | null>(null);
betInputValue = signal(10);
errorMessage = signal('');
isInvalidBet = signal(false);
@ViewChild('coinElement') coinElement?: ElementRef;
@ -62,18 +70,30 @@ export default class CoinflipComponent implements OnInit {
updateBet(event: Event) {
const inputElement = event.target as HTMLInputElement;
const value = Number(inputElement.value);
let value = Number(inputElement.value);
// Reset invalid bet state
this.isInvalidBet.set(false);
// Enforce minimum bet of 1
if (value <= 0) {
this.betInputValue.set(1);
this.currentBet.set(1);
} else if (value > this.balance()) {
this.betInputValue.set(this.balance());
this.currentBet.set(this.balance());
} else {
this.betInputValue.set(value);
this.currentBet.set(value);
value = 1;
}
// Cap bet at available balance and show feedback
if (value > this.balance()) {
value = this.balance();
// Show visual feedback
this.isInvalidBet.set(true);
// Indicate the error briefly
setTimeout(() => this.isInvalidBet.set(false), 800);
// Update the input field directly to show the user the max value
inputElement.value = String(value);
}
// Update signals
this.betInputValue.set(value);
this.currentBet.set(value);
}
betHeads() {
@ -191,6 +211,38 @@ export default class CoinflipComponent implements OnInit {
console.log(`Animation applied for result: ${result}`);
}
/**
* Validates input as the user types to prevent invalid values
*/
validateBetInput(event: KeyboardEvent) {
// Allow navigation keys (arrows, delete, backspace, tab)
const navigationKeys = ['ArrowLeft', 'ArrowRight', 'Delete', 'Backspace', 'Tab'];
if (navigationKeys.includes(event.key)) {
return;
}
// Only allow numbers
if (!/^\d$/.test(event.key)) {
event.preventDefault();
return;
}
// Get the value that would result after the keypress
const input = event.target as HTMLInputElement;
const currentValue = input.value;
const cursorPosition = input.selectionStart || 0;
const newValue = currentValue.substring(0, cursorPosition) + event.key + currentValue.substring(input.selectionEnd || cursorPosition);
const numValue = Number(newValue);
// Prevent values greater than balance
if (numValue > this.balance()) {
event.preventDefault();
}
}
// We removed the paste handler for simplicity since the updateBet method
// will handle any value that gets into the input field
getResultClass() {
if (!this.gameResult()) return '';
const result = this.gameResult();

View file

@ -48,9 +48,9 @@ export default class HomeComponent implements OnInit {
featuredGames: Game[] = [
{
id: '1',
name: 'Poker',
image: '/poker.webp',
route: '/game/poker',
name: 'Coinflip',
image: '/coinflip.png',
route: '/game/coinflip',
},
{
id: '2',