@kiva/kv-components 3.48.0 → 3.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,14 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [3.48.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.48.0...@kiva/kv-components@3.48.1) (2023-11-29)
7
+
8
+ **Note:** Version bump only for package @kiva/kv-components
9
+
10
+
11
+
12
+
13
+
6
14
  # [3.48.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.47.0...@kiva/kv-components@3.48.0) (2023-11-20)
7
15
 
8
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.48.0",
3
+ "version": "3.48.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -75,5 +75,5 @@
75
75
  "optional": true
76
76
  }
77
77
  },
78
- "gitHead": "d6d10fe82c51bb9bd2bab93e475dac025d1298e9"
78
+ "gitHead": "2c7054617fe956199335addc794ce7ac78003dab"
79
79
  }
@@ -0,0 +1,136 @@
1
+ import { render } from '@testing-library/vue';
2
+ import { axe } from 'jest-axe';
3
+ import KvClassicLoanCard from '../../../../vue/KvClassicLoanCard.vue';
4
+
5
+ const nextWeek = new Date();
6
+ nextWeek.setDate(new Date().getDate() + 7);
7
+ const kvTrackFunction = () => { };
8
+
9
+ const photoPath = 'https://www-kiva-org.freetls.fastly.net/img/';
10
+ const loan = {
11
+ id: 1,
12
+ name: 'Alan',
13
+ geocode: {
14
+ city: 'Lyantonde',
15
+ state: 'Central Region',
16
+ country: {
17
+ isoCode: 'UG',
18
+ name: 'Uganda',
19
+ region: 'Africa',
20
+ __typename: 'Country',
21
+ },
22
+ __typename: 'Geocode',
23
+ },
24
+ image: { hash: '9673d0722a7675b9b8d11f90849d9b44' },
25
+ fundraisingPercent: 0.5,
26
+ unreservedAmount: '500.00',
27
+ use: 'to purchase heifers to increase headcount of cattle and sales of organic milk.',
28
+ status: 'fundraising',
29
+ loanAmount: '1000.00',
30
+ borrowerCount: 1,
31
+ activity: {
32
+ id: 61,
33
+ name: 'Dairy',
34
+ __typename: 'Activity',
35
+ },
36
+ sector: {
37
+ id: 1,
38
+ name: 'Agriculture',
39
+ __typename: 'Sector',
40
+ },
41
+ plannedExpirationDate: nextWeek.toISOString(),
42
+ };
43
+
44
+ describe('KvClassicLoanCard', () => {
45
+ it('has no automated accessibility violations', async () => {
46
+ const { container } = render(KvClassicLoanCard,
47
+ {
48
+ props: {
49
+ loanId: loan.id,
50
+ loan: {
51
+ ...loan,
52
+ unreservedAmount: undefined,
53
+ fundraisingPercent: undefined,
54
+ },
55
+ kvTrackFunction,
56
+ photoPath,
57
+ externalLinks: true,
58
+ },
59
+ });
60
+ const results = await axe(container);
61
+ expect(results).toHaveNoViolations();
62
+ });
63
+ it('location should be formatted correctly for PR', async () => {
64
+ const { getByText } = render(KvClassicLoanCard,
65
+ {
66
+ props: {
67
+ loanId: loan.id,
68
+ loan: {
69
+ ...loan,
70
+ unreservedAmount: undefined,
71
+ fundraisingPercent: undefined,
72
+ geocode: {
73
+ city: 'Rincon',
74
+ country: {
75
+ name: 'Puerto Rico',
76
+ },
77
+ },
78
+ },
79
+ kvTrackFunction,
80
+ photoPath,
81
+ externalLinks: true,
82
+ },
83
+ });
84
+
85
+ const countryTagElement = getByText('Rincon, PR');
86
+ expect(countryTagElement).toBeDefined();
87
+ });
88
+ it('location should be formatted correctly for Kiva US', async () => {
89
+ const { getByText } = render(KvClassicLoanCard,
90
+ {
91
+ props: {
92
+ loanId: loan.id,
93
+ loan: {
94
+ ...loan,
95
+ distributionModel: 'direct',
96
+ geocode: {
97
+ city: 'Boulder',
98
+ state: 'Colorado',
99
+ country: {
100
+ name: 'United States',
101
+ },
102
+ },
103
+ },
104
+ kvTrackFunction,
105
+ photoPath,
106
+ externalLinks: true,
107
+ },
108
+ });
109
+
110
+ const countryTagElement = getByText('Boulder, Colorado, United States');
111
+ expect(countryTagElement).toBeDefined();
112
+ });
113
+ it('location should be formatted correctly for partner loans', async () => {
114
+ const { getByText } = render(KvClassicLoanCard,
115
+ {
116
+ props: {
117
+ loanId: loan.id,
118
+ loan: {
119
+ ...loan,
120
+ distributionModel: 'partner',
121
+ geocode: {
122
+ country: {
123
+ name: 'Uganda',
124
+ },
125
+ },
126
+ },
127
+ kvTrackFunction,
128
+ photoPath,
129
+ externalLinks: true,
130
+ },
131
+ });
132
+
133
+ const countryTagElement = getByText('Uganda');
134
+ expect(countryTagElement).toBeDefined();
135
+ });
136
+ });
@@ -0,0 +1,136 @@
1
+ import { render } from '@testing-library/vue';
2
+ import { axe } from 'jest-axe';
3
+ import KvWideLoanCard from '../../../../vue/KvWideLoanCard.vue';
4
+
5
+ const nextWeek = new Date();
6
+ nextWeek.setDate(new Date().getDate() + 7);
7
+ const kvTrackFunction = () => { };
8
+
9
+ const photoPath = 'https://www-kiva-org.freetls.fastly.net/img/';
10
+ const loan = {
11
+ id: 1,
12
+ name: 'Alan',
13
+ geocode: {
14
+ city: 'Lyantonde',
15
+ state: 'Central Region',
16
+ country: {
17
+ isoCode: 'UG',
18
+ name: 'Uganda',
19
+ region: 'Africa',
20
+ __typename: 'Country',
21
+ },
22
+ __typename: 'Geocode',
23
+ },
24
+ image: { hash: '9673d0722a7675b9b8d11f90849d9b44' },
25
+ fundraisingPercent: 0.5,
26
+ unreservedAmount: '500.00',
27
+ use: 'to purchase heifers to increase headcount of cattle and sales of organic milk.',
28
+ status: 'fundraising',
29
+ loanAmount: '1000.00',
30
+ borrowerCount: 1,
31
+ activity: {
32
+ id: 61,
33
+ name: 'Dairy',
34
+ __typename: 'Activity',
35
+ },
36
+ sector: {
37
+ id: 1,
38
+ name: 'Agriculture',
39
+ __typename: 'Sector',
40
+ },
41
+ plannedExpirationDate: nextWeek.toISOString(),
42
+ };
43
+
44
+ describe('KvWideLoanCard', () => {
45
+ it('has no automated accessibility violations', async () => {
46
+ const { container } = render(KvWideLoanCard,
47
+ {
48
+ props: {
49
+ loanId: loan.id,
50
+ loan: {
51
+ ...loan,
52
+ unreservedAmount: undefined,
53
+ fundraisingPercent: undefined,
54
+ },
55
+ kvTrackFunction,
56
+ photoPath,
57
+ externalLinks: true,
58
+ },
59
+ });
60
+ const results = await axe(container);
61
+ expect(results).toHaveNoViolations();
62
+ });
63
+ it('location should be formatted correctly for PR', async () => {
64
+ const { getByText } = render(KvWideLoanCard,
65
+ {
66
+ props: {
67
+ loanId: loan.id,
68
+ loan: {
69
+ ...loan,
70
+ unreservedAmount: undefined,
71
+ fundraisingPercent: undefined,
72
+ geocode: {
73
+ city: 'Rincon',
74
+ country: {
75
+ name: 'Puerto Rico',
76
+ },
77
+ },
78
+ },
79
+ kvTrackFunction,
80
+ photoPath,
81
+ externalLinks: true,
82
+ },
83
+ });
84
+
85
+ const countryTagElement = getByText('Rincon, PR');
86
+ expect(countryTagElement).toBeDefined();
87
+ });
88
+ it('location should be formatted correctly for Kiva US', async () => {
89
+ const { getByText } = render(KvWideLoanCard,
90
+ {
91
+ props: {
92
+ loanId: loan.id,
93
+ loan: {
94
+ ...loan,
95
+ distributionModel: 'direct',
96
+ geocode: {
97
+ city: 'Boulder',
98
+ state: 'Colorado',
99
+ country: {
100
+ name: 'United States',
101
+ },
102
+ },
103
+ },
104
+ kvTrackFunction,
105
+ photoPath,
106
+ externalLinks: true,
107
+ },
108
+ });
109
+
110
+ const countryTagElement = getByText('Boulder, Colorado, United States');
111
+ expect(countryTagElement).toBeDefined();
112
+ });
113
+ it('location should be formatted correctly for partner loans', async () => {
114
+ const { getByText } = render(KvWideLoanCard,
115
+ {
116
+ props: {
117
+ loanId: loan.id,
118
+ loan: {
119
+ ...loan,
120
+ distributionModel: 'partner',
121
+ geocode: {
122
+ country: {
123
+ name: 'Uganda',
124
+ },
125
+ },
126
+ },
127
+ kvTrackFunction,
128
+ photoPath,
129
+ externalLinks: true,
130
+ },
131
+ });
132
+
133
+ const countryTagElement = getByText('Uganda');
134
+ expect(countryTagElement).toBeDefined();
135
+ });
136
+ });
@@ -0,0 +1,189 @@
1
+ import {
2
+ computed,
3
+ toRefs,
4
+ } from 'vue-demi';
5
+
6
+ import { mdiMapMarker } from '@mdi/js';
7
+
8
+ const LSE_LOAN_KEY = 'N/A';
9
+ const ECO_FRIENDLY_KEY = 'ECO-FRIENDLY';
10
+ const SUSTAINABLE_AG_KEY = 'SUSTAINABLE AG';
11
+ const SINGLE_PARENT_KEY = 'SINGLE PARENT';
12
+ const REFUGEE_KEY = 'REFUGEES/DISPLACED';
13
+
14
+ export function loanCardComputedProperties(props) {
15
+ const {
16
+ externalLinks,
17
+ customLoanDetails,
18
+ loanId,
19
+ loan,
20
+ categoryPageName,
21
+ customCallouts,
22
+ } = toRefs(props);
23
+
24
+ const tag = computed(() => (externalLinks.value ? 'a' : 'router-link'));
25
+ const readMorePath = computed(() => (customLoanDetails.value ? '' : `/lend/${loanId.value}`));
26
+ const isLoading = computed(() => !loanId.value || !loan.value);
27
+ const borrowerName = computed(() => loan.value?.name || '');
28
+ const countryName = computed(() => loan.value?.geocode?.country?.name || '');
29
+ const city = computed(() => loan.value?.geocode?.city || '');
30
+ const state = computed(() => loan.value?.geocode?.state || '');
31
+ const distributionModel = computed(() => loan.value?.distributionModel || '');
32
+ const imageHash = computed(() => loan.value?.image?.hash ?? '');
33
+ const hasProgressData = computed(() => {
34
+ return typeof loan.value?.unreservedAmount !== 'undefined'
35
+ && typeof loan.value?.fundraisingPercent !== 'undefined';
36
+ });
37
+
38
+ const allDataLoaded = computed(() => !isLoading.value && hasProgressData.value);
39
+
40
+ const fundraisingPercent = computed(() => loan.value?.fundraisingPercent ?? 0);
41
+
42
+ const unreservedAmount = computed(() => {
43
+ const stringAmount = loan.value?.unreservedAmount ?? '0';
44
+ return Number(stringAmount);
45
+ });
46
+
47
+ const formattedLocation = computed(() => {
48
+ if (distributionModel.value === 'direct') {
49
+ return `${city.value}, ${state.value}, ${countryName.value}`;
50
+ }
51
+ if (countryName.value === 'Puerto Rico') {
52
+ return `${city.value}, PR`;
53
+ }
54
+ return countryName.value;
55
+ });
56
+
57
+ const loanUse = computed(() => loan.value?.use ?? '');
58
+
59
+ const loanStatus = computed(() => loan.value?.status ?? '');
60
+
61
+ const loanAmount = computed(() => loan.value?.loanAmount ?? '0');
62
+
63
+ const loanBorrowerCount = computed(() => loan.value?.borrowerCount ?? 0);
64
+
65
+ const loanCallouts = computed(() => {
66
+ const callouts = [];
67
+ const activityName = loan.value?.activity?.name ?? '';
68
+ const sectorName = loan.value?.sector?.name ?? '';
69
+ const tags = loan.value?.tags?.filter((loantag) => loantag.charAt(0) === '#')
70
+ .map((loantag) => loantag.substring(1)) ?? [];
71
+ const themes = loan.value?.themes ?? [];
72
+ const categories = {
73
+ ecoFriendly: !!tags
74
+ .filter((t) => t.toUpperCase() === ECO_FRIENDLY_KEY || t.toUpperCase() === SUSTAINABLE_AG_KEY).length,
75
+ refugeesIdps: !!themes.filter((t) => t.toUpperCase() === REFUGEE_KEY).length,
76
+ singleParents: !!tags.filter((t) => t.toUpperCase() === SINGLE_PARENT_KEY).length,
77
+ };
78
+
79
+ const isLseLoan = loan.value?.partnerName?.toUpperCase().includes(LSE_LOAN_KEY);
80
+
81
+ // P1 Category
82
+ // Exp limited to: Eco-friendly, Refugees and IDPs, Single Parents
83
+ // Tag as first option for LSE loans
84
+ if (isLseLoan && tags.length) {
85
+ const position = Math.floor(Math.random() * tags.length);
86
+ const atag = tags[position];
87
+ callouts.push(atag);
88
+ }
89
+
90
+ if (!categoryPageName.value) {
91
+ if (categories.ecoFriendly
92
+ // eslint-disable-next-line max-len
93
+ && !callouts.find((c) => c.toUpperCase() === ECO_FRIENDLY_KEY || c.toUpperCase() === SUSTAINABLE_AG_KEY)) {
94
+ callouts.push('Eco-friendly');
95
+ } else if (categories.refugeesIdps) {
96
+ callouts.push('Refugees and IDPs');
97
+ } else if (categories.singleParents
98
+ && !callouts.find((c) => c.toUpperCase() === SINGLE_PARENT_KEY)) {
99
+ callouts.push('Single Parent');
100
+ }
101
+ }
102
+
103
+ // P2 Activity
104
+ if (activityName && categoryPageName.value?.toUpperCase() !== activityName.toUpperCase()) {
105
+ callouts.push(activityName);
106
+ }
107
+
108
+ // P3 Sector
109
+ if (sectorName
110
+ && (activityName.toUpperCase() !== sectorName.toUpperCase())
111
+ && (sectorName.toUpperCase() !== categoryPageName.value?.toUpperCase())
112
+ && callouts.length < 2) {
113
+ callouts.push(sectorName);
114
+ }
115
+
116
+ // P4 Tag
117
+ if (!!tags.length && callouts.length < 2) {
118
+ const position = Math.floor(Math.random() * tags.length);
119
+ const atag = tags[position];
120
+ if (!callouts.filter((c) => c.toUpperCase() === tag.toUpperCase()).length) {
121
+ callouts.push(atag);
122
+ }
123
+ }
124
+
125
+ // P5 Theme
126
+ if (!!themes.length && callouts.length < 2) {
127
+ const position = Math.floor(Math.random() * themes.length);
128
+ const theme = themes[position];
129
+ if (!callouts.filter((c) => c.toUpperCase() === theme.toUpperCase()).length
130
+ && theme.toUpperCase() !== categoryPageName.value?.toUpperCase()) {
131
+ callouts.push(theme);
132
+ }
133
+ }
134
+
135
+ // Only show one callout for LSE loans
136
+ if (isLseLoan && callouts.length > 1) return [callouts.shift()];
137
+
138
+ // Add all custom callouts if available
139
+ callouts.push(...customCallouts?.value);
140
+ return callouts;
141
+ });
142
+
143
+ return {
144
+ tag,
145
+ readMorePath,
146
+ isLoading,
147
+ borrowerName,
148
+ countryName,
149
+ city,
150
+ state,
151
+ distributionModel,
152
+ imageHash,
153
+ hasProgressData,
154
+ allDataLoaded,
155
+ fundraisingPercent,
156
+ unreservedAmount,
157
+ formattedLocation,
158
+ loanUse,
159
+ loanStatus,
160
+ loanAmount,
161
+ loanBorrowerCount,
162
+ mdiMapMarker,
163
+ loanCallouts,
164
+ };
165
+ }
166
+
167
+ export function loanCardMethods(props) {
168
+ const {
169
+ loanId,
170
+ customLoanDetails,
171
+ kvTrackFunction,
172
+ } = toRefs(props);
173
+
174
+ function showLoanDetails(e) {
175
+ if (customLoanDetails.value) {
176
+ e.preventDefault();
177
+ this.$emit('show-loan-details');
178
+ }
179
+ }
180
+
181
+ function clickReadMore(target) {
182
+ kvTrackFunction.value('Lending', 'click-Read more', target, loanId.value);
183
+ }
184
+
185
+ return {
186
+ showLoanDetails,
187
+ clickReadMore,
188
+ };
189
+ }
@@ -146,8 +146,17 @@ export default {
146
146
  if (!width && !height && !square && !faceZoom) {
147
147
  return '';
148
148
  }
149
- const w = width ? `w${Math.ceil(width)}` : '';
150
- const h = height ? `h${Math.ceil(height)}` : '';
149
+ let w = '';
150
+ let h = '';
151
+ // If width and height are different, use w and h
152
+ if (width === height) {
153
+ // if height and width are the same, use square param
154
+ // eslint-disable-next-line no-param-reassign
155
+ square = width;
156
+ } else {
157
+ w = width ? `w${Math.ceil(width)}` : '';
158
+ h = height ? `h${Math.ceil(height)}` : '';
159
+ }
151
160
  const s = square ? `s${Math.ceil(square)}` : '';
152
161
  const fz = faceZoom ? `fz${Math.ceil(faceZoom)}` : '';
153
162