1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-26 17:43:22 +00:00

add progress tracking to achievement list

This commit is contained in:
✨ Audrey ✨
2025-03-21 01:01:13 -04:00
parent 6a8b7ae87e
commit 92731b54d0
12 changed files with 55 additions and 15 deletions

View File

@@ -7,4 +7,7 @@
@if (earned()) {
<h3 bitTypography="body2" class="tw-text-center">{{ date() }}</h3>
}
@if (goal() > 0) {
<h3 bitTypography="body2" class="tw-text-center">Progress: {{ progress() }} of {{ goal() }}</h3>
}
</bit-card>

View File

@@ -25,6 +25,7 @@ export class AchievementCard {
earned = input<boolean>(false);
progress = input<number>(0);
goal = input<number>(-1);
date = input<Date>();
protected cardClass: string;

View File

@@ -7,6 +7,8 @@
<span slot="secondary">{{ description() }}</span>
@if (earned()) {
<p slot="secondary">Earned: {{ date() | date: "medium" }}</p>
} @else if (goal() > 0) {
<p slot="secondary">Progress: {{ progress() }} of {{ goal() }}</p>
} @else if (progress() > 0) {
<p slot="secondary">Progress: {{ progress() }}</p>
}

View File

@@ -26,6 +26,7 @@ export class AchievementItem {
earned = input<boolean>(false);
progress = input<number>(0);
goal = input<number>(-1);
date = input<Date>();
protected bgColorClass: string = "";

View File

@@ -15,6 +15,7 @@
[earned]="isEarned(achievement)"
[date]="earnedDate(achievement)"
[progress]="progress(achievement)"
[goal]="goal(achievement)"
></achievement-item>
}
</bit-item-group>

View File

@@ -45,6 +45,7 @@ import { iconMap } from "./icons/icon-map";
})
export class AchievementsListComponent {
protected achievements: Array<Achievement>;
private _active: Set<AchievementId> = new Set();
private _earned: Map<AchievementId, AchievementEarnedEvent> = new Map();
private _progress: Map<MetricId, AchievementProgressEvent> = new Map();
@@ -55,21 +56,30 @@ export class AchievementsListComponent {
) {
this.achievements = Array.from(achievementService.achievementMap().values());
this.accountService.activeAccount$
const account$ = this.accountService.activeAccount$.pipe(
filter((account): account is Account => !!account),
);
account$
.pipe(
filter((account): account is Account => !!account),
switchMap((account) => this.achievementService.earnedMap$(account)),
takeUntilDestroyed(),
)
.subscribe((earned) => zone.run(() => (this._earned = earned)));
this.accountService.activeAccount$
account$
.pipe(
filter((account): account is Account => !!account),
switchMap((account) => this.achievementService.metricsMap$(account)),
takeUntilDestroyed(),
)
.subscribe((progress) => zone.run(() => (this._progress = progress)));
account$
.pipe(
switchMap((account) => this.achievementService.active$(account)),
takeUntilDestroyed(),
)
.subscribe((active) => zone.run(() => (this._active = active)));
}
protected isEarned(achievement: Achievement) {
@@ -81,13 +91,21 @@ export class AchievementsListComponent {
}
protected progress(achievement: Achievement) {
if (achievement.active === "until-earned") {
if (achievement.active === "until-earned" || this._earned.has(achievement.achievement)) {
return -1;
}
return this._progress.get(achievement.active.metric)?.achievement?.value ?? -1;
}
protected goal(achievement: Achievement) {
if (achievement.active === "until-earned" || !this._active.has(achievement.achievement)) {
return -1;
}
return this._progress.get(achievement.active.metric)?.achievement?.goal ?? -1;
}
protected icon(achievement: Achievement): Icon {
return (iconMap[achievement.achievement] as Icon) ?? AchievementIcon;
}