@kiva/kv-components 3.74.0 → 3.75.0

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,25 @@
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.75.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.74.1...@kiva/kv-components@3.75.0) (2024-04-26)
7
+
8
+
9
+ ### Features
10
+
11
+ * clickable tags added to classic loan card ([#393](https://github.com/kiva/kv-ui-elements/issues/393)) ([3677c91](https://github.com/kiva/kv-ui-elements/commit/3677c915855d68b125f71a0660d4fbb4628b8133))
12
+
13
+
14
+
15
+
16
+
17
+ ## [3.74.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.74.0...@kiva/kv-components@3.74.1) (2024-04-25)
18
+
19
+ **Note:** Version bump only for package @kiva/kv-components
20
+
21
+
22
+
23
+
24
+
6
25
  # [3.74.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.73.2...@kiva/kv-components@3.74.0) (2024-04-23)
7
26
 
8
27
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.74.0",
3
+ "version": "3.75.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -53,7 +53,7 @@
53
53
  "build": "echo No build needed for @kiva/kv-components."
54
54
  },
55
55
  "dependencies": {
56
- "@kiva/kv-tokens": "^2.11.0",
56
+ "@kiva/kv-tokens": "^2.11.1",
57
57
  "@mdi/js": "^5.9.55",
58
58
  "@vueuse/integrations": "^7.6.0",
59
59
  "aria-hidden": "^1.1.3",
@@ -75,5 +75,5 @@
75
75
  "optional": true
76
76
  }
77
77
  },
78
- "gitHead": "db1d9c79b08cf5489aa474fddaa610c365526ab7"
78
+ "gitHead": "478101c653870979f75a18e4ea2cb355e21c28ac"
79
79
  }
@@ -1,4 +1,5 @@
1
1
  import { render } from '@testing-library/vue';
2
+ import userEvent from '@testing-library/user-event';
2
3
  import { axe } from 'jest-axe';
3
4
  import KvClassicLoanCard from '../../../../vue/KvClassicLoanCard.vue';
4
5
 
@@ -198,4 +199,22 @@ describe('KvClassicLoanCard', () => {
198
199
  expect(activityText).toBeDefined();
199
200
  expect(activityBtn).toBeDefined();
200
201
  });
202
+
203
+ it('should emit clicked tag data', async () => {
204
+ const { getByText, emitted } = render(KvClassicLoanCard,
205
+ {
206
+ props: {
207
+ loanId: loan.id,
208
+ loan,
209
+ kvTrackFunction,
210
+ photoPath,
211
+ enableClickableTags: true,
212
+ },
213
+ });
214
+ const tagSpan = getByText('Dairy');
215
+
216
+ await userEvent.click(tagSpan);
217
+
218
+ expect(emitted()['jump-filter-page']).toEqual([[{ id: 61, label: 'Dairy', type: 'activity' }]]);
219
+ });
201
220
  });
package/utils/loanCard.js CHANGED
@@ -11,6 +11,8 @@ const SUSTAINABLE_AG_KEY = 'SUSTAINABLE AG';
11
11
  const SINGLE_PARENT_KEY = 'SINGLE PARENT';
12
12
  const REFUGEE_KEY = 'REFUGEES/DISPLACED';
13
13
 
