@stigg/react-sdk 5.2.1 → 5.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.
Files changed (28) hide show
  1. package/dist/components/common/TiersSelectContainer.d.ts +2 -4
  2. package/dist/components/common/VolumeBulkSelect.d.ts +1 -1
  3. package/dist/components/common/VolumePerUnitInput.d.ts +1 -1
  4. package/dist/components/paywall/PlanOfferingButton.d.ts +2 -3
  5. package/dist/components/paywall/PlanPrice.d.ts +2 -4
  6. package/dist/components/utils/getPaidPriceText.d.ts +2 -3
  7. package/dist/components/utils/getPlanPrice.d.ts +1 -1
  8. package/dist/components/utils/priceTierUtils.d.ts +4 -5
  9. package/dist/react-sdk.cjs.development.js +82 -176
  10. package/dist/react-sdk.cjs.development.js.map +1 -1
  11. package/dist/react-sdk.cjs.production.min.js +1 -1
  12. package/dist/react-sdk.cjs.production.min.js.map +1 -1
  13. package/dist/react-sdk.esm.js +83 -177
  14. package/dist/react-sdk.esm.js.map +1 -1
  15. package/package.json +1 -1
  16. package/src/components/checkout/hooks/usePlanStepModel.ts +1 -1
  17. package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +4 -11
  18. package/src/components/checkout/summary/components/LineItems.tsx +1 -1
  19. package/src/components/common/TiersSelectContainer.tsx +5 -16
  20. package/src/components/common/VolumeBulkSelect.tsx +7 -4
  21. package/src/components/common/VolumePerUnitInput.tsx +3 -5
  22. package/src/components/paywall/Paywall.tsx +2 -2
  23. package/src/components/paywall/PlanOffering.tsx +6 -27
  24. package/src/components/paywall/PlanOfferingButton.tsx +2 -8
  25. package/src/components/paywall/PlanPrice.tsx +4 -23
  26. package/src/components/utils/getPaidPriceText.ts +6 -24
  27. package/src/components/utils/getPlanPrice.ts +0 -2
  28. package/src/components/utils/priceTierUtils.ts +25 -69
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "5.2.1",
2
+ "version": "5.3.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -75,7 +75,7 @@ function getBillableFeatures(
75
75
 
76
76
  if (price.isTieredPrice && !hasTierWithUnitPrice(price.tiers)) {
77
77
  const tier = getTierByQuantity(price.tiers!, quantity);
78
- quantity = tier!.upTo!;
78
+ quantity = tier.upTo!;
79
79
  }
80
80
 
