@alma/widgets 2.2.10 → 2.3.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.
@@ -1506,7 +1506,7 @@ var messagesDE = {
1506
1506
  "payment-plan-strings.deferred": "{totalAmount} zu zahlen am {dueDate}",
1507
1507
  "payment-plan-strings.ineligible-greater-than-max": "Bis zu {maxAmount}",
1508
1508
  "payment-plan-strings.ineligible-lower-than-min": "Ab {minAmount}",
1509
- "payment-plan-strings.multiple-installments": "{firstInstallmentAmount} dann {numberOfRemainingInstallments} x {othersInstallmentAmount}",
1509
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} dann {numberOfRemainingInstallments} x {othersInstallmentAmount}} other {{firstInstallmentAmount} dann {numberOfRemainingInstallments} x {othersInstallmentAmount}}}",
1510
1510
  "payment-plan-strings.multiple-installments-same-amount": "{installmentsCount} x {totalAmount}",
1511
1511
  "payment-plan-strings.no-fee": "(gebührenfrei)"
1512
1512
  };
@@ -1528,7 +1528,7 @@ var messagesEN = {
1528
1528
  "payment-plan-strings.deferred": "{totalAmount} to be paid on {dueDate}",
1529
1529
  "payment-plan-strings.ineligible-greater-than-max": "Until {maxAmount}",
1530
1530
  "payment-plan-strings.ineligible-lower-than-min": "From {minAmount}",
1531
- "payment-plan-strings.multiple-installments": "{firstInstallmentAmount} then {numberOfRemainingInstallments} x {othersInstallmentAmount}",
1531
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} then {numberOfRemainingInstallments} x {othersInstallmentAmount}} other {{firstInstallmentAmount} then {numberOfRemainingInstallments} x {othersInstallmentAmount}}}",
1532
1532
  "payment-plan-strings.multiple-installments-same-amount": "{installmentsCount} x {totalAmount}",
1533
1533
  "payment-plan-strings.no-fee": "(free of charge)"
1534
1534
  };
@@ -1550,7 +1550,7 @@ var messagesES = {
1550
1550
  "payment-plan-strings.deferred": "{totalAmount} a pagar el {dueDate}",
1551
1551
  "payment-plan-strings.ineligible-greater-than-max": "Hasta {maxAmount}",
1552
1552
  "payment-plan-strings.ineligible-lower-than-min": "Desde {minAmount}",
1553
- "payment-plan-strings.multiple-installments": "{firstInstallmentAmount} hoy, después {numberOfRemainingInstallments, plural, one {# mensualidad} other {# mensualidades}} de {othersInstallmentAmount}",
1553
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} hoy, después {numberOfRemainingInstallments} mensualidad de {othersInstallmentAmount}} other {{firstInstallmentAmount} hoy, después {numberOfRemainingInstallments} de {othersInstallmentAmount} mensualidades }}",
1554
1554
  "payment-plan-strings.multiple-installments-same-amount": "{installmentsCount} plazos de {totalAmount}",
1555
1555
  "payment-plan-strings.no-fee": "(sin intereses)"
1556
1556
  };
@@ -1572,7 +1572,7 @@ var messagesFR = {
1572
1572
  "payment-plan-strings.deferred": "{totalAmount} à payer le {dueDate}",
1573
1573
  "payment-plan-strings.ineligible-greater-than-max": "Jusqu'à {maxAmount}",
1574
1574
  "payment-plan-strings.ineligible-lower-than-min": "À partir de {minAmount}",
1575
- "payment-plan-strings.multiple-installments": "{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}",
1575
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}} other {{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}}}",
1576
1576
  "payment-plan-strings.multiple-installments-same-amount": "{installmentsCount} x {totalAmount}",
1577
1577
  "payment-plan-strings.no-fee": "(sans frais)"
1578
1578
  };
@@ -1594,7 +1594,7 @@ var messagesIT = {
1594
1594
  "payment-plan-strings.deferred": "{totalAmount} da pagare il {dueDate}",
1595
1595
  "payment-plan-strings.ineligible-greater-than-max": "Disponibile fino a {maxAmount}",
1596
1596
  "payment-plan-strings.ineligible-lower-than-min": "Pagamento rateale disponibile a partire da {minAmount}",
1597
- "payment-plan-strings.multiple-installments": "Oggi paghi {firstInstallmentAmount} poi {numberOfRemainingInstallments} rate mensili di {othersInstallmentAmount}",
1597
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {Oggi paghi {firstInstallmentAmount} poi {numberOfRemainingInstallments} rata mensile di {othersInstallmentAmount}} other {Oggi paghi {firstInstallmentAmount} poi {numberOfRemainingInstallments} rate mensili di {othersInstallmentAmount}}}",
1598
1598
  "payment-plan-strings.multiple-installments-same-amount": "In {installmentsCount} rate mensili di {totalAmount}",
