diff --git a/src/components/LenderProfile/LenderBadges.vue b/src/components/LenderProfile/LenderBadges.vue index 7f73727961..5646944d61 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..245389aacc 100644 --- a/src/composables/useBadgeData.js +++ b/src/composables/useBadgeData.js @@ -50,9 +50,10 @@ export default function useBadgeData() { * Calls Apollo to get the badge achievement service data * * @param apollo The current instance of Apollo + * @param publicId Whether to get achievement data for a specific user */ - 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 ?? []), @@ -343,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; @@ -388,6 +389,58 @@ 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; + }; + + /** + * Get completed badges sorted by earned date + * + * @returns Completed badges sorted by earned date + */ + 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 +453,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..d11ccbf87d 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/pages/Portfolio/LendingStats/LendingStatsPage.vue b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue index 92a98f2632..cfa6900d1a 100644 --- a/src/pages/Portfolio/LendingStats/LendingStatsPage.vue +++ b/src/pages/Portfolio/LendingStats/LendingStatsPage.vue @@ -23,7 +23,7 @@



@@ -88,12 +88,13 @@ import _differenceBy from 'lodash/differenceBy'; import _sortBy from 'lodash/sortBy'; import lendingStatsQuery from '#src/graphql/query/myLendingStats.graphql'; -import userAchievementProgressQuery from '#src/graphql/query/userAchievementProgress.graphql'; import WwwPage from '#src/components/WwwFrame/WwwPage'; import TheMyKivaSecondaryMenu from '#src/components/WwwFrame/Menus/TheMyKivaSecondaryMenu'; import ThePortfolioTertiaryMenu from '#src/components/WwwFrame/Menus/ThePortfolioTertiaryMenu'; import KvGrid from '#kv-components/KvGrid'; import KvPageContainer from '#kv-components/KvPageContainer'; +import lenderProfileBadgeDataQuery from '#src/graphql/query/lenderProfileBadgeData.graphql'; +import useBadgeData from '#src/composables/useBadgeData'; import BadgesSection from './BadgesSection'; import StatsSection from './StatsSection'; @@ -124,6 +125,7 @@ export default { partnersNotLentTo: [], userId: null, allAchievements: [], + badgesData: [], }; }, apollo: { @@ -157,19 +159,46 @@ export default { }, created() { this.apollo.query({ - query: userAchievementProgressQuery, + query: lenderProfileBadgeDataQuery, + variables: { + contentType: 'challenge', + limit: 200, + } }).then(({ data }) => { - this.allAchievements = data?.userAchievementProgress?.lendingAchievements ?? []; + this.allAchievements = data ?? {}; }); }, computed: { completedAchievements() { - return this.allAchievements.filter( - achievement => achievement.milestoneProgress?.[0]?.milestoneStatus === 'COMPLETE' - ); + const completedBadgesArr = this.getBadgesData(); + + completedBadgesArr.sort((a, b) => { + return new Date(a.earnedAtDate) - new Date(b.earnedAtDate); + }); + + return completedBadgesArr; }, + badgesLoading() { + return !this.badgesData.length; + } }, methods: { + getBadgesData() { + const { + combineBadgeData, getCompletedBadges, getContentfulLevelData + } = useBadgeData(); + + const badgeAchievementData = [ + ...(this.allAchievements?.userAchievementProgress?.lendingAchievements ?? []), + ...(this.allAchievements?.userAchievementProgress?.tieredLendingAchievements ?? []) + ]; + const badgeContentfulData = (this.allAchievements?.contentful?.entries?.items ?? []) + .map(entry => getContentfulLevelData(entry)); + + this.badgesData = combineBadgeData(badgeAchievementData, badgeContentfulData); + + return getCompletedBadges(this.badgesData); + }, iconForSector(sector) { return `sector-${sector.name.toLowerCase().replace(' ', '-')}`; } diff --git a/test/unit/specs/composables/useBadgeData.spec.js b/test/unit/specs/composables/useBadgeData.spec.js index c22c00ee3a..5bc2114cf5 100644 --- a/test/unit/specs/composables/useBadgeData.spec.js +++ b/test/unit/specs/composables/useBadgeData.spec.js @@ -502,4 +502,75 @@ describe('useBadgeData.js', () => { expect(getHighestPriorityDisplayBadge(badges)).toEqual({ id: ID_CLIMATE_ACTION, level: 3 }); }); }); + + describe('getCompletedBadges', () => { + it('should return the completed badges', () => { + const { getCompletedBadges } = useBadgeData(); + const badges = [ + { + achievementData: { + milestoneProgress: [ + { earnedAtDate: '2024-10-22T18:49:21Z' } + ] + }, + }, + { + achievementData: { + milestoneProgress: [] + }, + }, + { + achievementData: { + milestoneProgress: [ + { earnedAtDate: '2024-10-23T18:49:21Z' } + ] + }, + }, + ]; + + expect(getCompletedBadges(badges)).toEqual([ + { + achievementData: { + milestoneProgress: [ + { earnedAtDate: '2024-10-22T18:49:21Z' } + ] + }, + earnedAtDate: '2024-10-22T18:49:21Z', + level: 0, + }, + { + achievementData: { + milestoneProgress: [ + { earnedAtDate: '2024-10-23T18:49:21Z' } + ] + }, + earnedAtDate: '2024-10-23T18:49:21Z', + level: 0, + } + ]); + }); + 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([]); + }); + }); });