From 513ff7886b614c2e549fcacf220d626335ef070d Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 7 May 2025 15:22:37 +0200 Subject: [PATCH 1/3] feat: add user balance updates during lootbox opening --- .../lootbox-opening.component.css | 2 ++ .../lootbox-opening.component.html | 9 ++++++++- .../lootbox-opening.component.ts | 20 ++++++++++++++++++- frontend/src/app/service/user.service.ts | 11 ++++++++++ .../components/navbar/navbar.component.ts | 3 +++ 5 files changed, 43 insertions(+), 2 deletions(-) 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..8867cb1 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 @@ -85,12 +85,19 @@ 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..3b4d0e8 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,7 @@ 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'; @Component({ selector: 'app-lootbox-opening', @@ -26,6 +27,7 @@ export default class LootboxOpeningComponent { private route: ActivatedRoute, private router: Router, private lootboxService: LootboxService, + private userService: UserService, private cdr: ChangeDetectorRef ) { this.loadLootbox(); @@ -58,6 +60,10 @@ export default class LootboxOpeningComponent { if (!this.lootbox || this.isOpening) return; this.resetState(true); + + if (this.lootbox.price) { + this.userService.updateLocalBalance(-this.lootbox.price); + } setTimeout(() => { this.lootboxService.purchaseLootBox(this.lootbox!.id).subscribe({ @@ -72,6 +78,7 @@ export default class LootboxOpeningComponent { this.generateCasePrizes(reward); this.isOpening = false; this.isOpen = true; + this.cdr.detectChanges(); } @@ -80,7 +87,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 +124,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); } diff --git a/frontend/src/app/service/user.service.ts b/frontend/src/app/service/user.service.ts index 5f668c2..9031845 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..c7ea92f 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() { From 790485decc393e7bc37c31455f601c918689458c Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 7 May 2025 15:30:19 +0200 Subject: [PATCH 2/3] feat(lootboxes): add balance check for opening lootboxes --- .../lootbox-opening.component.html | 21 +++++++++--- .../lootbox-opening.component.ts | 23 +++++++++++++ .../lootbox-selection.component.html | 10 ++++-- .../lootbox-selection.component.ts | 32 ++++++++++++++++++- 4 files changed, 78 insertions(+), 8 deletions(-) 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 8867cb1..841a985 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 @@
@@ -87,11 +93,16 @@ > 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..6ee3462 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; + } } From c92a1821232991d3bda32f3f7ef48687bc5737b1 Mon Sep 17 00:00:00 2001 From: Jan-Marlon Leibl Date: Wed, 7 May 2025 15:30:40 +0200 Subject: [PATCH 3/3] style: fix formatting and add missing commas in code --- .../lootbox-opening/lootbox-opening.component.html | 10 +++++----- .../lootbox-opening/lootbox-opening.component.ts | 14 +++++++------- .../lootbox-selection.component.html | 2 +- .../lootbox-selection.component.ts | 10 +++++----- frontend/src/app/service/user.service.ts | 4 ++-- .../shared/components/navbar/navbar.component.ts | 2 +- 6 files changed, 21 insertions(+), 21 deletions(-) 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 841a985..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 @@ -34,7 +34,7 @@ [disabled]="!hasEnoughBalance()" [ngClass]="{ 'button-primary': hasEnoughBalance(), - 'bg-gray-500 cursor-not-allowed': !hasEnoughBalance() + 'bg-gray-500 cursor-not-allowed': !hasEnoughBalance(), }" class="w-full py-3 text-lg font-semibold rounded" > @@ -91,14 +91,14 @@ class="flex justify-center gap-4 mt-8 animation-fade" [class.visible]="animationCompleted" > -