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

kiva / ui / 18926168227

30 Oct 2025 12:38AM UTC coverage: 50.154% (-0.005%) from 50.159%
18926168227

push

github

web-flow
feat: usegoaldata composable refactor for flexibility (#6403)

1840 of 3910 branches covered (47.06%)

Branch coverage included in aggregate %.

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

1 existing line in 1 file now uncovered.

2723 of 5188 relevant lines covered (52.49%)

259.94 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

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) {
31
        return GOAL_DISPLAY_MAP[category] || 'loans';
×
32
}
33

34
/**
35
 * Vue composable for loading and managing user goal data
36
 *
37
 * @param {Object} options - Configuration options
38
 * @param {Array} options.loans - List of loans to count toward goals
39
 * @param {Object} options.apollo - Apollo client instance (optional, will use inject if not provided)
40
 * @returns Goal data and utilities
41
 */
42
export default function useGoalData({ loans, apollo: apolloParam }) {
43
        const apollo = apolloParam || inject('apollo');
×
44
        const $kvTrackEvent = inject('$kvTrackEvent');
×
45

46
        const allTimeProgress = ref([]);
×
47
        const loading = ref(true);
×
48
        const totalLoanCount = ref(null);
×
49
        const userGoal = ref(null);
×
50
        const userPreferences = ref(null);
×
51

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

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

81
        function setGoalState(parsedPrefs) {
82
                if (!parsedPrefs) return;
×
83
                const goals = parsedPrefs.goals || [];
×
84
                userGoal.value = { ...goals[0] };
×
85
        }
86

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

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

110
        const userGoalAchieved = computed(() => goalProgress.value >= userGoal.value?.target);
×
111

NEW
112
        const checkCompletedGoal = async (category = 'post-checkout') => {
×
113
                if (userGoal.value && userGoalAchieved.value && userGoal.value.status !== 'completed') {
×
114
                        await storeGoalPreferences({
×
115
                                goalName: userGoal.value.goalName,
116
                                dateStarted: userGoal.value.dateStarted,
117
                                target: userGoal.value.target,
118
                                count: userGoal.value.count,
119
                                status: 'completed',
120
                        });
121
                        $kvTrackEvent(
×
122
                                category,
123
                                'show',
124
                                'annual-goal-complete',
125
                                userGoal.value.category,
126
                                userGoal.value.target
127
                        );
128
                }
129
        };
130

131
        async function loadGoalData() {
NEW
132
                loading.value = true;
×
NEW
133
                const parsedPrefs = await loadPreferences();
×
NEW
134
                await loadProgress();
×
NEW
135
                setGoalState(parsedPrefs);
×
UNCOV
136
                loading.value = false;
×
137
        }
138

139
        return {
×
140
                getGoalDisplayName,
141
                goalProgress,
142
                loading,
143
                loadGoalData,
144
                storeGoalPreferences,
145
                userGoal,
146
                userGoalAchieved,
147
                checkCompletedGoal,
148
        };
149
}
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