Sostituito frontend angular new con frontend angular. Sostituito frontend angular con frontend angular old

This commit is contained in:
Lorenzo Sanesi
2026-08-10 13:10:18 +02:00
parent 3d4eac4ea5
commit 0ed70eaa18
54 changed files with 7685 additions and 12730 deletions
@@ -1,156 +0,0 @@
<div class="min-h-screen pb-32">
<header class="sticky top-0 z-50 bg-background/80 backdrop-blur-md flex justify-between items-center px-6 py-4">
<div class="flex items-center gap-4">
<button class="w-10 h-10 rounded-full flex items-center justify-center hover:bg-surface-container transition-colors" [routerLink]="['/']">
<mat-icon>arrow_back</mat-icon>
</button>
<h1 class="font-headline font-black tracking-tight text-xl text-primary">The Arena</h1>
</div>
<div class="flex items-center gap-3">
<button (click)="editChallenge()" class="w-10 h-10 rounded-full flex items-center justify-center hover:bg-surface-container transition-colors text-primary">
<mat-icon>edit</mat-icon>
</button>
<mat-icon class="text-on-surface-variant cursor-pointer">search</mat-icon>
<div class="w-8 h-8 rounded-full bg-primary-container overflow-hidden">
<img src="https://picsum.photos/seed/user/100/100" class="w-full h-full object-cover" alt="User Avatar">
</div>
</div>
</header>
<main class="max-w-xl mx-auto px-6 pt-8 space-y-8">
@if (isLoading()) {
<div class="flex flex-col items-center justify-center py-20">
<div class="w-12 h-12 border-4 border-primary border-t-transparent rounded-full animate-spin"></div>
<p class="mt-4 text-on-surface-variant font-medium">Loading arena details...</p>
</div>
} @else if (bet(); as data) {
<!-- Hero Section -->
<section class="space-y-4">
<div class="flex justify-between items-start">
<div class="space-y-1">
<span class="inline-flex items-center px-3 py-1 rounded-full bg-secondary-container text-secondary text-xs font-semibold tracking-wide uppercase">
{{ data.status }}
</span>
<h2 class="text-3xl font-headline font-extrabold">{{ data.title }}</h2>
</div>
<div class="bg-surface-container p-3 rounded-2xl flex flex-col items-center">
<span class="text-[10px] font-bold text-on-surface-variant uppercase tracking-widest">Stake</span>
<span class="text-xl font-headline font-black text-primary">€{{ data.stake }}</span>
</div>
</div>
<p class="text-on-surface-variant text-lg">{{ data.description || 'No description provided.' }}</p>
</section>
<!-- Stats -->
<div class="grid grid-cols-2 gap-4">
<div class="bg-surface-container-low p-6 rounded-2xl flex flex-col gap-1 border border-black/5">
<span class="text-xs font-medium text-on-surface-variant">Start Date</span>
<span class="text-sm font-headline font-bold">{{ data.startDate | date:'mediumDate' }}</span>
</div>
<div class="bg-surface-container-low p-6 rounded-2xl flex flex-col gap-1 border border-black/5">
<span class="text-xs font-medium text-on-surface-variant">Visibility</span>
<span class="text-sm font-headline font-bold">{{ data.isPublic ? 'Public' : 'Private' }}</span>
</div>
</div>
<!-- Participants -->
<section class="space-y-4">
<div class="flex items-center justify-between">
<h3 class="font-headline font-bold">Participants</h3>
<span class="text-sm font-medium text-primary">{{ data.participants.length }} Joined</span>
</div>
<div class="flex flex-wrap gap-3">
@for (p of data.participants; track $index) {
<div class="flex flex-col items-center gap-1">
<div class="relative">
@if ($any(p.user)?.avatarUrl) {
<img [src]="$any(p.user).avatarUrl" class="h-12 w-12 rounded-full ring-2 ring-primary/20 object-cover" [alt]="$any(p.user).name">
} @else {
<div class="h-12 w-12 rounded-full ring-2 ring-primary/20 bg-primary-container/20 flex items-center justify-center">
<mat-icon class="text-primary">person</mat-icon>
</div>
}
@if (p.role === 'OBSERVER') {
<div class="absolute -bottom-1 -right-1 bg-surface-container rounded-full p-0.5 shadow-sm">
<mat-icon class="text-[10px] text-on-surface-variant">visibility</mat-icon>
</div>
}
</div>
<span class="text-[10px] font-medium text-on-surface-variant">{{ $any(p.user)?.name || 'Utente' }}</span>
</div>
}
</div>
</section>
} @else {
<div class="flex flex-col items-center justify-center py-20 text-center">
<mat-icon class="text-6xl text-on-surface-variant/20 mb-4">search_off</mat-icon>
<h3 class="text-xl font-headline font-bold">Challenge Not Found</h3>
<p class="text-on-surface-variant mt-2">The challenge you're looking for doesn't exist or has been removed.</p>
<button class="mt-6 text-primary font-bold" [routerLink]="['/']">Go Back Home</button>
</div>
}
<!-- Live Standings -->
<section class="bg-surface-container p-6 rounded-2xl space-y-6 border border-black/5">
<div class="flex items-center justify-between">
<h3 class="font-headline font-bold">Live Standings</h3>
<mat-icon class="text-primary">leaderboard</mat-icon>
</div>
<div class="space-y-5">
<div class="space-y-2">
<div class="flex justify-between items-end">
<span class="text-sm font-bold">You (Alex)</span>
<span class="text-xs font-medium text-on-surface-variant">16,402 / 20,000</span>
</div>
<div class="h-3 w-full bg-surface-container-highest rounded-full overflow-hidden">
<div class="h-full bg-gradient-to-r from-primary to-primary-container rounded-full" style="width: 82%"></div>
</div>
</div>
<div class="space-y-2">
<div class="flex justify-between items-end">
<span class="text-sm font-medium">Sarah J.</span>
<span class="text-xs font-medium text-on-surface-variant">18,210 / 20,000</span>
</div>
<div class="h-3 w-full bg-surface-container-highest rounded-full overflow-hidden">
<div class="h-full bg-tertiary rounded-full" style="width: 91%"></div>
</div>
</div>
</div>
</section>
<!-- Stats Bento -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-surface-container-low p-6 rounded-2xl flex items-center gap-4 border border-black/5">
<div class="w-12 h-12 rounded-full bg-tertiary-container/20 flex items-center justify-center">
<mat-icon class="text-tertiary">local_fire_department</mat-icon>
</div>
<div>
<p class="text-xs font-medium text-on-surface-variant">Hot Streak</p>
<p class="text-lg font-headline font-bold">3 Wins</p>
</div>
</div>
<div class="bg-surface-container-low p-6 rounded-2xl flex items-center gap-4 border border-black/5">
<div class="w-12 h-12 rounded-full bg-secondary-container/20 flex items-center justify-center">
<mat-icon class="text-secondary">groups</mat-icon>
</div>
<div>
<p class="text-xs font-medium text-on-surface-variant">Activity Level</p>
<p class="text-lg font-headline font-bold">High</p>
</div>
</div>
</div>
</main>
<!-- Action Buttons -->
<div class="fixed bottom-0 left-0 w-full p-6 bg-background/80 backdrop-blur-xl z-40 border-t border-black/5">
<div class="max-w-xl mx-auto flex flex-col gap-3">
<button class="w-full py-4 bg-gradient-to-r from-primary to-primary-container text-white font-headline font-bold rounded-full shadow-lg active:scale-95 transition-transform">
Update Progress
</button>
<button class="w-full py-4 bg-surface-container-highest text-on-surface font-headline font-bold rounded-full active:scale-95 transition-transform flex items-center justify-center gap-2">
<mat-icon>person_add</mat-icon>
Invite Friends
</button>
</div>
</div>
</div>
@@ -1,48 +0,0 @@
import {ChangeDetectionStrategy, Component, inject, signal, OnInit} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MatIconModule} from '@angular/material/icon';
import {RouterModule, Router, ActivatedRoute} from '@angular/router';
import {BetService} from '../../services/bet';
import {Bet} from '../../models/data.models';
@Component({
selector: 'app-challenge-detail',
standalone: true,
imports: [CommonModule, MatIconModule, RouterModule],
templateUrl: './challenge-detail.html',
styleUrl: './challenge-detail.css',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ChallengeDetail implements OnInit {
private router = inject(Router);
private route = inject(ActivatedRoute);
private betService = inject(BetService);
challengeId = this.route.snapshot.paramMap.get('id');
bet = signal<Bet | null>(null);
isLoading = signal(true);
ngOnInit() {
if (this.challengeId) {
this.betService.getBetById(this.challengeId).subscribe({
next: (data) => {
this.bet.set(data);
this.isLoading.set(false);
},
error: (err) => {
console.error('Error loading bet:', err);
this.isLoading.set(false);
}
});
}
}
editChallenge() {
const data = this.bet();
if (data) {
this.router.navigate(['/create-bet'], {
state: { bet: data }
});
}
}
}
@@ -1,4 +0,0 @@
import { InjectionToken } from '@angular/core';
import Keycloak from 'keycloak-js';
export const KEYCLOAK_INSTANCE = new InjectionToken<Keycloak>('KeycloakInstance');
@@ -1,18 +0,0 @@
export interface SuccessResponse<T = any> {
success: boolean;
message?: string;
data: T;
timestamp: string;
}
export interface ErrorDetail {
field?: string;
message: string;
}
export interface ErrorResponse {
success: boolean;
message: string;
errors?: ErrorDetail[];
timestamp: string;
}
@@ -1,7 +0,0 @@
export const environment = {
production: true,
apiUrl: '', // da compilare in produzione
keycloakUrl: '',
keycloakRealm: 'scommettiapp',
keycloakClientId: 'scommetti-frontend',
};