@kiva/kv-components 3.73.2 → 3.74.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,24 @@
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.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
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * adjusted comment ([e73e6a8](https://github.com/kiva/kv-ui-elements/commit/e73e6a842486ec5ce951a3130348cb1e3428288d))
12
+ * extracted CTA dropdown methods and added unit tests ([4ef99de](https://github.com/kiva/kv-ui-elements/commit/4ef99deb24399fcb619c41d20370ad79812f1b00))
13
+ * removed duplicate test ([838d6d4](https://github.com/kiva/kv-ui-elements/commit/838d6d48c85bbfd7759fd5266498219817e00cd7))
14
+
15
+
16
+ ### Features
17
+
18
+ * $1000 lend CTA options ([4f89352](https://github.com/kiva/kv-ui-elements/commit/4f8935237acb9c1f1655b77cc604fe68b21ab077))
19
+
20
+
21
+
22
+
23
+
6
24
  ## [3.73.2](https://github.com/kiva/kv-ui-elements/compare/@kiva/kv-components@3.73.1...@kiva/kv-components@3.73.2) (2024-04-23)
7
25
 
8
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kiva/kv-components",
3
- "version": "3.73.2",
3
+ "version": "3.74.0",
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": "9cd04b768af71aead30d08320229402bf3c79989"
78
+ "gitHead": "db1d9c79b08cf5489aa474fddaa610c365526ab7"
79
79
  }
@@ -2,6 +2,7 @@ import {
2
2
  isBetween25And50,
3
3
  isLessThan25,
4
4
  getLendCtaSelectedOption,
5
+ getDropdownPriceArray,
5
6
  ERL_COOKIE_NAME,
6
7
  TOP_UP_CAMPAIGN,
7
8
  BASE_CAMPAIGN,
@@ -310,4 +311,127 @@ describe('loanUtils', () => {
310
311
  expect(mockCookieStoreSet).toHaveBeenCalledTimes(0);
311
312
  });
312
313
  });
314
+
315
+ describe('getDropdownPriceArray', () => {
316
+ it('should return less than 25', () => {
317
+ const result = getDropdownPriceArray('15.00', true, 15);
318
+
319
+ expect(result).toEqual(['15']);
320
+ });
321
+
322
+ it('should return non-25 increments', () => {
323
+ const result = getDropdownPriceArray('30.00', true);
324
+
325
+ expect(result).toEqual(['25', '30']);
326
+ });
327
+
328
+ it('should return dropdown values', () => {
329
+ const result = getDropdownPriceArray('100.00');
330
+
331
+ expect(result).toEqual(['25', '50', '75', '100']);
332
+ });
333
+
334
+ it('should return huge dropdown values between 500 and 1000', () => {
335
+ const result = getDropdownPriceArray('650.00', false, 25, false, true, false);
336
+
337
+ expect(result).toEqual([
338
+ '25',
339
+ '50',
340
+ '75',
341
+ '100',
342
+ '125',
343
+ '150',
344
+ '175',
345
+ '200',
346
+ '225',
347
+ '250',
348
+ '275',
349
+ '300',
350
+ '325',
351
+ '350',
352
+ '375',
353
+ '400',
354
+ '425',
355
+ '450',
356
+ '475',
357
+ '500',
358
+ '600',
359
+ '650',
360
+ ]);
361
+ });
362
+
363
+ it('should return huge dropdown values up to 10,000', () => {
364
+ const result = getDropdownPriceArray('11000.00', false, 25, false, true, false);
365
+
366
+ expect(result).toEqual([
367
+ '25',
368
+ '50',
369
+ '75',
370
+ '100',
371
+ '125',
372
+ '150',
373
+ '175',
374
+ '200',
375
+ '225',
376
+ '250',
377
+ '275',
378
+ '300',
379
+ '325',
380
+ '350',
381
+ '375',
382
+ '400',
383
+ '425',
384
+ '450',
385
+ '475',
386
+ '500',
387
+ '600',
388
+ '700',
389
+ '800',
390
+ '900',
391
+ '1,000',
392
+ '2,000',
393
+ '3,000',
394
+ '4,000',
395
+ '5,000',
396
+ '6,000',
397
+ '7,000',
398
+ '8,000',
399
+ '9,000',
400
+ '10,000',
401
+ ]);
402
+ });
403
+
404
+ it('should return not huge dropdown values for visitor', () => {
405
+ const result = getDropdownPriceArray('650.00', false, 25, false, true, true);
406
+
407
+ expect(result).toEqual([
408
+ '25',
409
+ '50',
410
+ '75',
411
+ '100',
412
+ '125',
413
+ '150',
414
+ '175',
415
+ '200',
416
+ '225',
417
+ '250',
418
+ '275',
419
+ '300',
420
+ '325',
421
+ '350',
422
+ '375',
423
+ '400',
424
+ '425',
425
+ '450',
426
+ '475',
427
+ '500',
428
+ ]);
429
+ });
430
+
431
+ it('should return 5 dollar notes', () => {
432
+ const result = getDropdownPriceArray('30.00', true, 25, true);
433
+
434
+ expect(result).toEqual(['5', '10', '15', '20', '25', '30']);
435
+ });
436
+ });
313
437
  });
@@ -1,3 +1,5 @@
1
+ import numeral from 'numeral';
2
+
1
3
  export const ERL_COOKIE_NAME = 'kverlfivedollarnotes';
2
4
  export const TOP_UP_CAMPAIGN = 'TOPUP-VB-BALANCE-MPV1';
3
5
  export const BASE_CAMPAIGN = 'BASE-VB_BALANCE_MPV1';
@@ -109,3 +111,99 @@ export function getLendCtaSelectedOption(
109
111
  // $25 is the fallback default selected option
110
112
  return '25';
111
113
  }
114
+
115
+ function buildHugePriceArray(amountLeft) {
116
+ const priceArray = [];
117
+
118
+ // Add $100 options up to $1,000
119
+ let minAmount = 100;
120
+ let limitAmount = amountLeft > 1000 ? 1000 : amountLeft;
121
+ let optionCount = limitAmount / minAmount;
122
+ for (let i = 1; i <= optionCount; i += 1) {
123
+ const price = minAmount * i + 500;
124
+ if (price > limitAmount) break;
125
+ priceArray.push(numeral(price).format('0,0'));
126
+ }
127
+
128
+ // Add $1000 options up to $10,000
129
+ minAmount = 1000;
130
+ limitAmount = amountLeft > 10000 ? 10000 : amountLeft;
131
+ optionCount = limitAmount / minAmount;
132
+ for (let i = 1; i <= optionCount; i += 1) {
133
+ const price = minAmount * i + 1000;
134
+ if (price > limitAmount) break;
135
+ priceArray.push(numeral(price).format('0,0'));
136
+ }
137
+
138
+ // Ensure final option is added
139
+ if (!priceArray.includes(numeral(limitAmount).format('0,0'))) {
140
+ priceArray.push(numeral(limitAmount).format('0,0'));
141
+ }
142
+
143
+ return priceArray;
144
+ }
145
+
146
+ function build5DollarsPriceArray(amountLeft) {
147
+ const limit5Notes = amountLeft < 50 ? amountLeft : 50;
148
+ const numberOf5 = limit5Notes / 5;
149
+ const numberOf25 = Math.ceil((amountLeft - limit5Notes) / 25) + 1;
150
+ const priceArray = [];
151
+ for (let i = 1; i <= numberOf5; i += 1) {
152
+ priceArray.push(numeral(5 * i).format('0,0'));
153
+ }
154
+ if (amountLeft > limit5Notes) {
155
+ for (let i = 3; i <= numberOf25; i += 1) {
156
+ priceArray.push(numeral(25 * i).format('0,0'));
157
+ }
158
+ }
159
+ return priceArray;
160
+ }
161
+
162
+ function buildPriceArray(amountLeft, minAmount) {
163
+ // Get count of shares based on available remaining amount
164
+ const optionCount = amountLeft / minAmount;
165
+ // Convert this to formatted array for our select element
166
+ const priceArray = []; // ex. priceArray = ['25', '50', '75']
167
+ for (let i = 1; i <= optionCount; i += 1) {
168
+ priceArray.push(numeral(minAmount * i).format('0,0'));
169
+ }
170
+ return priceArray;
171
+ }
172
+
173
+ /**
174
+ * Gets the dropdown price values for the lend CTA
175
+ *
176
+ * @param {string} unreservedAmount The unreserved amount of the loan
177
+ * @param {boolean} isCompleteLoanActive Whether to include option that would complete loan
178
+ * @param {number} minAmount The min amount to show in the dropdown
179
+ * @param {boolean} enableFiveDollarsNotes Whether five dollar notes are enabled
180
+ * @param {boolean} enableHugeAmount Whether huge loan amounts are enabled
181
+ * @param {boolean} isVisitor Whether the current user is a visitor
182
+ * @param {boolean} inPfp Whether the loan is in PFP
183
+ * @returns {string[]} Price value array for the CTA dropdown
184
+ */
185
+ export function getDropdownPriceArray(
186
+ unreservedAmount,
187
+ isCompleteLoanActive = false,
188
+ minAmount = 25,
189
+ enableFiveDollarsNotes = false,
190
+ enableHugeAmount = false,
191
+ isVisitor = true,
192
+ inPfp = false,
193
+ ) {
194
+ const parsedAmountLeft = parseFloat(unreservedAmount);
195
+ let priceArray = (enableFiveDollarsNotes && !inPfp)
196
+ ? build5DollarsPriceArray(parsedAmountLeft).slice(0, 28)
197
+ : buildPriceArray(parsedAmountLeft, minAmount).slice(0, 20);
198
+
199
+ if (enableHugeAmount && parsedAmountLeft > 500 && !isVisitor) {
200
+ const hugePriceArray = buildHugePriceArray(parsedAmountLeft);
201
+ priceArray = priceArray.concat(hugePriceArray);
202
+ }
203
+
204
+ if (isCompleteLoanActive && !priceArray.includes(Number(unreservedAmount).toFixed())) {
205
+ priceArray.push(Number(unreservedAmount).toFixed());
206
+ }
207
+
208
+ return priceArray;
209
+ }
package/vue/KvLendCta.vue CHANGED
@@ -126,13 +126,12 @@
126
126
  </template>
127
127
 
128
128
  <script>
129
- import numeral from 'numeral';
130
129
  import { mdiChevronRight } from '@mdi/js';
131
130
  import KvLendAmountButton from './KvLendAmountButton.vue';
132
131
  import KvUiSelect from './KvSelect.vue';
133
132
  import KvUiButton from './KvButton.vue';
134
133
  import KvMaterialIcon from './KvMaterialIcon.vue';
135
- import { getLendCtaSelectedOption } from '../utils/loanUtils';
134
+ import { getLendCtaSelectedOption, getDropdownPriceArray } from '../utils/loanUtils';
136
135
 
137
136
  export default {
138
137
  name: 'KvLendCta',
@@ -251,15 +250,14 @@ export default {
251
250
  // If we wanted to show this interface on loans with less than 25 remaining they would see the selector
252
251
  const minAmount = parseFloat(this.unreservedAmount < 25 ? this.minNoteSize : 25);
253
252
  // Limit price options
254
- const priceArray = this.getDropdownPriceArray(
253
+ return getDropdownPriceArray(
255
254
  this.unreservedAmount,
255
+ this.isCompleteLoanActive,
256
256
  minAmount,
257
257
  this.enableFiveDollarsNotes,
258
+ this.enableHugeAmount,
259
+ this.isVisitor,
258
260
  );
259
- if (this.isCompleteLoanActive && !priceArray.includes(Number(this.unreservedAmount).toFixed())) {
260
- priceArray.push(Number(this.unreservedAmount).toFixed());
261
- }
262
- return priceArray;
263
261
  },
264
262
  ctaButtonText() {
265
263
  if (this.isCompleteLoanActive) {
@@ -403,63 +401,6 @@ export default {
403
401
  this.loanId,
404
402
  );
405
403
  },
406
- build5DollarsPriceArray(amountLeft) {
407
- const limit5Notes = amountLeft < 50 ? amountLeft : 50;
408
- const numberOf5 = limit5Notes / 5;
409
- const numberOf25 = Math.ceil((amountLeft - limit5Notes) / 25) + 1;
410
- const priceArray = [];
411
- for (let i = 1; i <= numberOf5; i += 1) {
412
- priceArray.push(numeral(5 * i).format('0,0'));
413
- }
414
- if (amountLeft > limit5Notes) {
415
- for (let i = 3; i <= numberOf25; i += 1) {
416
- priceArray.push(numeral(25 * i).format('0,0'));
417
- }
418
- }
419
- return priceArray;
420
- },
421
- buildPriceArray(amountLeft, minAmount) {
422
- // get count of shares based on available remaining amount.
423
- const N = amountLeft / minAmount;
424
- // convert this to formatted array for our select element
425
- const priceArray = []; // ex. priceArray = ['25', '50', '75']
426
- for (let i = 1; i <= N; i += 1) {
427
- priceArray.push(numeral(minAmount * i).format('0,0'));
428
- }
429
- return priceArray;
430
- },
431
- buildHugePriceArray(amountLeft) {
432
- const minAmount = 100;
433
- const limitAmount = amountLeft > 1000 ? 1000 : amountLeft;
434
- const N = limitAmount / minAmount;
435
-
436
- const priceArray = [];
437
- for (let i = 1; i <= N; i += 1) {
438
- const price = minAmount * i + 500;
439
- if (price > limitAmount) break;
440
- priceArray.push(numeral(price).format('0,0'));
441
- }
442
-
443
- if (!priceArray.includes(numeral(limitAmount).format('0,0'))) {
444
- priceArray.push(numeral(limitAmount).format('0,0'));
445
- }
446
-
447
- return priceArray;
448
- },
449
- getDropdownPriceArray(unreservedAmount, minAmount, enableFiveDollarsNotes, inPfp = false) {
450
- const parsedAmountLeft = parseFloat(unreservedAmount);
451
- let combinedPricesArray = [];
452
- const priceArray = (enableFiveDollarsNotes && !inPfp)
453
- ? this.build5DollarsPriceArray(parsedAmountLeft).slice(0, 28)
454
- : this.buildPriceArray(parsedAmountLeft, minAmount).slice(0, 20);
455
-
456
- const showHugeAmount = this.enableHugeAmount && parsedAmountLeft > 500 && !this.isVisitor;
457
- if (showHugeAmount) {
458
- const hugePriceArray = this.buildHugePriceArray(parsedAmountLeft);
459
- combinedPricesArray = priceArray.concat(hugePriceArray);
460
- }
461
- return showHugeAmount ? combinedPricesArray : priceArray;
462
- },
463
404
  },
464
405
  };
465
406
 
@@ -70,7 +70,7 @@ export const Dropdown = story({
70
70
  kvTrackFunction,
71
71
  });
72
72
 
73
- export const HugeLentAmount = story({
73
+ export const HugeAmount = story({
74
74
  isLoading: false,
75
75
  loan: {
76
76
  id: 1,
@@ -81,7 +81,7 @@ export const HugeLentAmount = story({
81
81
  isVisitor: false,
82
82
  });
83
83
 
84
- export const Between500and1000 = story({
84
+ export const HugeAmountUnder1000 = story({
85
85
  isLoading: false,
86
86
  loan: {
87
87
  id: 1,