diff --git a/apps/browser/src/tools/popup/achievements/achievements.component.html b/apps/browser/src/tools/popup/achievements/achievements.component.html index 1fe72e4caa5..7a096853173 100644 --- a/apps/browser/src/tools/popup/achievements/achievements.component.html +++ b/apps/browser/src/tools/popup/achievements/achievements.component.html @@ -4,7 +4,7 @@ - + diff --git a/apps/web/src/app/tools/achievements/achievements.component.ts b/apps/web/src/app/tools/achievements/achievements.component.ts index ce2351346ab..bb50057c403 100644 --- a/apps/web/src/app/tools/achievements/achievements.component.ts +++ b/apps/web/src/app/tools/achievements/achievements.component.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core"; import { firstValueFrom } from "rxjs"; import { AchievementNotifierService } from "@bitwarden/angular/tools/achievements/achievement-notifier.abstraction"; +import { AchievementsListComponent } from "@bitwarden/angular/tools/achievements/achievements-list.component"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { EventStoreAbstraction } from "@bitwarden/common/tools/achievements/event-store.abstraction.service"; import { VaultItems_10_Added_Achievement } from "@bitwarden/common/tools/achievements/examples/achievements"; @@ -14,7 +15,7 @@ import { SharedModule } from "../../shared"; @Component({ templateUrl: "achievements.component.html", standalone: true, - imports: [SharedModule, HeaderModule], + imports: [SharedModule, HeaderModule, AchievementsListComponent], }) export class AchievementsComponent implements OnInit { private currentUserId: UserId; diff --git a/libs/angular/src/tools/achievements/achievements-list.component.html b/libs/angular/src/tools/achievements/achievements-list.component.html new file mode 100644 index 00000000000..c504cf27922 --- /dev/null +++ b/libs/angular/src/tools/achievements/achievements-list.component.html @@ -0,0 +1,20 @@ + + +

+ {{ "achievements" | i18n }} +

+ {{ allAchievementCards.length }} +
+ + @for (achievement of allAchievementCards; track achievement.name) { +
+ +
+ } +
diff --git a/libs/angular/src/tools/achievements/achievements-list.component.ts b/libs/angular/src/tools/achievements/achievements-list.component.ts new file mode 100644 index 00000000000..64b9fc38e92 --- /dev/null +++ b/libs/angular/src/tools/achievements/achievements-list.component.ts @@ -0,0 +1,89 @@ +import { CommonModule } from "@angular/common"; +import { Component, OnInit } from "@angular/core"; +import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; +import { firstValueFrom } from "rxjs"; + +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { AchievementService } from "@bitwarden/common/tools/achievements/achievement.service.abstraction"; +import { + LoginItems_1_Added_Achievement, + VaultItems_10_Added_Achievement, + VaultItems_1_Added_Achievement, + VaultItems_50_Added_Achievement, +} from "@bitwarden/common/tools/achievements/examples/achievements"; +import { UserId } from "@bitwarden/common/types/guid"; +import { + ButtonModule, + IconButtonModule, + ItemModule, + SectionComponent, + SectionHeaderComponent, + TypographyModule, +} from "@bitwarden/components"; + +import { AchievementCard } from "./achievement-card.component"; + +@Component({ + selector: "achievements-list", + templateUrl: "achievements-list.component.html", + standalone: true, + imports: [ + CommonModule, + ItemModule, + ButtonModule, + IconButtonModule, + SectionComponent, + TypographyModule, + JslibModule, + SectionHeaderComponent, + AchievementCard, + ], +}) +export class AchievementsListComponent implements OnInit { + private currentUserId: UserId; + + //FIXME Should be retrieved from achievementService or possibly AchievementManager + private allAchievements = [ + VaultItems_1_Added_Achievement, + VaultItems_10_Added_Achievement, + VaultItems_50_Added_Achievement, + LoginItems_1_Added_Achievement, + ]; + + mockAchievements = [ + { ...VaultItems_1_Added_Achievement, earned: false, progress: 0, date: new Date(0) }, + { ...VaultItems_10_Added_Achievement, earned: false, progress: 1, date: new Date(0) }, + { ...VaultItems_50_Added_Achievement, earned: true, progress: 0, date: new Date(0) }, + ]; + //FIXME uses mockedData for AchievmentsList + allAchievementCards = this.mockAchievements; + // allAchievementCards = this.allAchievements.map(achievement => { return { ...achievement, earned: true, progress: 0, date: new Date(0) } }); + + constructor( + private achievementService: AchievementService, + private accountService: AccountService, + ) { + //FIXME AchievementProgressEvent is missing an identifier for a specific achievement + this.achievementService + .achievementsInProgress$(this.currentUserId) + .pipe(takeUntilDestroyed()) + .subscribe((event) => { + this.allAchievementCards.find((a) => a.name === event.achievement.name); + const index = this.allAchievementCards.findIndex((a) => a.name === event.achievement.name); + this.allAchievementCards[index].progress = event.achievement.value; + }); + this.achievementService + .achievementsEarned$(this.currentUserId) + .pipe(takeUntilDestroyed()) + .subscribe((event) => { + const index = this.allAchievementCards.findIndex((a) => a.name === event.achievement.name); + this.allAchievementCards[index].earned = true; + this.allAchievementCards[index].date = new Date(event["@timestamp"]); + }); + } + + async ngOnInit() { + this.currentUserId = (await firstValueFrom(this.accountService.activeAccount$)).id; + } +}