@kiva/kv-components 3.88.1 → 3.89.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,31 @@
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.89.0](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.88.1...@kiva/kv-components@3.89.0) (2024-07-23)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * flag-icons import ([0b58418](https://github.com/kiva/kv-ui-elements/commit/0b58418bf5aeb58cb8eefc265c228092e6e761e4))
12
+ * indent, use kvFlag and some refactor ([4fbc11a](https://github.com/kiva/kv-ui-elements/commit/4fbc11a03fa2970e7d8c3cc340aa144b9da35c24))
13
+ * line-clamp in loan use ([f4cf963](https://github.com/kiva/kv-ui-elements/commit/f4cf963a567adc6ba23349cbe0da1bc2d15f24d1))
14
+ * loan name clickable ([18f63ca](https://github.com/kiva/kv-ui-elements/commit/18f63ca60d08f92e034cae73e3eb326b2a61f735))
15
+ * loan use template ([4efe849](https://github.com/kiva/kv-ui-elements/commit/4efe8493ec1dce8a3edb73d17e47c1fb8e308be2))
16
+ * remove class props for deep ([c6923dc](https://github.com/kiva/kv-ui-elements/commit/c6923dc3ff576be80efc69f72a9cf6d35974aef7))
17
+ * remove kvflag from loan card ([1e2bba8](https://github.com/kiva/kv-ui-elements/commit/1e2bba8c726e7702aa52efb765651a138feb2220))
18
+
19
+
20
+ ### Features
21
+
22
+ * introduction card component and story ([7115800](https://github.com/kiva/kv-ui-elements/commit/71158004b0b9a18e9bf1ba8375c213c1c3ca251f))
23
+ * kvflag component and new loan card for homepage ([8cf61bb](https://github.com/kiva/kv-ui-elements/commit/8cf61bb62820c6f9ce280d0f864f5b58d5279694))
24
+ * toggle flag border ([2a782a1](https://github.com/kiva/kv-ui-elements/commit/2a782a1c9bec4ca9d0d3f60a7e9a6d44a310956c))
25
+ * using flag emoticons ([159497b](https://github.com/kiva/kv-ui-elements/commit/159497b08bb1efb5989544df068624cca3c6929b))
26
+
27
+
28
+
29
+
30
+
6
31
  ## [3.88.1](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.88.0...@kiva/kv-components@3.88.1) (2024-07-22)
7
32
 
8
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.88.1",
3
+ "version": "3.89.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -66,6 +66,7 @@
66
66
  "change-case": "^4.1.2",
67
67
  "date-fns": "^2.30.0",
68
68
  "embla-carousel": "^4.5.3",
69
+ "flag-icons": "^7.2.3",
69
70
  "focus-trap": "^6.7.2",
70
71
  "moment": "^2.29.4",
71
72
  "nanoid": "^3.1.23",
@@ -81,5 +82,5 @@
81
82
  "optional": true
82
83
  }
83
84
  },
84
- "gitHead": "76a3892223c35267dfbe3a9f25a9b78e62a7b1f0"
85
+ "gitHead": "042c90f037f0b23407c5daacfcc8f7668bc17c2d"
85
86
  }
package/utils/loanCard.js CHANGED
@@ -28,6 +28,7 @@ export function loanCardComputedProperties(props) {
28
28
  const isLoading = computed(() => !loanId.value || !loan.value);
29
29
  const borrowerName = computed(() => loan.value?.name || '');
30
30
  const countryName = computed(() => loan.value?.geocode?.country?.name || '');
31
+ const countryCode = computed(() => loan.value?.geocode?.country?.isoCode || '');
31
32
  const city = computed(() => loan.value?.geocode?.city || '');
32
33
  const state = computed(() => loan.value?.geocode?.state || '');
33
34
  const distributionModel = computed(() => loan.value?.distributionModel || '');
@@ -161,6 +162,7 @@ export function loanCardComputedProperties(props) {
161
162
  isLoading,
162
163
  borrowerName,
163
164
  countryName,
165
+ countryCode,
164
166
  city,
165
167
  state,
166
168
  distributionModel,
package/vue/KvFlag.vue ADDED
@@ -0,0 +1,120 @@
1
+ <template>
2
+ <div
3
+ v-if="country"
4
+ :class="`kv-flag kv-flag--${aspectRatio}`"
5
+ :style="{ maxWidth: spriteWidth, minWidth: spriteWidth }"
6
+ >
7
+ <div
8
+ class="
9
+ kv-flag__wrapper
10
+ kv-flag-svg
11
+ tw-bg-gray-100
12
+ tw-relative
13
+ tw-overflow-hidden
14
+ tw-h-0
15
+ tw-w-full
16
+ tw-border
17
+ tw-border-gray-600
18
+ !tw-bg-cover
19
+ fib
20
+ "
21
+ :class="classes"
22
+ >
23
+ <span class="tw-sr-only">{{ countryName }}</span>
24
+ </div>
25
+ <span
26
+ v-if="showName"
27
+ class="tw-text-h4 tw-my-2"
28
+ >{{ getNameByCode(country) }}</span>
29
+ </div>
30
+ </template>
31
+
32
+ <script>
33
+ export default {
34
+ name: 'KvFlag',
35
+ props: {
36
+ /**
37
+ * 2 letter ISO country code of the flag to show
38
+ * */
39
+ country: {
40
+ type: String,
41
+ required: true,
42
+ },
43
+ /**
44
+ * Aspect Ratio of the flag image
45
+ * `4x3, 1x1`
46
+ * */
47
+ aspectRatio: {
48
+ type: String,
49
+ default: '4x3',
50
+ },
51
+ /**
52
+ * Show the name of the country next to the flag
53
+ */
54
+ showName: {
55
+ type: Boolean,
56
+ default: false,
57
+ },
58
+ /**
59
+ * Override the width of the flag
60
+ */
61
+ widthOverride: {
62
+ type: String,
63
+ default: null,
64
+ },
65
+ /**
66
+ * Hide the border around the flag
67
+ */
68
+ hideBorder: {
69
+ type: Boolean,
70
+ default: false,
71
+ },
72
+ },
73
+ async setup() {
74
+ const countryList = await import('../../../node_modules/flag-icons/country.json');
75
+
76
+ return {
77
+ countryList,
78
+ };
79
+ },
80
+ computed: {
81
+ spriteWidth() {
82
+ if (this.widthOverride) {
83
+ return this.widthOverride;
84
+ }
85
+ return '100%';
86
+ },
87
+ countryName() {
88
+ return `Flag of ${this.getNameByCode(this.country)}`;
89
+ },
90
+ classes() {
91
+ return {
92
+ [`fi-${this.country.toLowerCase()}`]: true,
93
+ 'tw-border-0': this.hideBorder,
94
+ };
95
+ },
96
+ },
97
+ methods: {
98
+ getNameByCode(code) {
99
+ const uppercaseCode = code?.toLowerCase() ?? '';
100
+ return this.countryList?.default?.find((country) => country.code === uppercaseCode)?.name ?? '';
101
+ },
102
+ },
103
+ };
104
+ </script>
105
+
106
+ <style lang="postcss" scoped>
107
+ @import "../../../node_modules/flag-icons/css/flag-icons.min.css";
108
+
109
+ .kv-flag__wrapper {
110
+ line-height: 0;
111
+ }
112
+
113
+ .kv-flag--4x3 .kv-flag__wrapper.kv-flag-svg {
114
+ padding-bottom: 71%;
115
+ }
116
+
117
+ .kv-flag--1x1 .kv-flag__wrapper.kv-flag-svg {
118
+ padding-bottom: 96%;
119
+ }
120
+ </style>
@@ -0,0 +1,418 @@
1
+ <template>
2
+ <div
3
+ class="card-container"
4
+ :class="{ 'tw-pointer-events-none' : isLoading }"
5
+ style="box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);"
6
+ :style="{ minWidth: '230px', maxWidth: '20.5rem' }"
7
+ >
8
+ <div class="tw-grow">
9
+ <div class="loan-card-active-hover">
10
+ <!-- Borrower image -->
11
+ <kv-loading-placeholder
12
+ v-if="isLoading"
13
+ class="tw-w-full tw-rounded-t"
14
+ :style="{ height: '11rem' }"
15
+ />
16
+ <div
17
+ v-else
18
+ class="tw-relative"
19
+ >
20
+ <component
21
+ :is="tag"
22
+ :to="readMorePath"
23
+ :href="readMorePath"
24
+ class="tw-flex"
25
+ aria-label="Borrower image"
26
+ @click.native="clickReadMore('Photo', $event)"
27
+ >
28
+ <kv-borrower-image
29
+ class="
30
+ tw-relative
31
+ tw-w-full
32
+ tw-bg-black
33
+ tw-rounded-t
34
+ borrower-image
35
+ "
36
+ :alt="`Photo of ${borrowerName}`"
37
+ :aspect-ratio="imageAspectRatio"
38
+ :default-image="{ width: imageDefaultWidth }"
39
+ :hash="imageHash"
40
+ :images="imageSizes"
41
+ :photo-path="photoPath"
42
+ />
43
+
44
+ <div v-if="countryName">
45
+ <p
46
+ class="
47
+ tw-absolute
48
+ tw-bottom-1
49
+ tw-left-1
50
+ tw-text-primary
51
+ tw-bg-white
52
+ tw-rounded
53
+ tw-p-1
54
+ tw-mb-0
55
+ tw-mr-2
56
+ tw-text-h4
57
+ tw-inline-flex
58
+ tw-items-center
59
+ !tw-capitalize
60
+ "
61
+ style="padding: 2px 6px;"
62
+ >
63
+ <kv-flag
64
+ class="tw-mr-0.5"
65
+ :country="countryCode"
66
+ width-override="0.725rem"
67
+ hide-border
68
+ />
69
+ {{ formattedLocation }}
70
+ </p>
71
+ </div>
72
+ </component>
73
+ </div>
74
+
75
+ <!-- Loan name -->
76
+
77
+ <kv-loading-placeholder
78
+ v-if="isLoading || typeof loanCallouts === 'undefined'"
79
+ class="tw-mt-1 tw-mx-auto"
80
+ :style="{ width: '60%', height: '1.75rem', 'border-radius': '500rem' }"
81
+ />
82
+
83
+ <h2
84
+ class="loan-card-name"
85
+ :class="{'tw-text-center': borrowerName.length < 20}"
86
+ @click="clickReadMore('Name', $event)"
87
+ >
88
+ {{ borrowerName }}
89
+ </h2>
90
+
91
+ <!-- Loan tag -->
92
+
93
+ <div
94
+ v-if="isLoading"
95
+ class="tw-flex tw-justify-center tw-gap-2"
96
+ >
97
+ <kv-loading-placeholder
98
+ v-if="isLoading || typeof loanCallouts === 'undefined'"
99
+ class="tw-mt-0.5 tw-mb-1"
100
+ :style="{ width: '20%', height: '1.75rem', 'border-radius': '500rem' }"
101
+ />
102
+ <kv-loading-placeholder
103
+ v-if="isLoading || typeof loanCallouts === 'undefined'"
104
+ class="tw-mt-0.5 tw-mb-1"
105
+ :style="{ width: '20%', height: '1.75rem', 'border-radius': '500rem' }"
106
+ />
107
+ <kv-loading-placeholder
108
+ v-if="isLoading || typeof loanCallouts === 'undefined'"
109
+ class="tw-mt-0.5 tw-mb-1"
110
+ :style="{ width: '20%', height: '1.75rem', 'border-radius': '500rem' }"
111
+ />
112
+ </div>
113
+
114
+ <component
115
+ :is="tag"
116
+ v-else
117
+ :to="readMorePath"
118
+ :href="readMorePath"
119
+ class="tw-flex hover:tw-no-underline focus:tw-no-underline tw-justify-center"
120
+ aria-label="Loan tag"
121
+ @click.native="clickReadMore('Tag', $event)"
122
+ >
123
+ <kv-loan-callouts
124
+ :callouts="loanCallouts"
125
+ :add-bg-color="false"
126
+ class="loan-callouts"
127
+ />
128
+ </component>
129
+
130
+ <component
131
+ :is="tag"
132
+ :to="readMorePath"
133
+ :href="readMorePath"
134
+ class="loan-card-use tw-text-primary"
135
+ aria-label="Loan use"
136
+ @click.native="clickReadMore('Use', $event)"
137
+ >
138
+ <!-- Loan use -->
139
+ <div
140
+ class="tw-pt-1 tw-px-1"
141
+ :class="{'tw-mb-1.5': !isLoading}"
142
+ >
143
+ <div
144
+ v-if="isLoading"
145
+ class="tw-w-full"
146
+ style="height: 5.5rem;"
147
+ >
148
+ <div
149
+ v-for="(_n, i) in [...Array(3)]"
150
+ :key="i"
151
+ class="tw-h-2 tw-mb-1"
152
+ >
153
+ <kv-loading-placeholder />
154
+ </div>
155
+ </div>
156
+ <div v-else>
157
+ <kv-loan-use
158
+ :use="loanUse"
159
+ :loan-amount="loanAmount"
160
+ :status="loanStatus"
161
+ :borrower-count="loanBorrowerCount"
162
+ :name="borrowerName"
163
+ :distribution-model="distributionModel"
164
+ hide-loan-amount
165
+ class="!tw-line-clamp-3"
166
+ />
167
+ </div>
168
+ </div>
169
+ </component>
170
+ </div>
171
+ </div>
172
+
173
+ <div
174
+ class="tw-px-1 tw-grow"
175
+ >
176
+ <!-- Fundraising -->
177
+ <div
178
+ v-if="!hasProgressData"
179
+ class="tw-w-full tw-pr-1"
180
+ >
181
+ <div class="tw-flex tw-justify-between">
182
+ <kv-loading-placeholder
183
+ class="tw-mb-0.5"
184
+ :style="{ width: '20%', height: '1.3rem' }"
185
+ />
186
+ <kv-loading-placeholder
187
+ class="tw-mb-0.5"
188
+ :style="{ width: '20%', height: '1.3rem' }"
189
+ />
190
+ </div>
191
+
192
+ <kv-loading-placeholder
193
+ class="tw-rounded"
194
+ :style="{ width: '100%', height: '0.5rem' }"
195
+ />
196
+ </div>
197
+
198
+ <div>
199
+ <component
200
+ :is="tag"
201
+ v-if="unreservedAmount > 0"
202
+ :to="readMorePath"
203
+ :href="readMorePath"
204
+ class="loan-card-progress tw-mt-1"
205
+ aria-label="Loan progress"
206
+ @click.native="clickReadMore('Progress', $event)"
207
+ >
208
+ <kv-loan-progress-group
209
+ id="loanProgress"
210
+ :money-left="`${unreservedAmount}`"
211
+ :amount-goal="`${loanAmount}`"
212
+ :progress-percent="fundraisingPercent"
213
+ class="tw-text-secondary"
214
+ />
215
+ </component>
216
+ </div>
217
+
218
+ <!-- Loan Match -->
219
+ <kv-loading-placeholder
220
+ v-if="isLoading"
221
+ class="tw-rounded tw-mx-auto tw-mt-1"
222
+ :style="{ width: '9rem', height: '1rem' }"
223
+ />
224
+
225
+ <div class="tw-pb-2.5">
226
+ <kv-loan-tag
227
+ v-if="matchingText"
228
+ :loan="loan"
229
+ variation="matched-loan"
230
+ class="tw-text-center !tw-text-brand"
231
+ />
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </template>
236
+
237
+ <script>
238
+ import numeral from 'numeral';
239
+ import { loanCardComputedProperties, loanCardMethods } from '../utils/loanCard';
240
+
241
+ import KvLoanUse from './KvLoanUse.vue';
242
+ import KvBorrowerImage from './KvBorrowerImage.vue';
243
+ import KvLoanProgressGroup from './KvLoanProgressGroup.vue';
244
+ import KvLoanCallouts from './KvLoanCallouts.vue';
245
+ import KvLoanTag from './KvLoanTag.vue';
246
+ import KvMaterialIcon from './KvMaterialIcon.vue';
247
+ import KvLoadingPlaceholder from './KvLoadingPlaceholder.vue';
248
+ import KvFlag from './KvFlag.vue';
249
+
250
+ export default {
251
+ name: 'KvIntroductionLoanCard',
252
+ components: {
253
+ KvBorrowerImage,
254
+ KvLoadingPlaceholder,
255
+ KvLoanUse,
256
+ KvLoanProgressGroup,
257
+ KvMaterialIcon,
258
+ KvLoanTag,
259
+ KvLoanCallouts,
260
+ KvFlag,
261
+ },
262
+ props: {
263
+ loanId: {
264
+ type: Number,
265
+ default: undefined,
266
+ },
267
+ loan: {
268
+ type: Object,
269
+ default: null,
270
+ },
271
+ customLoanDetails: {
272
+ type: Boolean,
273
+ default: false,
274
+ },
275
+ categoryPageName: {
276
+ type: String,
277
+ default: '',
278
+ },
279
+ customCallouts: {
280
+ type: Array,
281
+ default: () => ([]),
282
+ },
283
+ kvTrackFunction: {
284
+ type: Function,
285
+ required: true,
286
+ },
287
+ photoPath: {
288
+ type: String,
289
+ required: true,
290
+ },
291
+ errorMsg: {
292
+ type: String,
293
+ default: '',
294
+ },
295
+ externalLinks: {
296
+ type: Boolean,
297
+ default: false,
298
+ },
299
+ route: {
300
+ type: Object,
301
+ default: undefined,
302
+ },
303
+ },
304
+ setup(props, { emit }) {
305
+ const {
306
+ allDataLoaded,
307
+ borrowerName,
308
+ city,
309
+ countryName,
310
+ countryCode,
311
+ distributionModel,
312
+ formattedLocation,
313
+ fundraisingPercent,
314
+ hasProgressData,
315
+ imageHash,
316
+ isLoading,
317
+ loanAmount,
318
+ loanBorrowerCount,
319
+ loanCallouts,
320
+ loanStatus,
321
+ loanUse,
322
+ mdiMapMarker,
323
+ readMorePath,
324
+ state,
325
+ tag,
326
+ unreservedAmount,
327
+ } = loanCardComputedProperties(props);
328
+
329
+ const {
330
+ clickReadMore,
331
+ } = loanCardMethods(props, emit);
332
+
333
+ return {
334
+ allDataLoaded,
335
+ borrowerName,
336
+ city,
337
+ countryName,
338
+ countryCode,
339
+ distributionModel,
340
+ formattedLocation,
341
+ fundraisingPercent,
342
+ hasProgressData,
343
+ imageHash,
344
+ isLoading,
345
+ loanAmount,
346
+ loanBorrowerCount,
347
+ loanCallouts,
348
+ loanStatus,
349
+ loanUse,
350
+ mdiMapMarker,
351
+ readMorePath,
352
+ state,
353
+ tag,
354
+ unreservedAmount,
355
+ clickReadMore,
356
+ };
357
+ },
358
+ computed: {
359
+ imageAspectRatio() {
360
+ return 178 / 328;
361
+ },
362
+ imageDefaultWidth() {
363
+ return 336;
364
+ },
365
+ imageSizes() {
366
+ return [
367
+ { width: this.imageDefaultWidth, viewSize: 1024 },
368
+ { width: this.imageDefaultWidth, viewSize: 768 },
369
+ { width: 416, viewSize: 480 },
370
+ { width: 374, viewSize: 414 },
371
+ { width: 335, viewSize: 375 },
372
+ ];
373
+ },
374
+ lendersNumber() {
375
+ return this.loan?.lenders?.totalCount ?? 0;
376
+ },
377
+ amountLent() {
378
+ const amount = this.loan?.loanFundraisingInfo?.fundedAmount ?? 0;
379
+ return numeral(parseFloat(amount)).format('$0,0');
380
+ },
381
+ matchingText() {
382
+ return this.loan?.matchingText ?? '';
383
+ },
384
+ },
385
+ };
386
+ </script>
387
+
388
+ <style lang="postcss" scoped>
389
+ .card-container {
390
+ @apply tw-flex tw-flex-col tw-bg-white tw-rounded tw-w-full tw-pb-1;
391
+ height: 415px;
392
+ }
393
+ @screen md {
394
+ .card-container {
395
+ height: 423px;
396
+ }
397
+ }
398
+ .loan-callouts >>> span {
399
+ @apply !tw-bg-transparent tw-text-brand;
400
+ }
401
+ .loan-card-use:hover,
402
+ .loan-card-use:focus {
403
+ @apply tw-text-primary;
404
+ }
405
+ .loan-card-active-hover:hover .loan-card-use, .loan-card-active-hover:hover .loan-card-name {
406
+ @apply tw-underline;
407
+ }
408
+ .loan-card-progress:hover,
409
+ .loan-card-progress:focus {
410
+ @apply tw-no-underline;
411
+ }
412
+ .borrower-image >>> img {
413
+ @apply tw-object-cover;
414
+ }
415
+ .loan-card-name {
416
+ @apply tw-pt-1 tw-px-3 tw-text-ellipsis tw-overflow-hidden tw-line-clamp-1 tw-cursor-pointer;
417
+ }
418
+ </style>
@@ -1,11 +1,19 @@
1
1
  <template>
2
2
  <figure>
3
- <h4
4
- class="tw-lowercase tw-mb-0.5"
5
- :class="{ 'progress-group-amount-low': amountLow }"
6
- >
7
- {{ fundingText }}
8
- </h4>
3
+ <div :class="{'tw-flex tw-justify-between': amountGoal}">
4
+ <h4
5
+ class="tw-lowercase tw-mb-0.5"
6
+ :class="{ 'progress-group-amount-low': amountLow}"
7
+ >
8
+ {{ fundingText }}
9
+ </h4>
10
+ <h4
11
+ v-if="amountGoal"
12
+ class="tw-lowercase tw-mb-0.5"
13
+ >
14
+ {{ goalText }}
15
+ </h4>
16
+ </div>
9
17
  <kv-progress-bar
10
18
  aria-label="Percent the loan has funded"
11
19
  :value="progressPercent * 100"
@@ -31,6 +39,10 @@ export default {
31
39
  type: Number,
32
40
  default: 0,
33
41
  },
42
+ amountGoal: {
43
+ type: String,
44
+ default: '',
45
+ },
34
46
  },
35
47
  computed: {
36
48
  numeralLeft() {
@@ -45,6 +57,14 @@ export default {
45
57
  const exclamationMark = this.amountLow ? '!' : '';
46
58
  return `${formattedMoneyLeft} to go${exclamationMark}`;
47
59
  },
60
+ numeralGoal() {
61
+ return numeral(this.amountGoal);
62
+ },
63
+ goalText() {
64
+ if (!this.numeralGoal.value()) return '';
65
+ const formattedGoal = this.numeralGoal.format('$0,0[.]00');
66
+ return `${formattedGoal} goal`;
67
+ },
48
68
  },
49
69
  };
50
70
  </script>
package/vue/KvLoanUse.vue CHANGED
@@ -46,6 +46,10 @@ export default {
46
46
  type: String,
47
47
  default: '',
48
48
  },
49
+ hideLoanAmount: {
50
+ type: Boolean,
51
+ default: false,
52
+ },
49
53
  },
50
54
  computed: {
51
55
  helpLanguage() {
@@ -67,6 +71,12 @@ export default {
67
71
  return 'For the borrower\'s privacy, this loan has been made anonymous.';
68
72
  }
69
73
 
74
+ if (this.hideLoanAmount) {
75
+ return `Help <span class="data-hj-suppress">${this.name}</span> `
76
+ + `${this.use.charAt(0).toLowerCase() + this.use.slice(1)} `
77
+ + `${this.whySpecialSentence}`;
78
+ }
79
+
70
80
  const isGroup = this.borrowerCount > 1;
71
81
 
72
82
  return `${numeral(this.loanAmount).format('$0,0')} `
@@ -0,0 +1,36 @@
1
+ import KvFlag from '../KvFlag.vue';
2
+
3
+ export default {
4
+ title: 'Components/KvFlag',
5
+ component: KvFlag,
6
+ };
7
+
8
+ const story = (args) => {
9
+ const template = (templateArgs, { argTypes }) => ({
10
+ props: Object.keys(argTypes),
11
+ components: { KvFlag },
12
+ setup() { return { args: templateArgs }; },
13
+ template: `
14
+ <div style="width: 100px; height: 100px;">
15
+ <KvFlag v-bind="args" />
16
+ </div>
17
+ `,
18
+ });
19
+ template.args = args;
20
+ return template;
21
+ };
22
+
23
+ // SVG based on the country code
24
+ export const InlineSvg = story({ country: 'TO' });
25
+ // SVG based on the country code with custom width
26
+ export const InlineSvgCustomWidth = story({ country: 'DE', widthOverride: '40px' });
27
+
28
+ // SVG Sqaure based on the country code
29
+ export const SquareInlineSvg = story({ country: 'ME', aspectRatio: '1x1', showName: true });
30
+ // SVG Sqaure based on the country code with custom width
31
+ export const SquareInlineSvgCustomWidth = story({
32
+ country: 'SA',
33
+ inlineSvg: true,
34
+ widthOverride: '40px',
35
+ aspectRatio: '1x1',
36
+ });
@@ -0,0 +1,132 @@
1
+ import KvIntroductionLoanCard from '../KvIntroductionLoanCard.vue';
2
+
3
+ export default {
4
+ title: 'KvIntroductionLoanCard',
5
+ component: KvIntroductionLoanCard,
6
+ };
7
+
8
+ const story = (args) => {
9
+ const template = (_args, { argTypes }) => ({
10
+ props: Object.keys(argTypes),
11
+ components: { KvIntroductionLoanCard },
12
+ template: `
13
+ <div style="width: 600px;">
14
+ <kv-introduction-loan-card
15
+ :loanId="loanId"
16
+ :loan="loan"
17
+ :category-page-name="categoryPageName"
18
+ :custom-callouts="customCallouts"
19
+ :kv-track-function="kvTrackFunction"
20
+ :photo-path="photoPath"
21
+ @show-loan-details="showLoanDetails"
22
+ />
23
+ </div>
24
+ `,
25
+ methods: {
26
+ showLoanDetails() {
27
+ console.log('show-loan-details');
28
+ },
29
+ },
30
+ });
31
+ template.args = args;
32
+ return template;
33
+ };
34
+
35
+ const nextWeek = new Date();
36
+ nextWeek.setDate(new Date().getDate() + 7);
37
+
38
+ const loan = {
39
+ id: 1,
40
+ name: 'Alan',
41
+ geocode: {
42
+ city: 'Lyantonde',
43
+ state: 'Central Region',
44
+ country: {
45
+ isoCode: 'UG',
46
+ name: 'Uganda',
47
+ region: 'Africa',
48
+ __typename: 'Country',
49
+ },
50
+ __typename: 'Geocode',
51
+ },
52
+ image: { hash: '9673d0722a7675b9b8d11f90849d9b44' },
53
+ fundraisingPercent: 0.5,
54
+ unreservedAmount: '500.00',
55
+ use: 'to purchase heifers to increase headcount of cattle and sales of organic milk. The profits from the loan will be used wisely.',
56
+ status: 'fundraising',
57
+ loanAmount: '1000.00',
58
+ borrowerCount: 1,
59
+ activity: {
60
+ id: 61,
61
+ name: 'Dairy',
62
+ __typename: 'Activity',
63
+ },
64
+ sector: {
65
+ id: 1,
66
+ name: 'Agriculture',
67
+ __typename: 'Sector',
68
+ },
69
+ plannedExpirationDate: nextWeek.toISOString(),
70
+ tags: [
71
+ 'user_favorite',
72
+ '#Woman-Owned Business',
73
+ '#Animals',
74
+ '#Repeat Borrower',
75
+ '#Supporting Family',
76
+ '#Eco-friendly',
77
+ '#Single parent',
78
+ ],
79
+ };
80
+
81
+ const kvTrackFunction = () => { };
82
+
83
+ const photoPath = 'https://www-kiva-org.freetls.fastly.net/img/';
84
+
85
+ export const Default = story({
86
+ loanId: loan.id,
87
+ loan: {
88
+ ...loan,
89
+ loanFundraisingInfo: {
90
+ fundedAmount: '200.00',
91
+ isExpiringSoon: false,
92
+ reservedAmount: '0.00',
93
+ },
94
+ },
95
+ kvTrackFunction,
96
+ photoPath,
97
+ });
98
+
99
+ export const Loading = story({
100
+ loanId: loan.id,
101
+ loan: undefined,
102
+ kvTrackFunction,
103
+ photoPath,
104
+ });
105
+
106
+ export const PartialLoading = story({
107
+ loanId: loan.id,
108
+ loan: {
109
+ ...loan,
110
+ unreservedAmount: undefined,
111
+ fundraisingPercent: undefined,
112
+ },
113
+ kvTrackFunction,
114
+ photoPath,
115
+ });
116
+
117
+ export const Matched = story({
118
+ loanId: loan.id,
119
+ loan: {
120
+ ...loan,
121
+ matchingText: 'Ebay',
122
+ matchRatio: 1,
123
+ loanFundraisingInfo: {
124
+ fundedAmount: '200.00',
125
+ isExpiringSoon: false,
126
+ reservedAmount: '0.00',
127
+ },
128
+ },
129
+ kvTrackFunction,
130
+ photoPath,
131
+ loanCallouts: [{ label: 'callout 1' }, { label: 'callout 2' }, { label: 'callout 3' }],
132
+ });