diff --git a/frontend/bun.lock b/frontend/bun.lock
index f09b071..91de068 100644
--- a/frontend/bun.lock
+++ b/frontend/bun.lock
@@ -14,6 +14,10 @@
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
+ "@fortawesome/angular-fontawesome": "^1.0.0",
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-brands-svg-icons": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@stripe/stripe-js": "^5.6.0",
"@tailwindcss/postcss": "^4.0.3",
"keycloak-angular": "^16.0.1",
@@ -373,6 +377,16 @@
"@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.5", "", { "dependencies": { "@eslint/core": "^0.10.0", "levn": "^0.4.1" } }, "sha512-lB05FkqEdUg2AA0xEbUz0SnkXT1LcCTa438W4IWTUh4hdOnVbQyOJ81OrDXsJk/LSiJHubgGEFoR5EHq1NsH1A=="],
+ "@fortawesome/angular-fontawesome": ["@fortawesome/angular-fontawesome@1.0.0", "", { "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.7.1", "tslib": "^2.8.1" }, "peerDependencies": { "@angular/core": "^19.0.0" } }, "sha512-EC2fYuXIuw2ld1kzJi+zysWus6OeGGfLQtbh0hW9zyyq5aBo8ZJkcJKBsVQ8E6Mg7nHyTWaXn+sdcXTPDWz+UQ=="],
+
+ "@fortawesome/fontawesome-common-types": ["@fortawesome/fontawesome-common-types@6.7.2", "", {}, "sha512-Zs+YeHUC5fkt7Mg1l6XTniei3k4bwG/yo3iFUtZWd/pMx9g3fdvkSK9E0FOC+++phXOka78uJcYb8JaFkW52Xg=="],
+
+ "@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-yxtOBWDrdi5DD5o1pmVdq3WMCvnobT0LU6R8RyyVXPvFRd2o79/0NCuQoCjNTeZz9EzA9xS3JxNWfv54RIHFEA=="],
+
+ "@fortawesome/free-brands-svg-icons": ["@fortawesome/free-brands-svg-icons@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-zu0evbcRTgjKfrr77/2XX+bU+kuGfjm0LbajJHVIgBWNIDzrhpRxiCPNT8DW5AdmSsq7Mcf9D1bH0aSeSUSM+Q=="],
+
+ "@fortawesome/free-solid-svg-icons": ["@fortawesome/free-solid-svg-icons@6.7.2", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.7.2" } }, "sha512-GsBrnOzU8uj0LECDfD5zomZJIjrPhIlWU82AHwa2s40FKH+kcxQaBvBo3Z4TxyZHIyX8XTDxsyA33/Vx9eFuQA=="],
+
"@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
"@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="],
diff --git a/frontend/package.json b/frontend/package.json
index c6be094..c79aae0 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -23,6 +23,10 @@
"@angular/platform-browser": "^18.2.0",
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
+ "@fortawesome/angular-fontawesome": "^1.0.0",
+ "@fortawesome/fontawesome-svg-core": "^6.7.2",
+ "@fortawesome/free-brands-svg-icons": "^6.7.2",
+ "@fortawesome/free-solid-svg-icons": "^6.7.2",
"@stripe/stripe-js": "^5.6.0",
"@tailwindcss/postcss": "^4.0.3",
"keycloak-angular": "^16.0.1",
@@ -49,4 +53,4 @@
"typescript": "~5.5.2",
"typescript-eslint": "8.23.0"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html
index 0680b43..41260d2 100644
--- a/frontend/src/app/app.component.html
+++ b/frontend/src/app/app.component.html
@@ -1 +1,6 @@
-
+
diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts
index 7dea888..bbc5fb6 100644
--- a/frontend/src/app/app.component.ts
+++ b/frontend/src/app/app.component.ts
@@ -2,11 +2,12 @@ import { Component, ChangeDetectionStrategy } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { KeycloakAngularModule } from 'keycloak-angular';
+import { FooterComponent } from './shared/components/footer/footer.component';
@Component({
selector: 'app-root',
standalone: true,
- imports: [CommonModule, RouterOutlet, KeycloakAngularModule],
+ imports: [CommonModule, RouterOutlet, KeycloakAngularModule, FooterComponent],
providers: [],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
diff --git a/frontend/src/app/app.config.ts b/frontend/src/app/app.config.ts
index c6b9f77..8401ece 100644
--- a/frontend/src/app/app.config.ts
+++ b/frontend/src/app/app.config.ts
@@ -4,6 +4,7 @@ import {
provideExperimentalZonelessChangeDetection,
} from '@angular/core';
import { provideRouter } from '@angular/router';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { routes } from './app.routes';
import {
@@ -38,6 +39,7 @@ export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
KeycloakAngularModule,
+ FontAwesomeModule,
{
provide: APP_INITIALIZER,
useFactory: initializeApp,
diff --git a/frontend/src/app/feature/deposit/deposit.component.ts b/frontend/src/app/feature/deposit/deposit.component.ts
index 6b8393d..36ec63f 100644
--- a/frontend/src/app/feature/deposit/deposit.component.ts
+++ b/frontend/src/app/feature/deposit/deposit.component.ts
@@ -7,7 +7,6 @@ import { environment } from '../../../environments/environment';
import { NgIf } from '@angular/common';
import {
MatDialogActions,
- MatDialogClose,
MatDialogContent,
MatDialogRef,
MatDialogTitle,
@@ -23,7 +22,6 @@ import { MatButton } from '@angular/material/button';
MatDialogTitle,
MatDialogContent,
MatDialogActions,
- MatDialogClose,
MatButton,
],
templateUrl: './deposit.component.html',
diff --git a/frontend/src/app/feature/home/home.component.html b/frontend/src/app/feature/home/home.component.html
index b85ce29..27cec95 100644
--- a/frontend/src/app/feature/home/home.component.html
+++ b/frontend/src/app/feature/home/home.component.html
@@ -1,14 +1,4 @@
-
+
diff --git a/frontend/src/app/feature/home/home.component.ts b/frontend/src/app/feature/home/home.component.ts
index a4b2b8b..7475214 100644
--- a/frontend/src/app/feature/home/home.component.ts
+++ b/frontend/src/app/feature/home/home.component.ts
@@ -3,10 +3,11 @@ import { KeycloakService } from 'keycloak-angular';
import { MatDialog } from '@angular/material/dialog';
import { DepositComponent } from '../deposit/deposit.component';
+import { NavbarComponent } from '../../shared/components/navbar/navbar.component';
@Component({
selector: 'app-homepage',
standalone: true,
- imports: [],
+ imports: [NavbarComponent],
templateUrl: './home.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
diff --git a/frontend/src/app/feature/landing/landing.component.html b/frontend/src/app/feature/landing/landing.component.html
index 80d5974..fb7e0e2 100644
--- a/frontend/src/app/feature/landing/landing.component.html
+++ b/frontend/src/app/feature/landing/landing.component.html
@@ -1,5 +1,142 @@
-@if (isLoggedIn) {
-
-} @else {
-
-}
+
+
+
+
+
+
+
+ Willkommensbonus
+
+
200% bis zu 500€
+
+ 200 Freispiele
+
+
+
+
+
+
Beliebte Spiele
+
+
+
+
+
+
+
Slots
+
Klassische Spielautomaten
+
+
+
+
+
+
Plinko
+
Spannendes Geschicklichkeitsspiel
+
+
+
+
+
+
Blackjack
+
Klassisches Kartenspiel
+
+
+
+
+
+
+
+
+
Poker
+
Texas Hold'em & mehr
+
+
+
+
+
+
Liars Dice
+
Würfelspiel mit Strategie
+
+
+
+
+
+
Lootboxen
+
Überraschungskisten
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
50 Mio.€+
+
Ausgezahlt
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/app/feature/landing/landing.component.ts b/frontend/src/app/feature/landing/landing.component.ts
index d2e28c0..7fa92b6 100644
--- a/frontend/src/app/feature/landing/landing.component.ts
+++ b/frontend/src/app/feature/landing/landing.component.ts
@@ -1,21 +1,55 @@
-import { Component, inject } from '@angular/core';
-import { KeycloakService } from 'keycloak-angular';
-import { RouterLink } from '@angular/router';
+import { ChangeDetectionStrategy, Component, OnInit, OnDestroy } from '@angular/core';
+import { NavbarComponent } from '../../shared/components/navbar/navbar.component';
+import { NgFor } from '@angular/common';
@Component({
- selector: 'app-landing',
+ selector: 'app-landing-page',
standalone: true,
- imports: [RouterLink],
+ imports: [NavbarComponent, NgFor],
templateUrl: './landing.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class LandingComponent {
- private keycloakService: KeycloakService = inject(KeycloakService);
+export class LandingComponent implements OnInit, OnDestroy {
+ currentSlide = 0;
+ private autoplayInterval: ReturnType
| undefined;
- public isLoggedIn = this.keycloakService.isLoggedIn();
+ ngOnInit() {
+ this.startAutoplay();
+ }
- public login() {
- const baseUrl = window.location.origin;
+ ngOnDestroy() {
+ this.stopAutoplay();
+ }
- this.keycloakService.login({ redirectUri: `${baseUrl}/home` });
+ prevSlide() {
+ this.currentSlide = this.currentSlide === 0 ? 1 : 0;
+ this.resetAutoplay();
+ }
+
+ nextSlide() {
+ this.currentSlide = this.currentSlide === 1 ? 0 : 1;
+ this.resetAutoplay();
+ }
+
+ goToSlide(index: number) {
+ this.currentSlide = index;
+ this.resetAutoplay();
+ }
+
+ private startAutoplay() {
+ this.autoplayInterval = setInterval(() => {
+ this.nextSlide();
+ }, 5000);
+ }
+
+ private stopAutoplay() {
+ if (this.autoplayInterval) {
+ clearInterval(this.autoplayInterval);
+ }
+ }
+
+ private resetAutoplay() {
+ this.stopAutoplay();
+ this.startAutoplay();
}
}
diff --git a/frontend/src/app/shared/components/footer/footer.component.html b/frontend/src/app/shared/components/footer/footer.component.html
new file mode 100644
index 0000000..87c4682
--- /dev/null
+++ b/frontend/src/app/shared/components/footer/footer.component.html
@@ -0,0 +1,80 @@
+
diff --git a/frontend/src/app/shared/components/footer/footer.component.ts b/frontend/src/app/shared/components/footer/footer.component.ts
new file mode 100644
index 0000000..1c3b309
--- /dev/null
+++ b/frontend/src/app/shared/components/footer/footer.component.ts
@@ -0,0 +1,22 @@
+import { ChangeDetectionStrategy, Component } from '@angular/core';
+import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
+import { faMoneyBillTransfer, faCreditCard, faWallet } from '@fortawesome/free-solid-svg-icons';
+import { faPaypal, faGooglePay, faApplePay } from '@fortawesome/free-brands-svg-icons';
+
+@Component({
+ selector: 'app-footer',
+ standalone: true,
+ templateUrl: './footer.component.html',
+ imports: [FontAwesomeModule],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class FooterComponent {
+ currentYear: number = new Date().getFullYear();
+
+ faPaypal = faPaypal;
+ faCreditCard = faCreditCard;
+ faMoneyBillTransfer = faMoneyBillTransfer;
+ faWallet = faWallet;
+ faGooglePay = faGooglePay;
+ faApplePay = faApplePay;
+}
diff --git a/frontend/src/app/shared/components/navbar/navbar.component.html b/frontend/src/app/shared/components/navbar/navbar.component.html
new file mode 100644
index 0000000..6ce24cc
--- /dev/null
+++ b/frontend/src/app/shared/components/navbar/navbar.component.html
@@ -0,0 +1,70 @@
+
diff --git a/frontend/src/app/shared/components/navbar/navbar.component.ts b/frontend/src/app/shared/components/navbar/navbar.component.ts
new file mode 100644
index 0000000..ba86e73
--- /dev/null
+++ b/frontend/src/app/shared/components/navbar/navbar.component.ts
@@ -0,0 +1,34 @@
+import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
+import { RouterModule } from '@angular/router';
+import { KeycloakService } from 'keycloak-angular';
+
+@Component({
+ selector: 'app-navbar',
+ templateUrl: './navbar.component.html',
+ standalone: true,
+ imports: [RouterModule],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class NavbarComponent {
+ isMenuOpen = false;
+ private keycloakService: KeycloakService = inject(KeycloakService);
+
+ isLoggedIn = this.keycloakService.isLoggedIn();
+
+ login() {
+ try {
+ const baseUrl = window.location.origin;
+ this.keycloakService.login({ redirectUri: `${baseUrl}/home` });
+ } catch (error) {
+ console.error('Login failed:', error);
+ }
+ }
+
+ logout() {
+ this.keycloakService.logout();
+ }
+
+ toggleMenu() {
+ this.isMenuOpen = !this.isMenuOpen;
+ }
+}
diff --git a/frontend/src/styles.css b/frontend/src/styles.css
index 12c08a1..d19c673 100644
--- a/frontend/src/styles.css
+++ b/frontend/src/styles.css
@@ -1,19 +1,143 @@
@import 'tailwindcss';
@theme {
- --color-deep-blue: #0f212e;
- --color-deep-blue-light: #1a2c38;
- --color-deep-blue-contrast: #1b2c3b;
- --color-light-blue: #1475e1;
+ --color-deep-blue: #0a1219;
+ --color-deep-blue-light: #121e27;
+ --color-deep-blue-contrast: #1a2835;
+
+ --color-emerald: #10b981;
+ --color-emerald-dark: #059669;
+ --color-emerald-light: #34d399;
+
+ --color-text-primary: #ffffff;
+ --color-text-secondary: #94a3b8;
+ --color-text-tertiary: #64748b;
+
+ --color-accent-yellow: #fbbf24;
+ --color-accent-red: #ef4444;
+ --color-accent-purple: #8b5cf6;
}
body {
- @apply bg-deep-blue text-gray-100;
+ @apply !bg-deep-blue !text-text-primary h-full;
+}
+
+button,
+a {
+ @apply cursor-pointer active:scale-95 !text-text-primary transition-all duration-200;
+}
+
+.card {
+ @apply bg-deep-blue-contrast rounded-lg overflow-hidden shadow-lg hover:shadow-xl transition-shadow duration-300;
+}
+
+.button-base {
+ @apply bg-emerald hover:bg-emerald-dark !text-text-primary transition-all duration-300 active:scale-95 rounded;
+}
+
+.game-card-content {
+ @apply p-4;
+}
+
+.nav-button {
+ @apply hidden lg:block absolute top-1/2 -translate-y-1/2 bg-deep-blue-contrast hover:bg-deep-blue-contrast/90 !text-text-primary p-3 rounded-full opacity-0 group-hover:opacity-100 transition-all duration-300 shadow-lg hover:scale-110;
+}
+
+.slider-container {
+ @apply flex transition-transform duration-500 ease-out;
+}
+
+.slider-grid {
+ @apply min-w-full grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4;
+}
+
+.welcome-bonus {
+ @apply !text-4xl sm:!text-5xl lg:!text-7xl !font-extrabold !text-emerald-light mb-3 sm:mb-4;
+}
+
+.bonus-description {
+ @apply !text-text-secondary !text-base sm:!text-lg mb-6 sm:mb-8;
+}
+
+.section-heading {
+ @apply !font-bold !text-text-primary;
+}
+
+.game-heading {
+ @apply !font-bold !text-text-primary !text-sm mb-2;
+}
+
+.game-text {
+ @apply !text-text-secondary !text-sm mb-4;
+}
+
+.stat-container {
+ @apply bg-deep-blue-contrast rounded-lg shadow-lg p-4 sm:p-6 !text-center;
+}
+
+.stat-number {
+ @apply !text-xl sm:!text-2xl !font-bold !text-emerald;
+}
+
+.stat-text {
+ @apply !text-text-secondary !text-sm;
+}
+
+.nav-brand {
+ @apply flex items-center !text-text-primary !text-xl !font-semibold;
+}
+
+.nav-link {
+ @apply px-3 py-2 rounded-md !font-normal !text-sm !text-text-secondary hover:!text-text-primary hover:bg-deep-blue-contrast transition-all duration-200;
+}
+
+.nav-toggle {
+ @apply !text-text-secondary hover:!text-text-primary transition-colors duration-200;
+}
+
+.nav-mobile-menu {
+ @apply p-2 pt-2 mb-4 space-y-1 bg-deep-blue-contrast rounded-b-lg;
+}
+
+.nav-mobile-link {
+ @apply block px-3 py-2 rounded-md !text-sm !text-text-secondary hover:!text-text-primary hover:bg-deep-blue-light transition-all duration-200;
+}
+
+.footer-section {
+ @apply col-span-2 md:col-span-1;
+}
+
+.footer-heading {
+ @apply !text-text-primary !text-sm !font-semibold mb-4;
+}
+
+.footer-link {
+ @apply !text-text-secondary hover:!text-text-primary !text-sm transition-all duration-200;
+}
+
+.footer-payment-method {
+ @apply bg-deep-blue rounded p-3 flex items-center justify-center space-x-2 hover:bg-deep-blue/50 transition-all duration-200;
+}
+
+.footer-payment-icon {
+ @apply !text-text-secondary !text-lg;
+}
+
+.footer-payment-text {
+ @apply !text-text-secondary !text-xs !whitespace-nowrap;
+}
+
+.footer-copyright {
+ @apply !text-text-secondary !text-sm;
+}
+
+.footer-disclaimer {
+ @apply !text-xs;
}
.mat-mdc-dialog-container {
- --mdc-dialog-container-color: var(--color-deep-blue-light) !important;
- --mdc-dialog-subhead-color: #ffffff !important;
- --mdc-dialog-supporting-text-color: #9ca3af !important;
- --mdc-dialog-container-shape: 6px !important;
+ --mdc-dialog-container-color: var(--color-deep-blue-light) important;
+ --mdc-dialog-subhead-color: var(--color-text-primary) important;
+ --mdc-dialog-supporting-text-color: var(--color-text-secondary) important;
+ --mdc-dialog-container-shape: 6px important;
}