14
+ const findCalloutData = (tags, tagName) => tags?.find((t) => t.name.toUpperCase() === tagName.toUpperCase()) ?? {};
15
+
14
16
  export function loanCardComputedProperties(props) {
15
17
  const {
16
18
  externalLinks,
@@ -64,8 +66,11 @@ export function loanCardComputedProperties(props) {
64
66
 
65
67
  const loanCallouts = computed(() => {
66
68
  const callouts = [];
69
+
67
70
  const activityName = loan.value?.activity?.name ?? '';
71
+ const activityId = loan.value?.activity?.id ?? null;
68
72
  const sectorName = loan.value?.sector?.name ?? '';
73
+ const sectorId = loan.value?.sector?.id ?? null;
69
74
  const tags = loan.value?.tags?.filter((loantag) => loantag.charAt(0) === '#')
70
75
  .map((loantag) => loantag.substring(1)) ?? [];
71
76
  const themes = loan.value?.themes ?? [];
@@ -78,47 +83,54 @@ export function loanCardComputedProperties(props) {
78
83
 
79
84
  const isLseLoan = loan.value?.partnerName?.toUpperCase().includes(LSE_LOAN_KEY);
80
85
 
86
+ const tagsData = loan.value?.tagsData ?? [];
87
+ const themesData = loan.value?.themesData ?? [];
88
+
81
89
  // P1 Category
82
90
  // Exp limited to: Eco-friendly, Refugees and IDPs, Single Parents
83
91
  // Tag as first option for LSE loans
84
92
  if (isLseLoan && tags.length) {
85
93
  const position = Math.floor(Math.random() * tags.length);
86
94
  const p1Tag = tags[position];
87
- callouts.push(p1Tag);
95
+ const tagData = findCalloutData(tagsData, p1Tag);
96
+ const id = tagData?.id ?? null;
97
+ callouts.push({ label: p1Tag, type: 'tag', id });
88
98
  }
89
99
 
90
100
  if (!categoryPageName.value) {
91
101
  if (categories.ecoFriendly
92
102
  // 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');
103
+ && !callouts.find((c) => c.label.toUpperCase() === ECO_FRIENDLY_KEY || c.label.toUpperCase() === SUSTAINABLE_AG_KEY)) {
104
+ callouts.push({ label: 'Eco-friendly' });
95
105
  } else if (categories.refugeesIdps) {
96
- callouts.push('Refugees and IDPs');
106
+ callouts.push({ label: 'Refugees and IDPs' });
97
107
  } else if (categories.singleParents
98
- && !callouts.find((c) => c.toUpperCase() === SINGLE_PARENT_KEY)) {
99
- callouts.push('Single Parent');
108
+ && !callouts.find((c) => c.label.toUpperCase() === SINGLE_PARENT_KEY)) {
109
+ callouts.push({ label: 'Single Parent' });
100
110
  }
101
111
  }
102
112
 
103
113
  // P2 Activity
104
- if (activityName && categoryPageName.value?.toUpperCase() !== activityName.toUpperCase()) {
105
- callouts.push(activityName);
114
+ if (activityName && activityId && categoryPageName.value?.toUpperCase() !== activityName.toUpperCase()) {
115
+ callouts.push({ id: activityId, label: activityName, type: 'activity' });
106
116
  }
107
117
 
108
118
  // P3 Sector
109
- if (sectorName
119
+ if (sectorName && sectorId
110
120
  && (activityName.toUpperCase() !== sectorName.toUpperCase())
111
121
  && (sectorName.toUpperCase() !== categoryPageName.value?.toUpperCase())
112
122
  && callouts.length < 2) {
113
- callouts.push(sectorName);
123
+ callouts.push({ id: sectorId, label: sectorName, type: 'sector' });
114
124
  }
115
125
 
116
126
  // P4 Tag
117
127
  if (!!tags.length && callouts.length < 2) {
118
128
  const position = Math.floor(Math.random() * tags.length);
119
129
  const p4Tag = tags[position];
120
- if (!callouts.filter((c) => c.toUpperCase() === p4Tag.toUpperCase()).length) {
121
- callouts.push(p4Tag);
130
+ const tagData = findCalloutData(tagsData, p4Tag);
131
+ const id = tagData?.id ?? null;
132
+ if (!callouts.filter((c) => c.label.toUpperCase() === p4Tag.toUpperCase()).length) {
133
+ callouts.push({ label: p4Tag, type: 'tag', id });
122
134
  }
123
135
  }
124
136
 
@@ -126,9 +138,11 @@ export function loanCardComputedProperties(props) {
126
138
  if (!!themes.length && callouts.length < 2) {
127
139
  const position = Math.floor(Math.random() * themes.length);
128
140
  const theme = themes[position];
129
- if (!callouts.filter((c) => c.toUpperCase() === theme.toUpperCase()).length
141
+ const themeData = findCalloutData(themesData, theme);
142
+ const id = themeData?.id ?? null;
143
+ if (!callouts.filter((c) => c.label.toUpperCase() === theme.toUpperCase()).length
130
144
  && theme.toUpperCase() !== categoryPageName.value?.toUpperCase()) {
131
- callouts.push(theme);
145
+ callouts.push({ label: theme, type: 'theme', id });
132
146
  }
133
147
  }
134
148
 
@@ -136,7 +150,8 @@ export function loanCardComputedProperties(props) {
136
150
  if (isLseLoan && callouts.length > 1) return [callouts.shift()];
137
151
 
138
152
  // Add all custom callouts if available
139
- callouts.push(...customCallouts?.value);
153
+ const customTags = customCallouts.value?.map((c) => ({ label: c })) ?? [];
154
+ callouts.push(...customTags);
140
155
  return callouts;
141
156
  });
142
157
 
@@ -152,8 +152,10 @@
152
152
  <kv-loan-callouts
153
153
  v-else
154
154
  :callouts="loanCallouts"
155
+ :enable-clickable="enableClickableTags"
155
156
  class="tw-mt-1.5"
156
157
  :class="{ 'tw-px-1': largeCard }"
158
+ @click="$emit('jump-filter-page', $event)"
157
159
  />
158
160
  </div>
159
161
 
@@ -391,6 +393,10 @@ export default {
391
393
  type: Boolean,
392
394
  default: false,
393
395
  },
396
+ enableClickableTags: {
397
+ type: Boolean,
398
+ default: false,
399
+ },
394
400
  },
395
401
  setup(props) {
396
402
  const {
@@ -13,8 +13,8 @@
13
13
  >
14
14
  <span
15
15
  v-for="tag in callouts"
16
- :key="tag"
17
- :title="tag"
16
+ :key="tag.label"
17
+ :title="tag.label"
18
18
  class="
19
19
  loan-callout
20
20
  tw-text-ellipsis
@@ -27,14 +27,18 @@
27
27
  tw-mb-0.5
28
28
  tw-text-small
29
29
  "
30
+ :class="{ 'tw-cursor-pointer hover:tw-underline': isClickable(tag) }"
31
+ @click="clickCallout(tag)"
30
32
  >
31
- {{ tag }}
33
+ {{ tag.label }}
32
34
  </span>
33
35
  </div>
34
36
  </div>
35
37
  </template>
36
38
 
37
39
  <script>
40
+ import { toRefs } from 'vue-demi';
41
+
38
42
  export default {
39
43
  name: 'KvLoanCallouts',
40
44
  props: {
@@ -42,6 +46,36 @@ export default {
42
46
  type: Array,
43
47
  required: true,
44
48
  },
49
+ enableClickable: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
53
+ },
54
+ emits: [
55
+ 'click',
56
+ ],
57
+ setup(props, { emit }) {
58
+ const {
59
+ enableClickable,
60
+ } = toRefs(props);
61
+
62
+ const isClickable = (tag) => {
63
+ const clickableTypes = ['activity', 'sector', 'tag', 'theme'];
64
+ const isClickableType = clickableTypes.includes(tag.type);
65
+
66
+ return enableClickable.value && isClickableType && !!tag.id;
67
+ };
68
+
69
+ const clickCallout = (tag) => {
70
+ if (isClickable(tag)) {
71
+ emit('click', tag);
72
+ }
73
+ };
74
+
75
+ return {
76
+ isClickable,
77
+ clickCallout,
78
+ };
45
79
  },
46
80
  };
47
81
  </script>
@@ -32,6 +32,7 @@ const story = (args) => {
32
32
  :is-team-pick="isTeamPick"
33
33
  :combined-activities="combinedActivities"
34
34
  :enable-huge-amount="enableHugeAmount"
35
+ :enable-clickable-tags="enableClickableTags"
35
36
  />
36
37
  </div>
37
38
  `,
@@ -388,3 +389,11 @@ export const HugeLentAmount = story({
388
389
  isVisitor: false,
389
390
  enableHugeAmount: true,
390
391
  });
392
+
393
+ export const ClickableTags = story({
394
+ loanId: loan.id,
395
+ loan,
396
+ kvTrackFunction,
397
+ photoPath,
398
+ enableClickableTags: true,
399
+ });
@@ -12,6 +12,7 @@ const story = (args) => {
12
12
  template: `
13
13
  <kv-loan-callouts
14
14
  :callouts="callouts"
15
+ :enableClickable="enableClickable"
15
16
  />
16
17
  `,
17
18
  });
@@ -19,4 +20,15 @@ const story = (args) => {
19
20
  return template;
20
21
  };
21
22
 
22
- export const Default = story({ callouts: ['callout 1', 'callout 2', 'callout 3'] });
23
+ export const Default = story({ callouts: [{ label: 'callout 1' }, { label: 'callout 2' }, { label: 'callout 3' }] });
24
+
25
+ export const Clickable = story({
26
+ callouts: [
27
+ { id: 1, label: 'callout 1', type: 'activity' },
28
+ { label: 'callout 2' },
29
+ { id: 33, label: 'callout 3', type: 'sector' },
30
+ { id: null, label: 'callout 4', type: 'tag' },
31
+ { id: 12, label: 'callout 5', type: 'theme' },
32
+ ],
33
+ enableClickable: true,
34
+ });