81
81
  return {
@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
3
3
  import styled from '@emotion/styled';
4
4
  import Box from '@mui/material/Box';
5
5
  import { BillableFeatureInput } from '@stigg/api-client-js/src/generated/sdk';
6
- import { BillingModel, BillingPeriod, Plan, Price, PriceTierFragment } from '@stigg/js-client-sdk';
6
+ import { BillingModel, BillingPeriod, Plan, Price } from '@stigg/js-client-sdk';
7
7
 
8
8
  import { Typography } from '../../../common/Typography';
9
9
  import { useChargesSort } from '../../../hooks/useChargeSort';
@@ -12,7 +12,6 @@ import { currencyPriceFormatter } from '../../../utils/currencyUtils';
12
12
  import { InputField } from '../../components';
13
13
  import { useCheckoutModel, usePlanStepModel, useProgressBarModel } from '../../hooks';
14
14
  import { TiersSelectContainer } from '../../../common/TiersSelectContainer';
15
- import { getTierByQuantity } from '../../../utils/priceTierUtils';
16
15
  import { getValidPriceQuantity } from '../../../utils/priceUtils';
17
16
  import { getFeatureDisplayNameText } from '../../../utils/getFeatureName';
18
17
 
@@ -104,20 +103,14 @@ export function PlanCharge({
104
103
  chargeRow += ' / unit';
105
104
  }
106
105
  } else if (charge.isTieredPrice && charge.tiersMode && featureId) {
107
- const tier = getTierByQuantity(charge.tiers!, billableFeature!.quantity || 1);
106
+ const quantity = billableFeature?.quantity || 1;
108
107
  chargeRow = (
109
108
  <TiersSelectContainer
110
109
  componentId={`${featureId}-tiers`}
111
110
  tiers={charge.tiers}
112
- selectedTier={tier}
113
- handleTierChange={(tier: PriceTierFragment) => {
114
- if (tier.upTo) {
115
- setBillableFeature(featureId, tier.upTo);
116
- }
117
- }}
118
111
  tiersMode={charge.tiersMode}
119
- perUnitQuantity={billableFeature?.quantity}
120
- handlePerUnitQuantityChange={(quantity: number) => {
112
+ value={quantity}
113
+ handleChange={(quantity: number) => {
121
114
  setBillableFeature(featureId, quantity);
122
115
  }}
123
116
  width={120}
@@ -75,7 +75,7 @@ export const BilledPriceLineItem = ({
75
75
  let amount;
76
76
  if (price.isTieredPrice) {
77
77
  const tier = getTierByQuantity(price.tiers!, quantity);
78
- amount = calculateTierPriceVolume(tier!, quantity);
78
+ amount = calculateTierPriceVolume(tier, quantity);
79
79
  } else {
80
80
  amount = price.amount!;
81
81
  }
@@ -1,7 +1,7 @@
1
1
  import { PriceTierFragment, TiersMode } from '@stigg/js-client-sdk';
2
2
  import React from 'react';
3
3
  import styled from '@emotion/styled/macro';
4
- import { getTierByQuantity, hasTierWithUnitPrice } from '../utils/priceTierUtils';
4
+ import { hasTierWithUnitPrice } from '../utils/priceTierUtils';
5
5
  import { Typography } from './Typography';
6
6
  import { VolumePerUnitInput } from './VolumePerUnitInput';
7
7
  import { VolumeBulkSelect } from './VolumeBulkSelect';
@@ -10,11 +10,9 @@ export type TiersSelectContainerProps = {
10
10
  componentId: string;
11
11
  tiers?: PriceTierFragment[] | null;
12
12
  tierUnits?: string;
13
- selectedTier?: PriceTierFragment;
14
- handleTierChange: (tier: PriceTierFragment) => void;
15
13
  tiersMode?: TiersMode | null;
16
- handlePerUnitQuantityChange: (quantity: number) => void;
17
- perUnitQuantity?: number;
14
+ handleChange: (quantity: number) => void;
15
+ value: number;
18
16
  width?: number;
19
17
  };
20
18
 
@@ -23,20 +21,11 @@ const TiersSelectLayout = styled(Typography)`
23
21
  `;
24
22
 
25
23
  export function TiersSelectContainer(props: TiersSelectContainerProps) {
26
- const { tiers, handleTierChange } = props;
27
- const handleChange = (quantity: number) => {
28
- if (!tiers) return;
29
-
30
- handleTierChange(getTierByQuantity(tiers, quantity)!);
31
- };
24
+ const { tiers } = props;
32
25
 
33
26
  return (
34
27
  <TiersSelectLayout as="div" className="stigg-price-tier-select">
35
- {hasTierWithUnitPrice(tiers) ? (
36
- <VolumePerUnitInput handleChange={handleChange} {...props} />
37
- ) : (
38
- <VolumeBulkSelect handleChange={handleChange} {...props} />
39
- )}
28
+ {hasTierWithUnitPrice(tiers) ? <VolumePerUnitInput {...props} /> : <VolumeBulkSelect {...props} />}
40
29
  </TiersSelectLayout>
41
30
  );
42
31
  }
@@ -29,12 +29,12 @@ const TierInput = styled(OutlinedInput)`
29
29
  `;
30
30
 
31
31
  export function VolumeBulkSelect({
32
- selectedTier,
32
+ value,
33
33
  componentId,
34
34
  tierUnits,
35
35
  tiers,
36
36
  handleChange,
37
- }: Pick<TiersSelectContainerProps, 'selectedTier' | 'componentId' | 'tiers' | 'tierUnits'> & {
37
+ }: Pick<TiersSelectContainerProps, 'value' | 'componentId' | 'tiers' | 'tierUnits'> & {
38
38
  handleChange: (quantity: number) => void;
39
39
  }) {
40
40
  if (!tiers) {
@@ -43,10 +43,13 @@ export function VolumeBulkSelect({
43
43
 
44
44
  return (
45
45
  <TierSelect
46
- value={selectedTier ? selectedTier.upTo?.toString() : tiers[0].upTo?.toString()}
46
+ value={value.toString()}
47
47
  fullWidth
48
48
  onChange={(event) => {
49
- handleChange(event.target.value as number);
49
+ const quantity = event?.target?.value ? Number(event?.target?.value) : null;
50
+ if (quantity) {
51
+ handleChange(quantity);
52
+ }
50
53
  }}
51
54
  id={componentId}
52
55
  input={<TierInput />}
@@ -7,10 +7,9 @@ import { TiersSelectContainerProps } from './TiersSelectContainer';
7
7
  export function VolumePerUnitInput({
8
8
  width,
9
9
  tierUnits,
10
- perUnitQuantity,
11
- handlePerUnitQuantityChange,
10
+ value,
12
11
  handleChange,
13
- }: Pick<TiersSelectContainerProps, 'width' | 'tierUnits' | 'perUnitQuantity' | 'handlePerUnitQuantityChange'> & {
12
+ }: Pick<TiersSelectContainerProps, 'width' | 'tierUnits' | 'value'> & {
14
13
  handleChange: (quantity: number) => void;
15
14
  }) {
16
15
  return (
@@ -27,12 +26,11 @@ export function VolumePerUnitInput({
27
26
  </InputAdornment>
28
27
  ),
29
28
  }}
30
- value={perUnitQuantity || 1}
29
+ value={value}
31
30
  onChange={(event) => {
32
31
  const quantity = event?.target?.value ? Number(event?.target?.value) : null;
33
32
  if (quantity) {
34
33
  handleChange(quantity);
35
- handlePerUnitQuantityChange(quantity);
36
34
  }
37
35
  }}
38
36
  />
@@ -17,7 +17,7 @@ import { useStiggContext } from '../..';
17
17
  import { hasPricePointsForPlans } from './utils/hasPricePoints';
18
18
  import { getPlansToDisplay } from './utils/getPlansToDisplay';
19
19
  import { getPlanPrice } from '../utils/getPlanPrice';
20
- import { getSelectedTier } from '../utils/priceTierUtils';
20
+ import { getTiersPerUnitQuantities } from '../utils/priceTierUtils';
21
21
 
22
22
  const PaywallPlansContainer = styled.div`
23
23
  color: ${({ theme }) => theme.stigg.palette.text.primary};
@@ -123,7 +123,7 @@ export const Paywall = ({
123
123
  return (
124
124
  !isCustomerInCustomPlan &&
125
125
  plansToShow.some((plan) => {
126
- const tiers = getSelectedTier(plan, selectedBillingPeriod, currentSubscription, {});
126
+ const tiers = getTiersPerUnitQuantities(plan, selectedBillingPeriod, currentSubscription);
127
127
  return Object.values(tiers).length > 0;
128
128
  })
129
129
  );
@@ -1,12 +1,5 @@
1
- import React, { useEffect, useState } from 'react';
2
- import {
3
- BillableFeature,
4
- BillingPeriod,
5
- Customer,
6
- PriceTierFragment,
7
- PricingType,
8
- Subscription,
9
- } from '@stigg/js-client-sdk';
1
+ import React, { useState } from 'react';
2
+ import { BillableFeature, BillingPeriod, Customer, PricingType, Subscription } from '@stigg/js-client-sdk';
10
3
  import styled from '@emotion/styled/macro';
11
4
  import classNames from 'classnames';
12
5
  import Grid from '@mui/material/Grid';
@@ -18,7 +11,7 @@ import { flexLayoutMapper } from '../../theme/getResolvedTheme';
18
11
  import { Typography } from '../common/Typography';
19
12
  import MiniSchedule from '../../assets/mini-schedule.svg';
20
13
  import { PlanPrice } from './PlanPrice';
21
- import { getSelectedTier, getSelectedTierQuantityBeFeature } from '../utils/priceTierUtils';
14
+ import { getTiersPerUnitQuantities } from '../utils/priceTierUtils';
22
15
 
23
16
  const PlanOfferingButtonHeight = '66px';
24
17
 
@@ -167,28 +160,17 @@ export function PlanOffering({
167
160
  );
168
161
  }
169
162
 
170
- const [perUnitQuantityByFeature, setPerUnitQuantityByFeature] = useState<Record<string, number>>({});
171
- const [selectedTierByFeature, setSelectedTierByFeature] = useState<Record<string, PriceTierFragment>>(
172
- getSelectedTier(plan, billingPeriod, currentSubscription, {}, selectDefaultTierIndex),
163
+ const [perUnitQuantityByFeature, setPerUnitQuantityByFeature] = useState<Record<string, number>>(
164
+ getTiersPerUnitQuantities(plan, billingPeriod, currentSubscription, selectDefaultTierIndex),
173
165
  );
174
166
 
175
- useEffect(() => {
176
- setSelectedTierByFeature(getSelectedTier(plan, billingPeriod, currentSubscription, selectedTierByFeature));
177
- setPerUnitQuantityByFeature(getSelectedTierQuantityBeFeature(plan, billingPeriod, currentSubscription));
178
- // eslint-disable-next-line react-hooks/exhaustive-deps
179
- }, [billingPeriod, currentSubscription, plan]);
180
-
181
167
  const onPlanButtonClick = (intentionType: SubscribeIntentionType) => {
182
- const tierBillableFeatures: BillableFeature[] = Object.keys(selectedTierByFeature).map((featureId) => ({
183
- featureId,
184
- quantity: selectedTierByFeature[featureId].upTo || 0,
185
- }));
186
168
  const perUnitBillableFeatures: BillableFeature[] = Object.keys(perUnitQuantityByFeature).map((featureId) => ({
187
169
  featureId,
188
170
  quantity: perUnitQuantityByFeature[featureId],
189
171
  }));
190
172
 
191
- return onPlanSelected(intentionType, { ...tierBillableFeatures, ...perUnitBillableFeatures });
173
+ return onPlanSelected(intentionType, perUnitBillableFeatures);
192
174
  };
193
175
 
194
176
  return (
@@ -216,8 +198,6 @@ export function PlanOffering({
216
198
  withUnitPriceRow={withUnitPriceRow}
217
199
  withStartingAtRow={withStartingAtRow}
218
200
  withTiersRow={withTiersRow}
219
- selectedTierByFeature={selectedTierByFeature}
220
- setSelectedTierByFeature={setSelectedTierByFeature}
221
201
  plan={plan}
222
202
  billingPeriod={billingPeriod}
223
203
  paywallLocale={paywallLocale}
@@ -239,7 +219,6 @@ export function PlanOffering({
239
219
  onPlanSelected={onPlanButtonClick}
240
220
  paywallLocale={paywallLocale}
241
221
  withTrialLeftRow={withTrialLeftRow}
242
- selectedTierByFeature={selectedTierByFeature}
243
222
  perUnitQuantityByFeature={perUnitQuantityByFeature}
244
223
  />
245
224
  ) : (
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react';
2
- import { BillingPeriod, Customer, PriceTierFragment, PricingType, Subscription } from '@stigg/js-client-sdk';
2
+ import { BillingPeriod, Customer, PricingType, Subscription } from '@stigg/js-client-sdk';
3
3
  import { isFunction } from 'lodash';
4
4
  import ClipLoader from 'react-spinners/ClipLoader';
5
5
  import styled from '@emotion/styled/macro';
@@ -82,7 +82,6 @@ type PlanOfferingButtonProps = {
82
82
  paywallLocale: PaywallLocalization;
83
83
  onPlanSelected: (intentionType: SubscribeIntentionType) => void | Promise<void>;
84
84
  withTrialLeftRow: boolean;
85
- selectedTierByFeature: Record<string, PriceTierFragment>;
86
85
  perUnitQuantityByFeature: Record<string, number>;
87
86
  };
88
87
 
@@ -96,7 +95,6 @@ export function PlanOfferingButton({
96
95
  paywallLocale,
97
96
  withTrialLeftRow,
98
97
  currentSubscription,
99
- selectedTierByFeature,
100
98
  perUnitQuantityByFeature,
101
99
  }: PlanOfferingButtonProps) {
102
100
  const theme = useTheme();
@@ -144,11 +142,7 @@ export function PlanOfferingButton({
144
142
  isSameBillingPeriod ||
145
143
  (plan.pricingType && [PricingType.Free, PricingType.Custom].includes(plan.pricingType))
146
144
  ) {
147
- const planComparison = compareSelectedTierToCurrentTier(
148
- selectedTierByFeature,
149
- perUnitQuantityByFeature,
150
- currentSubscription,
151
- );
145
+ const planComparison = compareSelectedTierToCurrentTier(perUnitQuantityByFeature, currentSubscription);
152
146
  switch (planComparison) {
153
147
  case PriceTierComparison.Lower:
154
148
  buttonProps.intentionType = SubscribeIntentionType.CHANGE_UNIT_QUANTITY;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import styled from '@emotion/styled/macro';
3
- import { BillingPeriod, PriceTierFragment } from '@stigg/js-client-sdk';
3
+ import { BillingPeriod } from '@stigg/js-client-sdk';
4
4
  import { PaywallPlan } from './types';
5
5
  import { PaywallLocalization } from './paywallTextOverrides';
6
6
  import { getPlanPrice } from '../utils/getPlanPrice';
@@ -57,8 +57,6 @@ export const PlanPrice = ({
57
57
  withUnitPriceRow,
58
58
  withStartingAtRow,
59
59
  withTiersRow,
60
- selectedTierByFeature,
61
- setSelectedTierByFeature,
62
60
  plan,
63
61
  billingPeriod,
64
62
  paywallLocale,
@@ -72,8 +70,6 @@ export const PlanPrice = ({
72
70
  withUnitPriceRow: boolean;
73
71
  withStartingAtRow: boolean;
74
72
  withTiersRow: boolean;
75
- selectedTierByFeature: Record<string, PriceTierFragment>;
76
- setSelectedTierByFeature: React.Dispatch<React.SetStateAction<Record<string, PriceTierFragment>>>;
77
73
  perUnitQuantityByFeature: Record<string, number>;
78
74
  setPerUnitQuantityByFeature: React.Dispatch<React.SetStateAction<Record<string, number>>>;
79
75
  plan: PaywallPlan;
@@ -89,7 +85,6 @@ export const PlanPrice = ({
89
85
  paywallLocale,
90
86
  locale,
91
87
  hasMonthlyPrice,
92
- selectedTierByFeature,
93
88
  perUnitQuantityByFeature,
94
89
  );
95
90
 
@@ -98,19 +93,7 @@ export const PlanPrice = ({
98
93
  return planPrice.billingPeriod === billingPeriod && planPrice.isTieredPrice;
99
94
  });
100
95
  const featureId = tieredPrice ? tieredPrice.feature!.featureId : undefined;
101
- const selectedTier = featureId ? selectedTierByFeature[featureId] : undefined;
102
- const perUnitQuantity = featureId ? perUnitQuantityByFeature[featureId] : undefined;
103
-
104
- const handleTierChange = (tier: PriceTierFragment) => {
105
- if (!featureId) {
106
- return;
107
- }
108
-
109
- setSelectedTierByFeature((prevState) => ({
110
- ...prevState,
111
- [featureId]: tier,
112
- }));
113
- };
96
+ const perUnitQuantity = perUnitQuantityByFeature[featureId || ''] ?? 1;
114
97
 
115
98
  const handlePerUnitQuantityChange = (quantity: number) => {
116
99
  if (!featureId) {
@@ -161,11 +144,9 @@ export const PlanPrice = ({
161
144
  componentId={`${plan.id}_${featureId}_tier`}
162
145
  tiers={tiers}
163
146
  tierUnits={tierUnits}
164
- selectedTier={selectedTier}
165
- handleTierChange={handleTierChange}
166
147
  tiersMode={tieredPrice?.tiersMode}
167
- handlePerUnitQuantityChange={handlePerUnitQuantityChange}
168
- perUnitQuantity={perUnitQuantity}
148
+ handleChange={handlePerUnitQuantityChange}
149
+ value={perUnitQuantity}
169
150
  />
170
151
  ) : null}
171
152
  </>
@@ -1,10 +1,4 @@
1
- import {
2
- BillingModel,
3
- BillingPeriod,
4
- PaywallCalculatedPricePoint,
5
- Price,
6
- PriceTierFragment,
7
- } from '@stigg/js-client-sdk';
1
+ import { BillingModel, BillingPeriod, PaywallCalculatedPricePoint, Price } from '@stigg/js-client-sdk';
8
2
  import { currencyPriceFormatter } from './currencyUtils';
9
3
  import { PlanPriceText } from './getPlanPrice';
10
4
  import { calculateTierPrice, getPriceFeatureUnit } from './priceTierUtils';
@@ -16,7 +10,6 @@ type GetPaidPriceTextParams = {
16
10
  selectedBillingPeriod: BillingPeriod;
17
11
  locale: string;
18
12
  shouldShowMonthlyPriceAmount: boolean;
19
- selectedTierByFeature: Record<string, PriceTierFragment>;
20
13
  paywallLocale: PaywallLocalization;
21
14
  perUnitQuantityByFeature?: Record<string, number>;
22
15
  };
@@ -27,7 +20,6 @@ export function getPaidPriceText({
27
20
  selectedBillingPeriod,
28
21
  locale,
29
22
  shouldShowMonthlyPriceAmount,
30
- selectedTierByFeature,
31
23
  paywallLocale,
32
24
  perUnitQuantityByFeature,
33
25
  }: GetPaidPriceTextParams): PlanPriceText {
@@ -46,22 +38,12 @@ export function getPaidPriceText({
46
38
  let unit = pricePeriod;
47
39
 
48
40
  for (const price of planPrices) {
49
- if (price.isTieredPrice) {
50
- let currentTier = price.tiers![0];
51
- if (selectedTierByFeature[price.feature!.featureId]) {
52
- currentTier = selectedTierByFeature[price.feature!.featureId] || currentTier;
41
+ if (price.isTieredPrice && price.tiers) {
42
+ const quantity = perUnitQuantityByFeature?.[price.feature!.featureId] || 1;
43
+ tiers = price.tiers;
44
+ tierUnits = getPriceFeatureUnit(price);
53
45
 
54
- tiers = price.tiers;
55
- tierUnits = getPriceFeatureUnit(price);
56
- }
57
-
58
- priceNumber += calculateTierPrice(
59
- price,
60
- currentTier,
61
- selectedBillingPeriod,
62
- shouldShowMonthlyPriceAmount,
63
- perUnitQuantityByFeature?.[price.feature!.featureId] || 1,
64
- );
46
+ priceNumber += calculateTierPrice(price, selectedBillingPeriod, shouldShowMonthlyPriceAmount, quantity);
65
47
  }
66
48
  }
67
49
 
@@ -15,7 +15,6 @@ export function getPlanPrice(
15
15
  paywallLocale: PaywallLocalization,
16
16
  locale: string,
17
17
  shouldShowMonthlyPriceAmount: boolean,
18
- selectedTierByFeature?: Record<string, PriceTierFragment>,
19
18
  perUnitQuantityByFeature?: Record<string, number>,
20
19
  ): PlanPriceText {
21
20
  switch (plan.pricingType) {
@@ -48,7 +47,6 @@ export function getPlanPrice(
48
47
  planPrices,
49
48
  paywallCalculatedPrice,
50
49
  selectedBillingPeriod: billingPeriod,
51
- selectedTierByFeature: selectedTierByFeature || {},
52
50
  perUnitQuantityByFeature: perUnitQuantityByFeature || {},
53
51
  };
54
52
 
@@ -11,9 +11,7 @@ export function getPriceFeatureUnit(price: Price) {
11
11
  return (price.feature.unitQuantity !== 1 ? price.feature.unitsPlural : price.feature.units) || '';
12
12
  }
13
13
 
14
- export function getTierByQuantity(tiers: PriceTierFragment[], quantity: number) {
15
- if (!tiers) return undefined;
16
-
14
+ export function getTierByQuantity(tiers: PriceTierFragment[], quantity: number): PriceTierFragment {
17
15
  const ascendingTiers = [...tiers];
18
16
  // Sort tiers by upTo value, ascending, if upTo is not set,
19
17
  // put it at the end as it represent the last infinity tier
@@ -54,64 +52,34 @@ export function calculateTierPriceVolume(
54
52
 
55
53
  export function calculateTierPrice(
56
54
  price: Price,
57
- currentTier: PriceTierFragment,
58
55
  selectedBillingPeriod: BillingPeriod,
59
56
  shouldShowMonthlyPriceAmount: boolean,
60
- perUnitQuantity: number,
57
+ unitQuantity: number,
61
58
  ): number {
59
+ if (!price.tiers) {
60
+ return 0;
61
+ }
62
+
62
63
  switch (price.tiersMode) {
63
64
  case TiersMode.Volume: {
64
- return calculateTierPriceVolume(
65
- currentTier,
66
- perUnitQuantity,
67
- selectedBillingPeriod,
68
- shouldShowMonthlyPriceAmount,
69
- );
65
+ const currentTier = getTierByQuantity(price.tiers, unitQuantity);
66
+ return calculateTierPriceVolume(currentTier, unitQuantity, selectedBillingPeriod, shouldShowMonthlyPriceAmount);
70
67
  }
71
68
  default:
72
69
  return 0;
73
70
  }
74
71
  }
75
72
 
76
- export function getSelectedTierQuantityBeFeature(
77
- plan: PaywallPlan,
78
- billingPeriod: BillingPeriod,
79
- currentSubscription: Subscription | null,
80
- ) {
81
- const result: Record<string, number> = {};
82
- const planTierPrices = plan.pricePoints.filter(
83
- (price) => price.billingPeriod === billingPeriod && price.isTieredPrice,
84
- );
85
- if (planTierPrices.length === 1) {
86
- const [price] = planTierPrices;
87
- const featureId = price?.feature!.featureId;
88
- if (currentSubscription && currentSubscription.plan.id === plan.id) {
89
- const tieredPrice = currentSubscription?.prices.find(
90
- (subscriptionPrice) =>
91
- subscriptionPrice.pricingModel === BillingModel.PerUnit &&
92
- subscriptionPrice.tiersMode &&
93
- subscriptionPrice.feature?.featureId === featureId,
94
- );
95
- if (tieredPrice) {
96
- result[featureId] = tieredPrice.feature?.unitQuantity || 1;
97
- }
98
- }
99
- }
100
-
101
- return result;
102
- }
103
-
104
73
  export function hasTierWithUnitPrice(tiers: PriceTierFragment[] | null | undefined) {
105
74
  return tiers?.some(({ unitPrice, upTo }) => unitPrice && !isNil(upTo));
106
75
  }
107
76
 
108
- export function getSelectedTier(
77
+ export function getTiersPerUnitQuantities(
109
78
  plan: PaywallPlan,
110
79
  billingPeriod: BillingPeriod,
111
80
  currentSubscription: Subscription | null,
112
- selectedTierByFeature: Record<string, PriceTierFragment>,
113
81
  selectDefaultTierIndex?: SelectDefaultTierIndexFn,
114
- ): Record<string, PriceTierFragment> {
82
+ ): Record<string, number> {
115
83
  const planTierPrices = plan.pricePoints.filter(
116
84
  (price) => price.billingPeriod === billingPeriod && price.isTieredPrice,
117
85
  );
@@ -120,11 +88,10 @@ export function getSelectedTier(
120
88
  const [price] = planTierPrices;
121
89
  const { featureId } = price.feature!;
122
90
  const selectedDefaultTierIndex = selectDefaultTierIndex ? selectDefaultTierIndex({ plan }) : 0;
123
- let currentTier = price.tiers![selectedDefaultTierIndex];
91
+ const currentTier = price.tiers![selectedDefaultTierIndex];
92
+ let quantity = hasTierWithUnitPrice(price.tiers) ? 1 : currentTier.upTo || 1;
124
93
 
125
- if (selectedTierByFeature[featureId]) {
126
- currentTier = price.tiers?.find((tier) => tier.upTo === selectedTierByFeature[featureId].upTo) || currentTier;
127
- } else if (currentSubscription && currentSubscription.plan.id === plan.id) {
94
+ if (currentSubscription && currentSubscription.plan.id === plan.id) {
128
95
  const tieredPrice = currentSubscription.prices.find(
129
96
  (subscriptionPrice) =>
130
97
  subscriptionPrice.pricingModel === BillingModel.PerUnit &&
@@ -133,12 +100,12 @@ export function getSelectedTier(
133
100
  );
134
101
 
135
102
  if (tieredPrice) {
136
- currentTier = getTierByQuantity(price.tiers!, tieredPrice.feature!.unitQuantity || 1)!;
103
+ quantity = tieredPrice.feature!.unitQuantity || 1;
137
104
  }
138
105
  }
139
106
 
140
- const result: Record<string, PriceTierFragment> = {};
141
- result[featureId] = currentTier;
107
+ const result: Record<string, number> = {};
108
+ result[featureId] = quantity;
142
109
 
143
110
  return result;
144
111
  }
@@ -153,11 +120,10 @@ export enum PriceTierComparison {
153
120
  }
154
121
 
155
122
  export function compareSelectedTierToCurrentTier(
156
- selectedTierByFeature: Record<string, PriceTierFragment>,
157
123
  perUnitQuantityByFeature: Record<string, number>,
158
124
  currentSubscription: Subscription | null,
159
125
  ): PriceTierComparison {
160
- if (!currentSubscription || !selectedTierByFeature) {
126
+ if (!currentSubscription) {
161
127
  return PriceTierComparison.Equal;
162
128
  }
163
129
 
@@ -168,29 +134,19 @@ export function compareSelectedTierToCurrentTier(
168
134
  return PriceTierComparison.Equal;
169
135
  }
170
136
 
171
- const { featureId, unitQuantity } = currentTierPrice.feature!;
172
- const { tiers } = currentTierPrice;
173
-
174
- if (!unitQuantity) {
175
- return PriceTierComparison.Equal;
176
- }
137
+ const { featureId, unitQuantity: oldQuantity } = currentTierPrice.feature!;
177
138
 
178
- const selectedTier = selectedTierByFeature[featureId];
179
- const selectedQuantity = perUnitQuantityByFeature[featureId];
180
- if (!selectedTier) {
139
+ if (isNil(oldQuantity)) {
181
140
  return PriceTierComparison.Equal;
182
141
  }
183
142
 
184
- const effectiveQuantity = hasTierWithUnitPrice(tiers) ? selectedQuantity : selectedTier.upTo;
143
+ const newQuantity = perUnitQuantityByFeature[featureId];
185
144
 
186
- if (!isNil(effectiveQuantity)) {
187
- if (effectiveQuantity < unitQuantity) {
188
- return PriceTierComparison.Lower;
189
- }
190
- if (effectiveQuantity > unitQuantity) {
191
- return PriceTierComparison.Higher;
192
- }
145
+ if (newQuantity < oldQuantity) {
146
+ return PriceTierComparison.Lower;
147
+ }
148
+ if (newQuantity > oldQuantity) {
149
+ return PriceTierComparison.Higher;
193
150
  }
194
-
195
151
  return PriceTierComparison.Equal;
196
152
  }