1599
1599
  "payment-plan-strings.no-fee": "(senza interessi)"
1600
1600
  };
@@ -1616,7 +1616,7 @@ var messagesNL = {
1616
1616
  "payment-plan-strings.deferred": "{totalAmount} te betalen op {dueDate}",
1617
1617
  "payment-plan-strings.ineligible-greater-than-max": "Tot {maxAmount}",
1618
1618
  "payment-plan-strings.ineligible-lower-than-min": "Van {minAmount}",
1619
- "payment-plan-strings.multiple-installments": "{firstInstallmentAmount} dan {numberOfRemainingInstallments} x {othersInstallmentAmount}",
1619
+ "payment-plan-strings.multiple-installments": "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} dan {numberOfRemainingInstallments} x {othersInstallmentAmount}} other {{firstInstallmentAmount} dan {numberOfRemainingInstallments} x {othersInstallmentAmount}}}",
1620
1620
  "payment-plan-strings.multiple-installments-same-amount": "{installmentsCount} x {totalAmount}",
1621
1621
  "payment-plan-strings.no-fee": "(gratis)"
1622
1622
  };
@@ -1744,8 +1744,8 @@ const useFetchEligibility = (purchaseAmount, {
1744
1744
  }, {
1745
1745
  Authorization: `Alma-Merchant-Auth ${merchantId}`
1746
1746
  }).then(res => {
1747
- setStatus(apiStatus.SUCCESS);
1748
1747
  setEligibility(res);
1748
+ setStatus(apiStatus.SUCCESS);
1749
1749
  }).catch(() => {
1750
1750
  setStatus(apiStatus.FAILED);
1751
1751
  });
