diff --git a/frontend/public/coinflip.png b/frontend/public/coinflip.png
deleted file mode 100644
index 0f39ca8..0000000
Binary files a/frontend/public/coinflip.png and /dev/null differ
diff --git a/frontend/public/poker.webp b/frontend/public/poker.webp
new file mode 100644
index 0000000..329f4da
Binary files /dev/null and b/frontend/public/poker.webp differ
diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts
index 6e9f9b7..b8adc5f 100644
--- a/frontend/src/app/app.routes.ts
+++ b/frontend/src/app/app.routes.ts
@@ -45,11 +45,6 @@ export const routes: Routes = [
loadComponent: () => import('./feature/game/blackjack/blackjack.component'),
canActivate: [authGuard],
},
- {
- path: 'game/coinflip',
- loadComponent: () => import('./feature/game/coinflip/coinflip.component'),
- canActivate: [authGuard],
- },
{
path: 'game/slots',
loadComponent: () => import('./feature/game/slots/slots.component'),
diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.css b/frontend/src/app/feature/game/coinflip/coinflip.component.css
deleted file mode 100644
index 06c9671..0000000
--- a/frontend/src/app/feature/game/coinflip/coinflip.component.css
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Custom CSS for 3D Transformations and Coin Flip */
-@keyframes flipToHeads {
- 0% {
- transform: rotateY(0);
- }
- 100% {
- transform: rotateY(1800deg); /* End with heads facing up (even number of Y rotations) */
- }
-}
-
-@keyframes flipToTails {
- 0% {
- transform: rotateY(0);
- }
- 100% {
- transform: rotateY(1980deg); /* End with tails facing up (odd number of Y rotations) */
- }
-}
-
-.coin-container {
- width: 180px;
- height: 180px;
- perspective: 1000px;
- margin: 20px auto;
-}
-
-.coin {
- width: 100%;
- height: 100%;
- position: relative;
- transform-style: preserve-3d;
- transition: transform 0.01s;
- transform: rotateY(0deg);
- box-shadow: 0 0 30px rgba(0, 0, 0, 0.4);
-}
-
-.coin-side {
- width: 100%;
- height: 100%;
- position: absolute;
- backface-visibility: hidden;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- font-weight: bold;
- font-size: 24px;
- box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.2);
- border: 8px solid rgba(255, 255, 255, 0.2);
-}
-
-.front {
- background: linear-gradient(45deg, #ffd700, #ffb700);
- color: #333;
- z-index: 2;
- transform: rotateY(0);
-}
-
-.back {
- background: linear-gradient(45deg, #5a5a5a, #333333);
- color: white;
- z-index: 1;
- transform: rotateY(180deg);
-}
-
-/* We apply transform directly to the SVG element in HTML */
-
-/* Text for both sides */
-.coin-text {
- /* Ensure text is readable */
- user-select: none;
- pointer-events: none;
-}
-
-/* Animation classes */
-.coin.animate-to-heads {
- animation: flipToHeads 1s ease-in-out forwards;
-}
-
-.coin.animate-to-tails {
- animation: flipToTails 1s ease-in-out forwards;
-}
-
-/* Make the buttons more responsive */
-button:not([disabled]) {
- cursor: pointer;
- transition: all 0.2s ease;
-}
-
-button:not([disabled]):hover {
- transform: translateY(-2px);
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
-}
-
-button:not([disabled]):active {
- transform: translateY(1px);
-}
-
-/* Animation for results */
-@keyframes popIn {
- 0% {
- transform: scale(0.8);
- opacity: 0;
- }
- 70% {
- transform: scale(1.1);
- opacity: 1;
- }
- 100% {
- transform: scale(1);
- opacity: 1;
- }
-}
-
-.result-text {
- animation: popIn 0.5s ease-out forwards;
-}
diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.html b/frontend/src/app/feature/game/coinflip/coinflip.component.html
deleted file mode 100644
index 671bc31..0000000
--- a/frontend/src/app/feature/game/coinflip/coinflip.component.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
-
- @if (gameResult()) {
-
-
- {{ gameResult()?.isWin ? 'You Won!' : 'You Lost' }}
-
-
- Coin landed on:
- {{
- gameResult()?.coinSide === 'HEAD' ? 'HEAD' : 'TAILS'
- }}
-
- @if (gameResult()?.isWin) {
-
- +{{ gameResult()?.payout | currency: 'EUR' }}
-
- }
-
- }
-
-
- @if (errorMessage()) {
-
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Game Information
-
-
-
-
Current Bet:
-
0 ? 'text-accent-red' : 'text-text-secondary'">
- €
-
-
-
-
-
- Your Balance:
-
- {{ balance() | currency: 'EUR' }}
-
-
-
-
- @if (!gameInProgress()) {
-
-
-
-
-
-
- }
-
-
-
-
-
- Cannot exceed balance
-
-
-
-
-
-
-
How to Play
-
- - • Choose your bet amount
- - • Select Heads or Tails
- - • Win double your bet if correct
-
-
-
-
-
-
-
diff --git a/frontend/src/app/feature/game/coinflip/coinflip.component.ts b/frontend/src/app/feature/game/coinflip/coinflip.component.ts
deleted file mode 100644
index 1766e4d..0000000
--- a/frontend/src/app/feature/game/coinflip/coinflip.component.ts
+++ /dev/null
@@ -1,248 +0,0 @@
-import { NgClass, NgIf, CurrencyPipe, CommonModule } from '@angular/common';
-import { HttpClient } from '@angular/common/http';
-import { FormsModule } from '@angular/forms';
-import {
- ChangeDetectionStrategy,
- Component,
- ElementRef,
- inject,
- OnInit,
- signal,
- ViewChild,
-} from '@angular/core';
-import { AnimatedNumberComponent } from '@blackjack/components/animated-number/animated-number.component';
-import { catchError, finalize } from 'rxjs/operators';
-import { of } from 'rxjs';
-import { AuthService } from '@service/auth.service';
-import { AudioService } from '@shared/services/audio.service';
-import { CoinflipGame, CoinflipRequest } from './models/coinflip.model';
-
-@Component({
- selector: 'app-coinflip',
- standalone: true,
- imports: [AnimatedNumberComponent, CurrencyPipe, FormsModule, CommonModule, NgIf, NgClass],
- templateUrl: './coinflip.component.html',
- styleUrl: './coinflip.component.css',
- changeDetection: ChangeDetectionStrategy.OnPush,
-})
-export default class CoinflipComponent implements OnInit {
- currentBet = signal(10);
- balance = signal(0);
- gameInProgress = signal(false);
- isActionInProgress = signal(false);
- gameResult = signal(null);
- betInputValue = signal(10);
- errorMessage = signal('');
- isInvalidBet = signal(false);
-
- @ViewChild('coinElement') coinElement?: ElementRef;
-
- audioService = inject(AudioService);
- authService = inject(AuthService);
- private http = inject(HttpClient);
-
- private coinflipSound?: HTMLAudioElement;
-
- ngOnInit(): void {
- // Subscribe to user updates for real-time balance changes
- this.authService.userSubject.subscribe((user) => {
- if (user) {
- this.balance.set(user.balance);
- }
- });
-
- // Initialize coinflip sound
- this.coinflipSound = new Audio('/sounds/coinflip.mp3');
- }
-
- setBetAmount(percentage: number) {
- const newBet = Math.floor(this.balance() * percentage);
- this.betInputValue.set(newBet > 0 ? newBet : 1);
- this.currentBet.set(this.betInputValue());
- }
-
- updateBet(event: Event) {
- const inputElement = event.target as HTMLInputElement;
- let value = Number(inputElement.value);
-
- // Reset invalid bet state
- this.isInvalidBet.set(false);
-
- // Enforce minimum bet of 1
- if (value <= 0) {
- 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() {
- this.placeBet('HEAD');
- }
-
- betTails() {
- this.placeBet('TAILS');
- }
-
- private placeBet(side: 'HEAD' | 'TAILS') {
- if (this.gameInProgress() || this.isActionInProgress()) return;
-
- // Reset previous result
- this.gameResult.set(null);
- this.errorMessage.set('');
-
- // Set game state
- this.gameInProgress.set(true);
- this.isActionInProgress.set(true);
-
- // Play bet sound
- this.audioService.playBetSound();
-
- // Create bet request
- const request: CoinflipRequest = {
- betAmount: this.currentBet(),
- coinSide: side,
- };
-
- // Call API
- this.http
- .post('/backend/coinflip', request)
- .pipe(
- catchError((error) => {
- console.error('Error playing coinflip:', error);
-
- if (error.status === 400 && error.error.message.includes('insufficient')) {
- this.errorMessage.set('Insufficient funds');
- } else {
- this.errorMessage.set('An error occurred. Please try again.');
- }
-
- this.gameInProgress.set(false);
- return of(null);
- }),
- finalize(() => {
- this.isActionInProgress.set(false);
- })
- )
- .subscribe((result) => {
- if (!result) return;
-
- console.log('API response:', result);
-
- // Fix potential property naming inconsistency from the backend
- const fixedResult: CoinflipGame = {
- isWin: result.isWin ?? result.win,
- payout: result.payout,
- coinSide: result.coinSide,
- };
-
- console.log('Fixed result:', fixedResult);
-
- // Play coin flip animation and sound
- this.playCoinFlipAnimation(fixedResult.coinSide);
-
- // Set result after animation completes
- setTimeout(() => {
- this.gameResult.set(fixedResult);
-
- // Update balance with new value from auth service
- this.authService.loadCurrentUser();
-
- // Play win sound if player won
- if (fixedResult.isWin) {
- this.audioService.playWinSound();
- }
-
- // Reset game state after showing result
- setTimeout(() => {
- this.gameInProgress.set(false);
- }, 1500);
- }, 1100); // Just after animation ends
- });
- }
-
- private playCoinFlipAnimation(result: 'HEAD' | 'TAILS') {
- if (!this.coinElement) return;
-
- const coinEl = this.coinElement.nativeElement;
-
- // Reset any existing animations
- coinEl.classList.remove('animate-to-heads', 'animate-to-tails');
-
- // Reset any inline styles from previous animations
- coinEl.style.transform = '';
-
- // Force a reflow to restart animation
- void coinEl.offsetWidth;
-
- // Play flip sound
- if (this.coinflipSound) {
- this.coinflipSound.currentTime = 0;
- this.coinflipSound.play().catch((err) => console.error('Error playing sound:', err));
- }
-
- // Add appropriate animation class based on result
- if (result === 'HEAD') {
- coinEl.classList.add('animate-to-heads');
- } else {
- coinEl.classList.add('animate-to-tails');
- }
-
- 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();
- const isWinner = result?.isWin || result?.win;
- return isWinner ? 'text-emerald-500' : 'text-accent-red';
- }
-}
diff --git a/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts b/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts
deleted file mode 100644
index f87a3f9..0000000
--- a/frontend/src/app/feature/game/coinflip/models/coinflip.model.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export interface CoinflipGame {
- isWin?: boolean;
- win?: boolean;
- payout: number;
- coinSide: 'HEAD' | 'TAILS';
-}
-
-export interface CoinflipRequest {
- betAmount: number;
- coinSide: 'HEAD' | 'TAILS';
-}
diff --git a/frontend/src/app/feature/home/home.component.ts b/frontend/src/app/feature/home/home.component.ts
index 1fad4cb..494c03f 100644
--- a/frontend/src/app/feature/home/home.component.ts
+++ b/frontend/src/app/feature/home/home.component.ts
@@ -48,9 +48,9 @@ export default class HomeComponent implements OnInit {
featuredGames: Game[] = [
{
id: '1',
- name: 'Coinflip',
- image: '/coinflip.png',
- route: '/game/coinflip',
+ name: 'Poker',
+ image: '/poker.webp',
+ route: '/game/poker',
},
{
id: '2',
diff --git a/justfile b/justfile
index 4fc777c..1d68253 100644
--- a/justfile
+++ b/justfile
@@ -21,7 +21,3 @@ build-be:
# Builds the frontend docker image
build-fe:
docker buildx build -f frontend/.docker/Dockerfile -t git.kjan.de/szut/casino-frontend:latest frontend
-
-# Formats the code duh
-format:
- cd frontend && bunx prettier --write "src/**/*.{ts,html,css,scss}"