diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css index 1272a49..4e5f67f 100644 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css +++ b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.css @@ -312,9 +312,11 @@ body { opacity 0.5s ease-out, transform 0.5s ease-out; transition-delay: 0.5s; + pointer-events: none; /* Prevent clicks when invisible */ } .animation-fade.visible { opacity: 1; transform: translateY(0); + pointer-events: auto; /* Enable clicks when visible */ } diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html index 0da3ed8..cc234ac 100644 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html +++ b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.html @@ -31,9 +31,15 @@
@@ -85,12 +91,24 @@ class="flex justify-center gap-4 mt-8 animation-fade" [class.visible]="animationCompleted" > - diff --git a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts index cd3ed1f..c1255ef 100644 --- a/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts +++ b/frontend/src/app/feature/lootboxes/lootbox-opening/lootbox-opening.component.ts @@ -4,6 +4,8 @@ import { ActivatedRoute, Router } from '@angular/router'; import { LootboxService } from '../services/lootbox.service'; import { LootBox, Reward } from 'app/model/LootBox'; import { NavbarComponent } from '@shared/components/navbar/navbar.component'; +import { UserService } from '@service/user.service'; +import { User } from 'app/model/User'; @Component({ selector: 'app-lootbox-opening', @@ -21,14 +23,20 @@ export default class LootboxOpeningComponent { wonReward: Reward | null = null; prizeList: Reward[] = []; animationCompleted = false; + currentUser: User | null = null; constructor( private route: ActivatedRoute, private router: Router, private lootboxService: LootboxService, + private userService: UserService, private cdr: ChangeDetectorRef ) { this.loadLootbox(); + this.userService.currentUser$.subscribe((user) => { + this.currentUser = user; + this.cdr.detectChanges(); + }); } private loadLootbox(): void { @@ -57,8 +65,24 @@ export default class LootboxOpeningComponent { openLootbox(): void { if (!this.lootbox || this.isOpening) return; + // Check if user has enough balance + if (!this.hasEnoughBalance()) { + this.error = 'Nicht genug Guthaben, um diese Lootbox zu öffnen.'; + window.scrollTo(0, 0); + this.cdr.detectChanges(); + setTimeout(() => { + this.error = ''; + this.cdr.detectChanges(); + }, 5000); + return; + } + this.resetState(true); + if (this.lootbox.price) { + this.userService.updateLocalBalance(-this.lootbox.price); + } + setTimeout(() => { this.lootboxService.purchaseLootBox(this.lootbox!.id).subscribe({ next: this.handleRewardSuccess.bind(this), @@ -72,6 +96,7 @@ export default class LootboxOpeningComponent { this.generateCasePrizes(reward); this.isOpening = false; this.isOpen = true; + this.cdr.detectChanges(); } @@ -80,7 +105,12 @@ export default class LootboxOpeningComponent { const rewards = this.lootbox.rewards; const fallback = rewards[Math.floor(Math.random() * rewards.length)]; - this.handleRewardSuccess(fallback); + + this.wonReward = fallback; + this.generateCasePrizes(fallback); + this.isOpening = false; + this.isOpen = true; + this.cdr.detectChanges(); } private resetState(isOpening = false): void { @@ -112,6 +142,12 @@ export default class LootboxOpeningComponent { setTimeout(() => { this.animationCompleted = true; + + if (this.wonReward) { + this.userService.updateLocalBalance(this.wonReward.value); + } + + this.userService.refreshCurrentUser(); this.cdr.detectChanges(); }, 10000); } @@ -168,4 +204,9 @@ export default class LootboxOpeningComponent { if (!this.wonReward || !this.lootbox) return ''; return this.wonReward.value > (this.lootbox.price || 0) ? 'text-emerald' : 'text-accent-red'; } + + hasEnoughBalance(): boolean { + if (!this.currentUser || !this.lootbox) return false; + return this.currentUser.balance >= this.lootbox.price; + } } diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html index 2699f1a..25d8df0 100644 --- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html +++ b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.html @@ -44,9 +44,15 @@
diff --git a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts index 217af16..bc3023c 100644 --- a/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts +++ b/frontend/src/app/feature/lootboxes/lootbox-selection/lootbox-selection.component.ts @@ -5,6 +5,8 @@ import { LootboxService } from '../services/lootbox.service'; import { LootBox } from 'app/model/LootBox'; import { Router } from '@angular/router'; import { timeout } from 'rxjs'; +import { UserService } from '@service/user.service'; +import { User } from 'app/model/User'; @Component({ selector: 'app-lootbox-selection', @@ -17,6 +19,7 @@ export default class LootboxSelectionComponent implements OnInit { lootboxes: LootBox[] = []; isLoading = true; error = ''; + currentUser: User | null = null; // Fallback data in case the API call fails fallbackLootboxes: LootBox[] = [ @@ -86,11 +89,16 @@ export default class LootboxSelectionComponent implements OnInit { constructor( private lootboxService: LootboxService, private router: Router, - private cdr: ChangeDetectorRef + private cdr: ChangeDetectorRef, + private userService: UserService ) {} ngOnInit(): void { this.loadLootboxes(); + this.userService.currentUser$.subscribe((user) => { + this.currentUser = user; + this.cdr.detectChanges(); + }); } loadLootboxes(): void { @@ -120,6 +128,24 @@ export default class LootboxSelectionComponent implements OnInit { } openLootbox(lootboxId: number): void { + const lootbox = this.lootboxes.find((box) => box.id === lootboxId); + + if (!lootbox) { + return; + } + + if (!this.currentUser || this.currentUser.balance < lootbox.price) { + this.error = 'Nicht genug Guthaben, um diese Lootbox zu öffnen.'; + // Scroll to top to see the error message + window.scrollTo(0, 0); + this.cdr.detectChanges(); + setTimeout(() => { + this.error = ''; + this.cdr.detectChanges(); + }, 5000); + return; + } + this.router.navigate(['/game/lootboxes/open', lootboxId]); } @@ -136,4 +162,8 @@ export default class LootboxSelectionComponent implements OnInit { formatProbability(probability: number): string { return (probability * 100).toFixed(0) + '%'; } + + hasEnoughBalance(price: number): boolean { + return !!this.currentUser && this.currentUser.balance >= price; + } } diff --git a/frontend/src/app/service/user.service.ts b/frontend/src/app/service/user.service.ts index 5f668c2..a76e7b4 100644 --- a/frontend/src/app/service/user.service.ts +++ b/frontend/src/app/service/user.service.ts @@ -33,6 +33,17 @@ export class UserService { this.getCurrentUser().subscribe(); } + public updateLocalBalance(amount: number): void { + const currentUser = this.currentUserSubject.getValue(); + if (currentUser) { + const updatedUser = { + ...currentUser, + balance: currentUser.balance + amount, + }; + this.currentUserSubject.next(updatedUser); + } + } + public createUser(id: string, username: string): Observable { return this.http .post('/backend/user', { diff --git a/frontend/src/app/shared/components/navbar/navbar.component.ts b/frontend/src/app/shared/components/navbar/navbar.component.ts index 5405b07..c8dfe40 100644 --- a/frontend/src/app/shared/components/navbar/navbar.component.ts +++ b/frontend/src/app/shared/components/navbar/navbar.component.ts @@ -31,7 +31,10 @@ export class NavbarComponent implements OnInit, OnDestroy { ngOnInit() { this.userSubscription = this.userService.currentUser$.subscribe((user) => { this.balance.set(user?.balance ?? 0); + console.log('Updated navbar balance:', user?.balance); }); + + this.userService.refreshCurrentUser(); } ngOnDestroy() {