@@ -1927,7 +1927,7 @@ const paymentPlanInfoText = payment => {
1927
1927
 
1928
1928
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FormattedMessage, {
1929
1929
  id: "payment-plan-strings.multiple-installments",
1930
- defaultMessage: "{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}",
1930
+ defaultMessage: "{numberOfRemainingInstallments, plural, one {{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}} other {{firstInstallmentAmount} puis {numberOfRemainingInstallments} x {othersInstallmentAmount}}}",
1931
1931
  values: {
1932
1932
  firstInstallmentAmount: /*#__PURE__*/React.createElement(FormattedNumber, {
1933
1933
  value: priceFromCents(payment.payment_plan[0].total_amount),
@@ -2257,37 +2257,106 @@ const useButtonAnimation = (iterateValues, transitionDelay) => {
2257
2257
  };
2258
2258
  };
2259
2259
 
2260
- var s$b = {"widgetButton":"_TSkFv","logo":"_LJ4nZ","primaryContainer":"_bMClc","paymentPlans":"_17c_S","plan":"_2Kqjn","active":"_3dG_J","notEligible":"_3O1bg","info":"_25GrF","loader":"_30j1O","error":"_R0YlN","errorText":"_2kGhu","errorButton":"_73d_Y","pending":"_1ZDMS"};
2260
+ /**
2261
+ * It returns the **index** of the **first eligible plan** that matches the default installments count
2262
+ *
2263
+ * @param {number | number[]} suggestedPaymentPlan
2264
+ * @param {EligibilityPlan[]} eligibilityPlans
2265
+ * @returns number (index of the first eligible plan that matches the default installments count)
2266
+ */
2267
+ const getIndexOfActivePlan = ({
2268
+ suggestedPaymentPlan,
2269
+ eligibilityPlans
2270
+ }) => {
2271
+ const suggestedPaymentPlanArray = Array.isArray(suggestedPaymentPlan) ? suggestedPaymentPlan : [suggestedPaymentPlan];
2272
+
2273
+ for (const index in suggestedPaymentPlanArray) {
2274
+ const installmentsCount = suggestedPaymentPlanArray[index];
2275
+ const planFound = eligibilityPlans.findIndex(plan => {
2276
+ return plan.installments_count === installmentsCount && plan.eligible;
2277
+ });
2278
+
2279
+ if (planFound !== -1) {
2280
+ return planFound;
2281
+ }
2282
+ }
2283
+
2284
+ return 0;
2285
+ };
2286
+
2287
+ var s$b = {"widgetButton":"_TSkFv","logo":"_LJ4nZ","primaryContainer":"_bMClc","paymentPlans":"_17c_S","plan":"_2Kqjn","active":"_3dG_J","notEligible":"_3O1bg","info":"_25GrF","loader":"_30j1O","error":"_R0YlN","errorText":"_2kGhu","errorButton":"_73d_Y","pending":"_1ZDMS","clickable":"_UksZa","unClickable":"_1lr-q"};
2288
+
2289
+ const VERY_LONG_TIME_IN_MS = 1000 * 3600 * 24 * 365;
2290
+ const DEFAULT_TRANSITION_TIME = 5500;
2261
2291
 
2262
2292
  const PaymentPlanWidget = ({
2263
2293
  purchaseAmount,
2264
2294
  apiData,
2265
2295
  configPlans,
2266
2296
  transitionDelay,
2267
- hideIfNotEligible
2297
+ hideIfNotEligible,
2298
+ suggestedPaymentPlan
2268
2299
  }) => {
2269
2300
  const [eligibilityPlans, status] = useFetchEligibility(purchaseAmount, apiData, configPlans);
2270
2301
  const eligiblePlans = eligibilityPlans.filter(plan => plan.eligible);
2302
+ const activePlanIndex = getIndexOfActivePlan({
2303
+ eligibilityPlans,
2304
+ suggestedPaymentPlan: suggestedPaymentPlan != null ? suggestedPaymentPlan : 0
2305
+ });
2306
+ const isSuggestedPaymentPlanSpecified = suggestedPaymentPlan !== undefined; // 👈 The merchant decided to focus a tab and remove animated transition.
2307
+
2308
+ const isTransitionSpecified = transitionDelay !== undefined; // 👈 The merchant has specified a transition time
2309
+
2271
2310
  const [isOpen, setIsOpen] = useState(false);
2272
- const [initialPlanIndex, setInitialPlanIndex] = useState(0);
2273
2311
 
2274
2312
  const openModal = () => setIsOpen(true);
2275
2313
 
2276
2314
  const closeModal = () => setIsOpen(false);
2277
2315
 
2278
2316
  const eligiblePlanKeys = eligibilityPlans.reduce((acc, plan, index) => plan.eligible ? [...acc, index] : acc, []);
2317
+ /**
2318
+ * If merchand specify a suggestedPaymentPlan and no transition, we set a very long transition delay.
2319
+ * Otherwise, we set the transition delay specified by the merchant.
2320
+ * If none of those properties are specified, we set a default transition delay.
2321
+ * @returns
2322
+ */
2323
+
2324
+ const realTransitionTime = () => {
2325
+ if (isTransitionSpecified) {
2326
+ return transitionDelay != null ? transitionDelay : DEFAULT_TRANSITION_TIME;
2327
+ }
2328
+
2329
+ if (isSuggestedPaymentPlanSpecified) {
2330
+ return VERY_LONG_TIME_IN_MS;
2331
+ }
2332
+
2333
+ return DEFAULT_TRANSITION_TIME;
2334
+ };
2335
+
2279
2336
  const {
2280
2337
  current,
2281
2338
  onHover,
2282
2339
  onLeave
2283
- } = useButtonAnimation(eligiblePlanKeys, transitionDelay ? transitionDelay : 5500); // This hook is needed to update the initial plan index when useButtonAnimation
2284
- // updates the `current` value (i.e. without any hover / click callback).
2285
-
2340
+ } = useButtonAnimation(eligiblePlanKeys, realTransitionTime());
2286
2341
  useEffect(() => {
2287
- if (current !== initialPlanIndex) {
2288
- setInitialPlanIndex(current);
2342
+ // When API has given a response AND the marchand set an active plan by default.
2343
+ if (status === apiStatus.SUCCESS && isSuggestedPaymentPlanSpecified) {
2344
+ onHover(activePlanIndex); // We select the first active plan possible
2345
+
2346
+ onLeave(); // We need to call onLeave to reset the animation
2289
2347
  }
2290
- }, [current, initialPlanIndex]);
2348
+ }, [status]);
2349
+ /**
2350
+ * It takes a plan index and returns the index of that plan within the eligible plans
2351
+ *
2352
+ * @param {number} planIndex - The index of the plan that the user has selected.
2353
+ * @returns The index of the planKey in the eligiblePlanKeys array.
2354
+ */
2355
+
2356
+ const getIndexWithinEligiblePlans = planIndex => {
2357
+ const index = eligiblePlanKeys.findIndex(planKey => planKey === planIndex);
2358
+ return index === -1 ? 0 : index;
2359
+ };
2291
2360
 
2292
2361
  if (status === apiStatus.PENDING) {
2293
2362
  return /*#__PURE__*/React.createElement("div", {
@@ -2295,11 +2364,7 @@ const PaymentPlanWidget = ({
2295
2364
  }, /*#__PURE__*/React.createElement(Loader, null));
2296
2365
  }
2297
2366
 
2298
- if (hideIfNotEligible && eligiblePlans.length == 0 || eligibilityPlans.length === 0) {
2299
- return null;
2300
- }
2301
-
2302
- if (status === apiStatus.FAILED) {
2367
+ if (hideIfNotEligible && eligiblePlans.length === 0 || eligibilityPlans.length === 0 || status === apiStatus.FAILED) {
2303
2368
  return null;
2304
2369
  }
2305
2370
 
@@ -2311,19 +2376,12 @@ const PaymentPlanWidget = ({
2311
2376
  }
2312
2377
  };
2313
2378
 
2314
- const handleHoverAndClick = (key, newInitialPlanIndex) => {
2315
- // This is needed to update the initial plan index and button style when hovering (desktop) or clicking (mobile).
2316
- // The actual modal opening is triggered by a click on the highest parent div in `handleOpenModal`.
2317
- onHover(key);
2318
- setInitialPlanIndex(newInitialPlanIndex);
2319
- };
2320
-
2321
2379
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
2322
2380
  onClick: handleOpenModal,
2323
- className: s$b.widgetButton,
2324
- style: {
2325
- cursor: eligiblePlans.length > 0 ? 'pointer' : 'initial'
2326
- },
2381
+ className: cx(s$b.widgetButton, {
2382
+ [s$b.clickable]: eligiblePlans.length > 0,
2383
+ [s$b.unClickable]: eligiblePlans.length === 0
2384
+ }),
2327
2385
  "data-testid": "widget-button"
2328
2386
  }, /*#__PURE__*/React.createElement("div", {
2329
2387
  className: s$b.primaryContainer
@@ -2332,18 +2390,10 @@ const PaymentPlanWidget = ({
2332
2390
  }), /*#__PURE__*/React.createElement("div", {
2333
2391
  className: s$b.paymentPlans
2334
2392
  }, eligibilityPlans.map((eligibilityPlan, key) => {
2335
- const newInitialPlanIndex = eligiblePlanKeys.includes(key) ? eligiblePlanKeys.findIndex(planKey => planKey === key) : 0;
2336
2393
  return /*#__PURE__*/React.createElement("div", {
2337
- onMouseEnter: () => {
2338
- handleHoverAndClick(key, newInitialPlanIndex);
2339
- },
2340
- onMouseOut: () => {
2341
- onLeave();
2342
- },
2343
- onClick: () => {
2344
- handleHoverAndClick(key, newInitialPlanIndex);
2345
- },
2346
2394
  key: key,
2395
+ onMouseEnter: () => onHover(key),
2396
+ onMouseOut: onLeave,
2347
2397
  className: cx(s$b.plan, {
2348
2398
  [s$b.active]: current === key,
2349
2399
  [s$b.notEligible]: !eligibilityPlan.eligible
@@ -2354,7 +2404,7 @@ const PaymentPlanWidget = ({
2354
2404
  [s$b.notEligible]: eligibilityPlans[current] && !eligibilityPlans[current].eligible
2355
2405
  })
2356
2406
  }, eligibilityPlans.length !== 0 && paymentPlanInfoText(eligibilityPlans[current]))), isOpen && /*#__PURE__*/React.createElement(EligibilityModal, {
2357
- initialPlanIndex: initialPlanIndex,
2407
+ initialPlanIndex: getIndexWithinEligiblePlans(current),
2358
2408
  onClose: closeModal,
2359
2409
  eligibilityPlans: eligiblePlans,
2360
2410
  status: status
@@ -2380,6 +2430,7 @@ class WidgetsController {
2380
2430
  plans,
2381
2431
  transitionDelay,
2382
2432
  hideIfNotEligible,
2433
+ suggestedPaymentPlan,
2383
2434
  locale = Locale.en
2384
2435
  } = options;
2385
2436
 
@@ -2391,7 +2442,8 @@ class WidgetsController {
2391
2442
  apiData: this.apiData,
2392
2443
  configPlans: plans,
2393
2444
  transitionDelay: transitionDelay,
2394
- hideIfNotEligible: hideIfNotEligible
2445
+ hideIfNotEligible: hideIfNotEligible,
2446
+ suggestedPaymentPlan: suggestedPaymentPlan
2395
2447
  })), document.querySelector(container));
2396
2448
  }
2397
2449
  }