• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kiva / ui / 18732492604

22 Oct 2025 11:15PM UTC coverage: 49.681% (-0.5%) from 50.172%
18732492604

Pull #6281

github

web-flow
Merge d6ecbc16f into 1cc04a665
Pull Request #6281: feat: mp-2014 / Display Thank You Page and Prompt for New Achievement After Goal Completion

1815 of 3902 branches covered (46.51%)

Branch coverage included in aggregate %.

0 of 51 new or added lines in 1 file covered. (0.0%)

2699 of 5184 relevant lines covered (52.06%)

259.84 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/composables/useGoalData.js
1
import {
2
        computed,
3
        inject,
4
        ref,
5
} from 'vue';
6

7
import useGoalDataQuery from '#src/graphql/query/useGoalData.graphql';
8
import useGoalDataProgressQuery from '#src/graphql/query/useGoalDataProgress.graphql';
9
import logFormatter from '#src/util/logFormatter';
10
import { createUserPreferences, updateUserPreferences } from '#src/util/userPreferenceUtils';
11

12
import {
13
        ID_BASIC_NEEDS,
14
        ID_CLIMATE_ACTION,
15
        ID_REFUGEE_EQUALITY,
16
        ID_SUPPORT_ALL,
17
        ID_US_ECONOMIC_EQUALITY,
18
        ID_WOMENS_EQUALITY,
19
} from '#src/composables/useBadgeData';
20

NEW
21
const GOAL_DISPLAY_MAP = {
×
22
        [ID_BASIC_NEEDS]: 'basic needs loans',
23
        [ID_CLIMATE_ACTION]: 'eco-friendly loans',
24
        [ID_REFUGEE_EQUALITY]: 'refugees',
25
        [ID_SUPPORT_ALL]: 'loans',
26
        [ID_US_ECONOMIC_EQUALITY]: 'U.S. entrepreneurs',
27
        [ID_WOMENS_EQUALITY]: 'women',
28
};
29

30
function getGoalDisplayName(category) {
NEW
31
        return GOAL_DISPLAY_MAP[category] || 'loans';
×
32
}
33

34
/**
35
 * Vue composable for loading and managing user goal data
36
 *
37
 * @param {Array} loans - List of loans to count toward goals
38
 * @returns Goal data and utilities
39
 */
40
export default function useGoalData({ loans }) {
NEW
41
        const apollo = inject('apollo');
×
42

NEW
43
        const allTimeProgress = ref([]);
×
NEW
44
        const loading = ref(true);
×
NEW
45
        const totalLoanCount = ref(null);
×
NEW
46
        const userGoal = ref(null);
×
NEW
47
        const userPreferences = ref(null);
×
48

49
        async function loadPreferences(fetchPolicy = 'cache-first') {
×
NEW
50
                try {
×
NEW
51
                        const response = await apollo.query({ query: useGoalDataQuery, fetchPolicy });
×
NEW
52
                        const prefsData = response.data?.my?.userPreferences || null;
×
NEW
53
                        totalLoanCount.value = response.data?.my?.loans?.totalCount || 0;
×
NEW
54
                        userPreferences.value = prefsData;
×
NEW
55
                        return prefsData ? JSON.parse(prefsData.preferences || '{}') : {};
×
56
                } catch (error) {
NEW
57
                        logFormatter(error, 'Failed to load preferences');
×
NEW
58
                        return null;
×
59
                }
60
        }
61

62
        async function loadProgress(fetchPolicy = 'cache-first') {
×
NEW
63
                try {
×
NEW
64
                        const loanIds = loans.map(loan => loan.id);
×
NEW
65
                        const response = await apollo.query({
×
66
                                query: useGoalDataProgressQuery,
67
                                variables: { loanIds },
68
                                fetchPolicy
69
                        });
NEW
70
                        allTimeProgress.value = response?.data?.postCheckoutAchievements?.allTimeProgress || [];
×
NEW
71
                        return true;
×
72
                } catch (error) {
NEW
73
                        logFormatter(error, 'Failed to load progress');
×
NEW
74
                        return null;
×
75
                }
76
        }
77

78
        function setGoalState(parsedPrefs) {
NEW
79
                if (!parsedPrefs) return;
×
NEW
80
                const goals = parsedPrefs.goals || [];
×
NEW
81
                userGoal.value = { ...goals[0] };
×
82
        }
83

84
        async function storeGoalPreferences(updates) {
NEW
85
                if (!userPreferences.value) {
×
NEW
86
                        await createUserPreferences(apollo, { goals: [] });
×
NEW
87
                        await loadPreferences('network-only'); // Reload after create
×
88
                }
NEW
89
                const parsedPrefs = JSON.parse(userPreferences.value?.preferences || '{}');
×
NEW
90
                const goals = parsedPrefs.goals || [];
×
NEW
91
                const goalIndex = goals.findIndex(g => g.goalName === updates.goalName);
×
NEW
92
                if (goalIndex !== -1) goals[goalIndex] = { ...goals[goalIndex], ...updates };
×
NEW
93
                else goals.push(updates);
×
NEW
94
                await updateUserPreferences(apollo, userPreferences.value, parsedPrefs, { goals });
×
NEW
95
                setGoalState({ goals }); // Refresh local state after update
×
96
        }
97

NEW
98
        const goalProgress = computed(() => {
×
NEW
99
                if (userGoal.value?.category === ID_SUPPORT_ALL) return totalLoanCount.value || 0;
×
NEW
100
                const totalProgress = allTimeProgress.value.find(
×
NEW
101
                        entry => entry.achievementId === userGoal.value?.category
×
102
                )?.totalProgress || 0;
NEW
103
                const adjustedProgress = totalProgress - (userGoal.value?.loanTotalAtStart || 0);
×
NEW
104
                return Math.max(adjustedProgress, 0);
×
105
        });
106

NEW
107
        const userGoalAchieved = computed(() => goalProgress.value >= userGoal.value?.target);
×
108

109
        async function runComposable() {
NEW
110
                loading.value = true;
×
NEW
111
                const parsedPrefs = await loadPreferences();
×
NEW
112
                await loadProgress();
×
NEW
113
                setGoalState(parsedPrefs);
×
114
                // Auto-update if active goal achieved
NEW
115
                if (userGoal.value && userGoalAchieved.value) {
×
NEW
116
                        await storeGoalPreferences({
×
117
                                goalName: userGoal.value.goalName,
118
                                dateStarted: userGoal.value.dateStarted,
119
                                target: userGoal.value.target,
120
                                count: userGoal.value.count,
121
                                status: 'completed',
122
                        });
123
                }
NEW
124
                loading.value = false;
×
125
        }
126

NEW
127
        return {
×
128
                getGoalDisplayName,
129
                goalProgress,
130
                loading,
131
                runComposable,
132
                storeGoalPreferences,
133
                userGoal,
134
                userGoalAchieved,
135
        };
136
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc