Added achievements in profil page

This commit is contained in:
2026-04-15 12:18:00 +01:00
parent ce5cc5880b
commit d9af61889a
8 changed files with 123 additions and 5 deletions
@@ -0,0 +1,18 @@
<div class="rounded-lg px-2 m-3 bg-white border border-gray-200 items-center h-full max-h-48 overflow-scroll">
<ion-list lines="none" class="flex flex-col gap-3 pt-1 pb-1">
@for (challenge of userChallenges(); track challenge.challengeTitle) {
<ion-item class="border border-gray-200 rounded-xl" style="--inner-padding-end: 0; --padding-start: 0;">
<div class="grid grid-cols-[1fr_auto] gap-2 items-start w-full px-3 py-2">
<div>
<p class="m-0 text-sm font-medium text-gray-900">{{ challenge.challengeTitle }}</p>
<p class="m-0 mt-1 text-xs text-gray-500 leading-relaxed">{{ challenge.challengeDescription }}</p>
</div>
<div class="text-right shrink-0">
<p class="m-0 text-xs text-gray-500">{{ converterHours(challenge.challengeDuration) }}</p>
<p class="m-0 mt-1 text-xs text-gray-400">{{ challenge.challengeStartDate }}</p>
</div>
</div>
</ion-item>
}
</ion-list>
</div>
@@ -0,0 +1,39 @@
import {Component, input} from '@angular/core';
import {IonicModule} from "@ionic/angular";
import {GetUserChallengeDto} from "../../services/api";
@Component({
selector: 'app-challenges-accomplished',
templateUrl: './challenges-accomplished.component.html',
styleUrls: ['./challenges-accomplished.component.scss'],
imports: [
IonicModule
]
})
export class ChallengesAccomplishedComponent {
userChallenges = input.required<GetUserChallengeDto[]>();
converterHours(hours: number) {
const day = Math.floor(hours / 24);
const week = Math.floor(day / 7);
const month = Math.floor(week / 4);
const year = Math.floor(month / 12);
switch (true) {
case year > 0:
return `${year} an${year > 1 ? 's' : ''}`;
case month > 0:
return `${month} mois`;
case week > 0:
return `${week} semaine${week > 1 ? 's' : ''}`;
case day > 0:
return `${day} jour${day > 1 ? 's' : ''}`;
default:
return `${hours} heure${hours > 1 ? 's' : ''}`;
}
}
}
@@ -0,0 +1,31 @@
<div class="rounded-lg m-3 bg-white border border-gray-200 items-center h-full max-h-48 overflow-scroll">
@if (achievements().length > 0) {
@for (achievement of achievements(); track achievement.id) {
<ion-item lines="none" class="border border-gray-300 rounded-xl m-2"
style="--inner-padding-end: 0; --padding-start: 0; --background: #F0FAF3;">
<div class="flex items-center gap-4 px-3 py-1">
<div class="flex items-center justify-center">
<ion-icon class="text-[18px] text-green-700" name="check"></ion-icon>
</div>
<div>
<p class="m-0 text-sm font-medium" style="color:#2d4a35;">{{ achievement.label }}</p>
<p class="m-0 mt-1 text-xs leading-relaxed"
style="color:#5a7a62;">{{ achievement.description }}</p>
</div>
</div>
</ion-item>
}
} @else {
<ion-item lines="none" class="border border-stone-200 rounded-xl m-3" style="--background: #fafaf8;">
<div class="flex flex-col items-center w-full px-5 py-8 gap-3">
<div class="w-10 h-10 rounded-full bg-stone-100 border border-stone-200 flex items-center justify-center">
<ion-icon name="trophy" style="color:#a8a090; font-size:20px;"></ion-icon>
</div>
<div class="text-center">
<p class="m-0 text-sm font-medium text-stone-400">Pas encore de succès</p>
<p class="m-0 mt-1 text-xs text-stone-300 leading-relaxed">Vos premiers succès apparaîtront ici</p>
</div>
</div>
</ion-item>
}
</div>
@@ -0,0 +1,22 @@
import {Component, input} from '@angular/core';
import {IonicModule} from "@ionic/angular";
import {checkmarkCircleOutline, trophyOutline} from "ionicons/icons";
import {addIcons} from "ionicons";
import {GetAchievementDto} from "../../services/api";
addIcons({
'check': checkmarkCircleOutline,
'trophy': trophyOutline
});
@Component({
selector: 'app-user-achievements',
templateUrl: './user-achievements.component.html',
styleUrls: ['./user-achievements.component.scss'],
imports: [
IonicModule
]
})
export class UserAchievementsComponent {
achievements = input.required<GetAchievementDto[]>();
}
+3 -4
View File
@@ -50,13 +50,12 @@
<app-title-part textInfo="Mes participations"></app-title-part> <app-title-part textInfo="Mes participations"></app-title-part>
<app-challenges-accomplished [userChallenges]="userChallenge()"></app-challenges-accomplished> <app-challenges-accomplished [userChallenges]="userChallenge()"></app-challenges-accomplished>
</div> </div>
<div class="mt-4"> <div class="mt-4">
<app-title-part textInfo="Succès"></app-title-part> <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"> <app-user-achievements [achievements]="userAchievement()"></app-user-achievements>
<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>
<div class="mt-4"> <div class="mt-4">
<app-title-part textInfo="Paramètres de compte"></app-title-part> <app-title-part textInfo="Paramètres de compte"></app-title-part>
<app-settings-options></app-settings-options> <app-settings-options></app-settings-options>
+10 -1
View File
@@ -5,6 +5,8 @@ import {personOutline, addOutline, settingsOutline} from "ionicons/icons";
import {TitlePartComponent} from "../../components/title-part/title-part.component"; import {TitlePartComponent} from "../../components/title-part/title-part.component";
import {ChallengeCardComponent} from "../../components/challenge-card/challenge-card.component"; import {ChallengeCardComponent} from "../../components/challenge-card/challenge-card.component";
import { import {
AchievementsService,
GetAchievementDto,
GetRandomChallengeDto, GetRandomChallengeDto,
GetUserChallengeDto, GetUserChallengeDto,
GetUserDetailsDto, GetUserDetailsDto,
@@ -17,6 +19,7 @@ import {GenericUserInfoComponent} from "../../components/generic-user-info/gener
import { import {
ChallengesAccomplishedComponent ChallengesAccomplishedComponent
} from "../../components/challenges-accomplished/challenges-accomplished.component"; } from "../../components/challenges-accomplished/challenges-accomplished.component";
import {UserAchievementsComponent} from "../../components/user-achievements/user-achievements.component";
addIcons({ addIcons({
'profile': personOutline, 'profile': personOutline,
@@ -34,7 +37,8 @@ addIcons({
ChallengeCardComponent, ChallengeCardComponent,
SettingsOptionsComponent, SettingsOptionsComponent,
GenericUserInfoComponent, GenericUserInfoComponent,
ChallengesAccomplishedComponent ChallengesAccomplishedComponent,
UserAchievementsComponent
] ]
}) })
export class HomeComponent implements OnInit { export class HomeComponent implements OnInit {
@@ -42,10 +46,12 @@ export class HomeComponent implements OnInit {
private toastCtrl = inject(ToastController); private toastCtrl = inject(ToastController);
private usersService = inject(UsersService); private usersService = inject(UsersService);
private loadCtrl = inject(LoadingController); private loadCtrl = inject(LoadingController);
private achievementsService = inject(AchievementsService);
randomChallenge = signal<GetRandomChallengeDto>({}); randomChallenge = signal<GetRandomChallengeDto>({});
user = signal<GetUserDetailsDto>({}) user = signal<GetUserDetailsDto>({})
userChallenge = signal<GetUserChallengeDto[]>([]); userChallenge = signal<GetUserChallengeDto[]>([]);
userAchievement = signal<GetAchievementDto[]>([])
isModalOpen = false; isModalOpen = false;
@@ -73,8 +79,11 @@ export class HomeComponent implements OnInit {
try { try {
const userInfo = await firstValueFrom(this.usersService.getUserDetailsEndpoint()); const userInfo = await firstValueFrom(this.usersService.getUserDetailsEndpoint());
const userChallenge = await firstValueFrom(this.usersService.getAllUserChallengesEndpoint()); const userChallenge = await firstValueFrom(this.usersService.getAllUserChallengesEndpoint());
const userAchievement = await firstValueFrom((this.achievementsService.getUserAchievementsEndpoint()));
this.user.set(userInfo); this.user.set(userInfo);
this.userChallenge.set(userChallenge); this.userChallenge.set(userChallenge);
this.userAchievement.set(userAchievement);
} catch { } catch {
const toast = await this.toastCtrl.create({ const toast = await this.toastCtrl.create({
message: 'Impossible de charger les données du joueur', message: 'Impossible de charger les données du joueur',