style: format code

This commit is contained in:
Phan Huy Tran 2025-05-21 10:42:36 +02:00 committed by Phan Huy Tran
commit f2aa81b6d2
5 changed files with 274 additions and 221 deletions

View file

@ -63,7 +63,7 @@ export const routes: Routes = [
}, },
{ {
path: 'game/dice', path: 'game/dice',
loadComponent: () => import('./feature/game/dice/dice.component').then(m => m.DiceComponent), loadComponent: () => import('./feature/game/dice/dice.component').then((m) => m.DiceComponent),
canActivate: [authGuard], canActivate: [authGuard],
}, },
]; ];

View file

@ -7,45 +7,91 @@
<div class="controls space-y-4"> <div class="controls space-y-4">
<div> <div>
<label for="betAmount" class="block text-text-secondary mb-2">Bet Amount:</label> <label for="betAmount" class="block text-text-secondary mb-2">Bet Amount:</label>
<input id="betAmount" type="number" formControlName="betAmount" min="0.01" step="0.01" <input
class="w-full bg-deep-blue-light text-white rounded-lg p-2 focus:outline-none focus:ring-1 focus:ring-emerald"> id="betAmount"
type="number"
formControlName="betAmount"
min="0.01"
step="0.01"
class="w-full bg-deep-blue-light text-white rounded-lg p-2 focus:outline-none focus:ring-1 focus:ring-emerald"
/>
@if (hasError('betAmount', 'required')) { @if (hasError('betAmount', 'required')) {
<span class="text-accent-red text-sm mt-1 block">Bet Amount is required</span> <span class="text-accent-red text-sm mt-1 block">Bet Amount is required</span>
} }
@if (hasError('betAmount', 'min')) { @if (hasError('betAmount', 'min')) {
<span class="text-accent-red text-sm mt-1 block">Bet Amount must be at least 0.01</span> <span class="text-accent-red text-sm mt-1 block"
>Bet Amount must be at least 0.01</span
>
} }
</div> </div>
<div> <div>
<label class="block text-text-secondary mb-2">Roll Mode:</label> <label class="block text-text-secondary mb-2">Roll Mode:</label>
<div class="roll-mode flex rounded-lg overflow-hidden"> <div class="roll-mode flex rounded-lg overflow-hidden">
<button type="button" (click)="toggleRollMode()" [ngClass]="{'bg-emerald text-white': diceForm.get('rollOver')?.value, 'bg-deep-blue-light text-text-secondary': !diceForm.get('rollOver')?.value}" <button
class="flex-1 py-2 text-center font-semibold transition-colors duration-200">Roll Over</button> type="button"
<button type="button" (click)="toggleRollMode()" [ngClass]="{'bg-emerald text-white': !diceForm.get('rollOver')?.value, 'bg-deep-blue-light text-text-secondary': diceForm.get('rollOver')?.value}" (click)="toggleRollMode()"
class="flex-1 py-2 text-center font-semibold transition-colors duration-200">Roll Under</button> [ngClass]="{
'bg-emerald text-white': diceForm.get('rollOver')?.value,
'bg-deep-blue-light text-text-secondary': !diceForm.get('rollOver')?.value,
}"
class="flex-1 py-2 text-center font-semibold transition-colors duration-200"
>
Roll Over
</button>
<button
type="button"
(click)="toggleRollMode()"
[ngClass]="{
'bg-emerald text-white': !diceForm.get('rollOver')?.value,
'bg-deep-blue-light text-text-secondary': diceForm.get('rollOver')?.value,
}"
class="flex-1 py-2 text-center font-semibold transition-colors duration-200"
>
Roll Under
</button>
</div> </div>
</div> </div>
<div> <div>
<label for="targetValue" class="block text-text-secondary mb-2">Target Value: {{ diceForm.get('targetValue')?.value | number:'1.0-2' }}</label> <label for="targetValue" class="block text-text-secondary mb-2"
<input id="targetValue" type="range" formControlName="targetValue" min="1" max="100" step="0.01" >Target Value: {{ diceForm.get('targetValue')?.value | number: '1.0-2' }}</label
class="w-full h-2 bg-deep-blue-light rounded-lg appearance-none cursor-pointer range-lg accent-emerald"> >
@if (hasError('targetValue', 'required')) { <input
id="targetValue"
type="range"
formControlName="targetValue"
min="1"
max="100"
step="0.01"
class="w-full h-2 bg-deep-blue-light rounded-lg appearance-none cursor-pointer range-lg accent-emerald"
/>
@if (hasError('targetValue', 'required')) {
<span class="text-accent-red text-sm mt-1 block">Target Value is required</span> <span class="text-accent-red text-sm mt-1 block">Target Value is required</span>
} }
@if (hasError('targetValue', 'min')) { @if (hasError('targetValue', 'min')) {
<span class="text-accent-red text-sm mt-1 block">Target Value must be at least 1</span> <span class="text-accent-red text-sm mt-1 block"
>Target Value must be at least 1</span
>
} }
@if (hasError('targetValue', 'max')) { @if (hasError('targetValue', 'max')) {
<span class="text-accent-red text-sm mt-1 block">Target Value must be at most 100</span> <span class="text-accent-red text-sm mt-1 block"
>Target Value must be at most 100</span
>
} }
</div> </div>
</div> </div>
<div class="info space-y-2 text-text-secondary"> <div class="info space-y-2 text-text-secondary">
<p>Win Chance: <span class="text-white">{{ winChance() | number:'1.0-2' }}%</span></p> <p>
<p>Potential Win: <span class="text-white">{{ potentialWin() | currency:'EUR':'symbol':'1.2-2' }}</span></p> Win Chance: <span class="text-white">{{ winChance() | number: '1.0-2' }}%</span>
</p>
<p>
Potential Win:
<span class="text-white">{{
potentialWin() | currency: 'EUR' : 'symbol' : '1.2-2'
}}</span>
</p>
</div> </div>
<button type="submit" class="button-primary w-full py-2 font-bold">Roll Dice</button> <button type="submit" class="button-primary w-full py-2 font-bold">Roll Dice</button>
@ -61,11 +107,12 @@
</div> </div>
</div> </div>
@if (rolledValue() !== null) { @if (rolledValue() !== null) {
<div class="result max-w-sm mx-auto card p-6 mt-8 text-center"> <div class="result max-w-sm mx-auto card p-6 mt-8 text-center">
@if (win()) { @if (win()) {
<p class="text-emerald text-base font-semibold">You Won! Payout: {{ payout() | currency:'EUR':'symbol':'1.2-2' }}</p> <p class="text-emerald text-base font-semibold">
You Won! Payout: {{ payout() | currency: 'EUR' : 'symbol' : '1.2-2' }}
</p>
} @else { } @else {
<p class="text-accent-red text-base font-semibold">You Lost.</p> <p class="text-accent-red text-base font-semibold">You Lost.</p>
} }

View file

@ -1,10 +1,16 @@
import { Component, signal, inject, OnInit } from '@angular/core'; import { Component, signal, inject, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; import {
FormBuilder,
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { DiceService } from './dice.service'; import { DiceService } from './dice.service';
import { DiceDto, DiceResult } from './dice.model'; import { DiceDto, DiceResult } from './dice.model';
import { debounceTime, tap } from 'rxjs/operators'; import { debounceTime, tap } from 'rxjs/operators';
import {UserService} from "@service/user.service"; import { UserService } from '@service/user.service';
type DiceFormGroup = FormGroup<{ type DiceFormGroup = FormGroup<{
betAmount: FormControl<number | null>; betAmount: FormControl<number | null>;
@ -23,7 +29,6 @@ export class DiceComponent implements OnInit {
private readonly diceService = inject(DiceService); private readonly diceService = inject(DiceService);
private readonly userService = inject(UserService); private readonly userService = inject(UserService);
rolledValue = signal<number | null>(null); rolledValue = signal<number | null>(null);
win = signal<boolean | null>(null); win = signal<boolean | null>(null);
payout = signal<number | null>(null); payout = signal<number | null>(null);
@ -34,21 +39,22 @@ export class DiceComponent implements OnInit {
private readonly MAX_DICE_VALUE = 100; private readonly MAX_DICE_VALUE = 100;
constructor() { constructor() {}
}
ngOnInit(): void { ngOnInit(): void {
this.diceForm.valueChanges.pipe( this.diceForm.valueChanges
debounceTime(100), .pipe(
tap(() => this.calculateWinChanceAndPotentialWin()) debounceTime(100),
).subscribe(); tap(() => this.calculateWinChanceAndPotentialWin())
)
.subscribe();
this.calculateWinChanceAndPotentialWin(); this.calculateWinChanceAndPotentialWin();
} }
createDiceForm(): DiceFormGroup { createDiceForm(): DiceFormGroup {
return this.formBuilder.group({ return this.formBuilder.group({
betAmount: new FormControl<number | null>(1.00, { betAmount: new FormControl<number | null>(1.0, {
validators: [Validators.required, Validators.min(0.01)], validators: [Validators.required, Validators.min(0.01)],
nonNullable: true, nonNullable: true,
}), }),
@ -56,7 +62,7 @@ export class DiceComponent implements OnInit {
validators: [Validators.required], validators: [Validators.required],
nonNullable: true, nonNullable: true,
}), }),
targetValue: new FormControl<number | null>(50.50, { targetValue: new FormControl<number | null>(50.5, {
validators: [Validators.required, Validators.min(1), Validators.max(100)], validators: [Validators.required, Validators.min(1), Validators.max(100)],
nonNullable: true, nonNullable: true,
}), }),
@ -107,7 +113,7 @@ export class DiceComponent implements OnInit {
}, },
error: (error) => { error: (error) => {
console.error('Dice roll failed:', error); console.error('Dice roll failed:', error);
} },
}); });
} }

View file

@ -4,12 +4,12 @@ import { Observable } from 'rxjs';
import { DiceDto, DiceResult } from './dice.model'; import { DiceDto, DiceResult } from './dice.model';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root',
}) })
export class DiceService { export class DiceService {
private apiUrl = '/backend/dice'; private apiUrl = '/backend/dice';
constructor(private http: HttpClient) { } constructor(private http: HttpClient) {}
rollDice(diceDto: DiceDto): Observable<DiceResult> { rollDice(diceDto: DiceDto): Observable<DiceResult> {
return this.http.post<DiceResult>(this.apiUrl, diceDto); return this.http.post<DiceResult>(this.apiUrl, diceDto);