From 2c29b716dbc179ef2cf641e4aaf60dc933acad9a Mon Sep 17 00:00:00 2001
From: Christian Bedon
Date: Thu, 21 Nov 2024 19:33:37 -0500
Subject: [PATCH 1/7] feat: add tiered badges to BadgesList component
---
src/components/LenderProfile/LenderBadges.vue | 104 +++++-------------
src/composables/useBadgeData.js | 53 ++++++++-
.../query/userAchievementProgress.graphql | 4 +-
.../Portfolio/LendingStats/BadgesList.vue | 85 +++++---------
.../LendingStats/LendingStatsPage.vue | 40 +++++--
.../specs/composables/useBadgeData.spec.js | 48 ++++++++
6 files changed, 192 insertions(+), 142 deletions(-)
diff --git a/src/components/LenderProfile/LenderBadges.vue b/src/components/LenderProfile/LenderBadges.vue
index 7f73727961..4ecdb0b254 100644
--- a/src/components/LenderProfile/LenderBadges.vue
+++ b/src/components/LenderProfile/LenderBadges.vue
@@ -1,6 +1,6 @@
-
-
diff --git a/src/composables/useBadgeData.js b/src/composables/useBadgeData.js
index 7f93611da4..a44ff87640 100644
--- a/src/composables/useBadgeData.js
+++ b/src/composables/useBadgeData.js
@@ -51,8 +51,8 @@ export default function useBadgeData() {
*
* @param apollo The current instance of Apollo
*/
- const fetchAchievementData = apollo => {
- apollo.query({ query: userAchievementProgressQuery })
+ const fetchAchievementData = (apollo, publicId = null) => {
+ apollo.query({ query: userAchievementProgressQuery, variables: { publicId } })
.then(result => {
badgeAchievementData.value = [
...(result.data?.userAchievementProgress?.lendingAchievements ?? []),
@@ -388,6 +388,53 @@ export default function useBadgeData() {
return displayedBadge ?? {};
};
+ /**
+ * Get completed badges of a user
+ *
+ * @param badges The badges to get the completed badges from
+ * @returns Completed badges
+ */
+ const getCompletedBadges = badges => {
+ const completedBadgesArr = [];
+
+ badges?.forEach(badge => {
+ if (badge.achievementData?.tiers?.length) {
+ const { tiers } = badge.achievementData;
+ tiers.forEach(tier => {
+ if (tier.completedDate) {
+ completedBadgesArr.push({
+ ...badge,
+ earnedAtDate: tier.completedDate,
+ level: tier.level,
+ });
+ }
+ });
+ }
+ if (badge?.achievementData?.milestoneProgress?.length) {
+ const earnedAtDate = badge.achievementData?.milestoneProgress?.[0]?.earnedAtDate;
+ if (earnedAtDate) {
+ completedBadgesArr.push({
+ ...badge,
+ earnedAtDate,
+ level: 0,
+ });
+ }
+ }
+ });
+
+ return completedBadgesArr;
+ };
+
+ const completedBadges = computed(() => {
+ const completedBadgesArr = getCompletedBadges(badgeData.value);
+
+ completedBadgesArr.sort((a, b) => {
+ return new Date(a.earnedAtDate) - new Date(b.earnedAtDate);
+ });
+
+ return completedBadgesArr;
+ });
+
return {
fetchAchievementData,
fetchContentfulData,
@@ -400,9 +447,11 @@ export default function useBadgeData() {
getBadgeWithVisibleTiers,
getLastCompletedBadgeLevelData,
getHighestPriorityDisplayBadge,
+ getCompletedBadges,
badgeAchievementData,
badgeData,
badgeLoanIdData,
isBadgeKeyValid,
+ completedBadges,
};
}
diff --git a/src/graphql/query/userAchievementProgress.graphql b/src/graphql/query/userAchievementProgress.graphql
index 319de66b97..7450817ca1 100644
--- a/src/graphql/query/userAchievementProgress.graphql
+++ b/src/graphql/query/userAchievementProgress.graphql
@@ -1,5 +1,5 @@
-query UserAchievementProgress {
- userAchievementProgress {
+query UserAchievementProgress($publicId: String) {
+ userAchievementProgress(publicId: $publicId) {
id
lendingAchievements {
id
diff --git a/src/pages/Portfolio/LendingStats/BadgesList.vue b/src/pages/Portfolio/LendingStats/BadgesList.vue
index 8ae5a04a3b..812751c0c6 100644
--- a/src/pages/Portfolio/LendingStats/BadgesList.vue
+++ b/src/pages/Portfolio/LendingStats/BadgesList.vue
@@ -22,16 +22,21 @@
-
+
-
{{ challenge.challengeName }}
-
- {{ challenge.dateTagline }}
+
+ {{ getBadgeTitle(badge) }}
+
+
+ {{ getBadgeDate(badge) }}
@@ -39,9 +44,8 @@
diff --git a/src/composables/useBadgeData.js b/src/composables/useBadgeData.js
index 3f6f4bc741..11bc34ba5f 100644
--- a/src/composables/useBadgeData.js
+++ b/src/composables/useBadgeData.js
@@ -344,7 +344,7 @@ export default function useBadgeData() {
levelName: contentfulData.challengeName,
};
}
- } else if (badge.achievementData?.tiers?.length) {
+ } else if (badge?.achievementData?.tiers?.length) {
const tiers = JSON.parse(JSON.stringify(badge.achievementData.tiers));
tiers.sort((a, b) => new Date(a.completedDate) - new Date(b.completedDate));
const levelIndex = tiers[0].level - 1;
@@ -426,6 +426,11 @@ export default function useBadgeData() {
return completedBadgesArr;
};
+ /**
+ * Get completed badges sorted by earned date
+ *
+ * @returns Completed badges sorted by earned date
+ */
const completedBadges = computed(() => {
const completedBadgesArr = getCompletedBadges(badgeData.value);
diff --git a/src/pages/Portfolio/LendingStats/BadgesList.vue b/src/pages/Portfolio/LendingStats/BadgesList.vue
index 812751c0c6..d11ccbf87d 100644
--- a/src/pages/Portfolio/LendingStats/BadgesList.vue
+++ b/src/pages/Portfolio/LendingStats/BadgesList.vue
@@ -58,10 +58,6 @@ export default {
type: Array,
default: () => ([])
},
- totalPossibleBadges: {
- type: Number,
- default: 0
- },
isLoading: {
type: Boolean,
default: false
@@ -87,7 +83,6 @@ export default {
const badgeData = badge?.contentfulData?.find(data => data.level === badge.level);
return badgeData?.imageUrl ?? '';
},
-
getBadgeDate(badge) {
const earnedAtDate = badge.earnedAtDate ? Date.parse(badge.earnedAtDate) : new Date();
return format(earnedAtDate, 'MMM yyyy');
diff --git a/src/pages/Portfolio/LendingStats/LendingStatsPage.vue b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
index 6d4cf01c3a..8aee83472a 100644
--- a/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
+++ b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
@@ -23,7 +23,7 @@
@@ -178,6 +178,11 @@ export default {
return completedBadgesArr;
},
+ totalPossibleBadges() {
+ return this.badgesData.reduce((acc, badge) => {
+ return acc + (badge?.contentfulData?.length ?? 0);
+ }, 0);
+ }
},
methods: {
getBadgesData() {
diff --git a/test/unit/specs/composables/useBadgeData.spec.js b/test/unit/specs/composables/useBadgeData.spec.js
index 185404c50e..5bc2114cf5 100644
--- a/test/unit/specs/composables/useBadgeData.spec.js
+++ b/test/unit/specs/composables/useBadgeData.spec.js
@@ -549,5 +549,28 @@ describe('useBadgeData.js', () => {
}
]);
});
+ it('should return empty array when not badges', () => {
+ const { getCompletedBadges } = useBadgeData();
+ expect(getCompletedBadges(null)).toEqual([]);
+ });
+ it('should return empty array when badges are not well formatted', () => {
+ const { getCompletedBadges } = useBadgeData();
+ expect(getCompletedBadges([
+ {
+ achievementData: {
+ milestoneProgress: [
+ { earnedAtDate: null }
+ ]
+ },
+ },
+ {
+ achievementData: {
+ milestoneProgress: [
+ { earnedAtDate: undefined }
+ ]
+ },
+ }
+ ])).toEqual([]);
+ });
});
});
From 36e8e0f98261dc193529d2338b2a6f818e8efa03 Mon Sep 17 00:00:00 2001
From: Christian Bedon
Date: Mon, 25 Nov 2024 14:23:04 -0500
Subject: [PATCH 4/7] feat: remove totalPossibleBadges from start of badges
section
---
src/pages/Portfolio/LendingStats/BadgesSection.vue | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/pages/Portfolio/LendingStats/BadgesSection.vue b/src/pages/Portfolio/LendingStats/BadgesSection.vue
index b04df51c3b..449143a99b 100644
--- a/src/pages/Portfolio/LendingStats/BadgesSection.vue
+++ b/src/pages/Portfolio/LendingStats/BadgesSection.vue
@@ -6,7 +6,7 @@
v-if="!isLoading"
class="tw-text-base tw-bg-brand tw-text-white tw-py-0.5 tw-px-1 tw-self-center"
>
- {{ badgesObtained }}/{{ totalPossibleBadges }}
+ {{ badgesObtained }}
Date: Mon, 25 Nov 2024 15:04:00 -0500
Subject: [PATCH 5/7] fix: missing optional chaining
---
src/composables/useBadgeData.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/composables/useBadgeData.js b/src/composables/useBadgeData.js
index 11bc34ba5f..245389aacc 100644
--- a/src/composables/useBadgeData.js
+++ b/src/composables/useBadgeData.js
@@ -399,7 +399,7 @@ export default function useBadgeData() {
const completedBadgesArr = [];
badges?.forEach(badge => {
- if (badge.achievementData?.tiers?.length) {
+ if (badge?.achievementData?.tiers?.length) {
const { tiers } = badge.achievementData;
tiers.forEach(tier => {
if (tier.completedDate) {
From cbced40904352da30bdf678776e5019879440c9d Mon Sep 17 00:00:00 2001
From: Christian Bedon
Date: Mon, 25 Nov 2024 15:51:40 -0500
Subject: [PATCH 6/7] fix: remove totalPossibleBadges prop
---
src/pages/Portfolio/LendingStats/BadgesSection.vue | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/pages/Portfolio/LendingStats/BadgesSection.vue b/src/pages/Portfolio/LendingStats/BadgesSection.vue
index 449143a99b..67745f107c 100644
--- a/src/pages/Portfolio/LendingStats/BadgesSection.vue
+++ b/src/pages/Portfolio/LendingStats/BadgesSection.vue
@@ -16,7 +16,6 @@
From e2414fbb8f4e9e33efdf486f583e47d9215b012a Mon Sep 17 00:00:00 2001
From: Christian Bedon
Date: Mon, 25 Nov 2024 16:44:41 -0500
Subject: [PATCH 7/7] fix: badges loading indicator
---
src/pages/Portfolio/LendingStats/BadgesSection.vue | 10 +++-------
src/pages/Portfolio/LendingStats/LendingStatsPage.vue | 8 +++-----
2 files changed, 6 insertions(+), 12 deletions(-)
diff --git a/src/pages/Portfolio/LendingStats/BadgesSection.vue b/src/pages/Portfolio/LendingStats/BadgesSection.vue
index 67745f107c..15256aa850 100644
--- a/src/pages/Portfolio/LendingStats/BadgesSection.vue
+++ b/src/pages/Portfolio/LendingStats/BadgesSection.vue
@@ -38,10 +38,9 @@ export default {
type: Array,
default: () => []
},
- /* total number of possible badges */
- totalPossibleBadges: {
- type: Number,
- default: 0
+ isLoading: {
+ type: Boolean,
+ default: false
},
},
components: {
@@ -52,9 +51,6 @@ export default {
badgesObtained() {
return this.completedAchievements.length ?? 0;
},
- isLoading() {
- return this.totalPossibleBadges === 0;
- },
},
};
diff --git a/src/pages/Portfolio/LendingStats/LendingStatsPage.vue b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
index 8aee83472a..cfa6900d1a 100644
--- a/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
+++ b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue
@@ -23,7 +23,7 @@
@@ -178,10 +178,8 @@ export default {
return completedBadgesArr;
},
- totalPossibleBadges() {
- return this.badgesData.reduce((acc, badge) => {
- return acc + (badge?.contentfulData?.length ?? 0);
- }, 0);
+ badgesLoading() {
+ return !this.badgesData.length;
}
},
methods: {