Started profil page

This commit is contained in:
2026-04-14 15:48:36 +01:00
parent 83f68a3029
commit 90243bc671
50 changed files with 849 additions and 1654 deletions
+130 -4
View File
@@ -1,13 +1,16 @@
<ion-header>
<ion-toolbar>
<ion-buttons slot="secondary">
<ion-button fill="solid" style="--background: #f7f6f2;" class="border border-gray-200">
<ion-icon slot="icon-only" name="profile"></ion-icon>
<ion-button fill="solid" style="--background: #F0EFE9;"
class="border border-gray-300 rounded-lg overflow-hidden"
(touchstart)="setOpen(true)">
<ion-icon slot="icon-only" class="text-xl text-gray-500" name="profile"></ion-icon>
</ion-button>
</ion-buttons>
<ion-buttons slot="primary">
<ion-button fill="solid">
<ion-icon slot="icon-only" name="add"></ion-icon>
<ion-button fill="solid" style="--background: #F0EFE9;"
class="border border-gray-300 rounded-lg overflow-hidden">
<ion-icon slot="icon-only" class="text-2xl text-gray-500" name="add"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title class="font-mono">BeReady</ion-title>
@@ -30,3 +33,126 @@
<app-challenge-card [data]="randomChallenge()" action="Participer" tag="Défis" color=""></app-challenge-card>
</div>
</ion-content>
<ion-modal [isOpen]="isModalOpen">
<ng-template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="secondary">
<ion-buttons slot="start" style="--ion-color-primary: #0054E9;">
<ion-back-button default-href="" (touchstart)="setOpen(false)"></ion-back-button>
</ion-buttons>
</ion-buttons>
<ion-buttons slot="primary">
<ion-button fill="solid" style="--background: #FFFFFF;"
class="border border-gray-300 rounded-lg overflow-hidden">
<ion-icon slot="icon-only" class="text-2xl text-gray-500" name="settings"></ion-icon>
</ion-button>
</ion-buttons>
<ion-title>Profil</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding m-1" style="--background: #f7f6f2;">
<div class="rounded-lg px-5 m-3 bg-white border border-gray-200 grid grid-cols-3 items-center">
<div>
<ion-avatar slot="start" class="w-20 h-20 p-2">
<img alt=""
src="https://ionicframework.com/docs/img/demos/avatar.svg"/>
</ion-avatar>
</div>
<div class="col-span-2 py-3">
<ion-label class="text-[15px] font-sans font-bold block">
{{ user()?.firstName }} {{ user()?.name.charAt(0) }}.
</ion-label>
<ion-label class="text-xs font-mono block text-gray-400 mt-0.5">
{{ user()?.username }}
</ion-label>
<ion-label
class="text-[10px] font-sans font-semibold block mt-2 bg-gray-100 text-gray-500 rounded-full px-2 py-0.5 w-fit">
@if (user().designationName) {
⚡ {{ user().designationName }}
} @else {
⚡ En sommeil
}
</ion-label>
</div>
</div>
<div class="grid grid-cols-3 px-1">
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.totalChallenge }}</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Défis réalisés</p>
</div>
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.totalWin }}</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Victoires</p>
</div>
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.totalPodium }}</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Podiums</p>
</div>
</div>
<div class="grid grid-cols-2 px-1">
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.totalBonusChallenge }}</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Défis bonus</p>
</div>
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.series }}×</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Séries max</p>
</div>
</div>
<div class="px-1">
<div class="rounded-lg px-4 py-0.5 m-2 bg-white border border-gray-200">
<p class="text-2xl font-black font-mono mb-0.5">{{ user().getUserStatsDto.score }}</p>
<p class="text-[11px] font-semibold font-mono text-gray-400 mt-0">Score global</p>
</div>
</div>
<div class="mt-4">
<app-title-part textInfo="Succès"></app-title-part>
<div class="rounded-lg px-5 m-3 bg-white border border-gray-200 grid grid-cols-6 items-center">
<p class="col-span-5">Vous n'avez pas encore débloqué de succès</p>
<p class="col-span-1">Test</p>
</div>
</div>
<div class="mt-4">
<app-title-part textInfo="Paramètres de compte"></app-title-part>
<div class="rounded-lg px-5 m-3 bg-white border border-gray-200 items-center">
<ion-list>
@for (n of options; track n) {
@if (n == options.length) {
<ion-item lines="none">
<p class="text-sm text-red-800">Se déconnecter</p>
<ion-icon slot="end" class="text-xl text-red-800" name="logout"></ion-icon>
</ion-item>
} @else {
<ion-item lines="full">
@switch (n) {
@case (1) {
<p class="text-sm text-gray-600">Modifier le pseudo</p>
<ion-icon slot="end" class="text-xl text-gray-400" name="chevron"></ion-icon>
}
@case (2) {
<p class="text-sm text-gray-600">Modifier l'email</p>
<ion-icon slot="end" class="text-xl text-gray-400" name="chevron"></ion-icon>
}
@case (3) {
<p class="text-sm text-gray-600">Modifier le mot de passe</p>
<ion-icon slot="end" class="text-xl text-gray-400" name="chevron"></ion-icon>
}
@case (4) {
<p class="text-sm text-gray-600">Changer de désignation</p>
<ion-icon slot="end" class="text-xl text-gray-400" name="chevron"></ion-icon>
}
}
</ion-item>
}
}
</ion-list>
</div>
</div>
</ion-content>
</ng-template>
</ion-modal>
+29 -26
View File
@@ -1,16 +1,19 @@
import {Component, inject, OnInit, signal} from '@angular/core';
import {IonicModule, ToastController} from "@ionic/angular";
import {addIcons} from "ionicons";
import {walkOutline, addOutline} from "ionicons/icons";
import {personOutline, addOutline, logOutOutline, settingsOutline, chevronForwardOutline, swapHorizontalOutline} from "ionicons/icons";
import {TitlePartComponent} from "../../components/title-part/title-part.component";
import {ChallengeCardComponent} from "../../components/challenge-card/challenge-card.component";
import * as signalR from '@microsoft/signalr';
import {GetRandomChallengeDto, RandomchallengesService} from "../../services/api";
import {GetRandomChallengeDto, GetUserDetailsDto, RandomchallengesService, UsersService} from "../../services/api";
import {firstValueFrom} from "rxjs";
addIcons({
'profile': walkOutline,
'profile': personOutline,
'add': addOutline,
'settings': settingsOutline,
'logout': logOutOutline,
'chevron': chevronForwardOutline,
'swap': swapHorizontalOutline,
});
@Component({
@@ -24,32 +27,15 @@ addIcons({
]
})
export class HomeComponent implements OnInit {
// private connection: signalR.HubConnection;
//
// ngOnInit(): void {
// this.connection = new signalR.HubConnectionBuilder()
// .withUrl('http://localhost:5235/timeHub', {
// withCredentials: true
// })
// .build();
//
// this.connection.on('ReceiveTime', (time) => {
// console.log('Server time:', time);
// });
//
// this.connection.start()
// .then(() => {
// console.log('Connected to SignalR');
// this.connection.invoke('SendTime');
// })
// .catch(err => console.error('Connection error:', err));
// }
private randomChallengeService = inject(RandomchallengesService)
private toastCtrl = inject(ToastController);
private usersService = inject(UsersService)
randomChallenge = signal<GetRandomChallengeDto>({});
user = signal<GetUserDetailsDto>({})
isModalOpen = false;
options = [1, 2, 3, 4, 5];
async ngOnInit() {
try {
@@ -64,4 +50,21 @@ export class HomeComponent implements OnInit {
await toast.present();
}
}
async setOpen(isOpen: boolean) {
if (isOpen) {
try {
const userInfo = await firstValueFrom(this.usersService.getUserDetailsEndpoint());
this.user.set(userInfo);
} catch (e) {
const toast = await this.toastCtrl.create({
message: 'Impossible de charger les données du joueur',
duration: 2000,
color: 'danger'
});
await toast.present();
}
}
this.isModalOpen = isOpen;
}
}