@stigg/react-sdk 4.3.0-beta.0 → 4.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 (170) hide show
  1. package/README.md +1 -1
  2. package/dist/components/common/Icon.d.ts +2 -3
  3. package/dist/components/common/PoweredByStigg.d.ts +1 -1
  4. package/dist/components/common/customIcons.d.ts +5 -17
  5. package/dist/components/common/mapExternalTheme.d.ts +0 -2
  6. package/dist/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.d.ts +1 -1
  7. package/dist/components/{common/TiersSelectContainer.d.ts → paywall/TiersLayout.d.ts} +3 -2
  8. package/dist/components/paywall/paywallTextOverrides.d.ts +2 -0
  9. package/dist/components/{utils/priceTierUtils.d.ts → paywall/planPriceTier.d.ts} +1 -3
  10. package/dist/components/utils/calculateDiscountRate.d.ts +0 -1
  11. package/dist/components/utils/currencyUtils.d.ts +1 -1
  12. package/dist/index.d.ts +0 -1
  13. package/dist/react-sdk.cjs.development.js +201 -3447
  14. package/dist/react-sdk.cjs.development.js.map +1 -1
  15. package/dist/react-sdk.cjs.production.min.js +1 -1
  16. package/dist/react-sdk.cjs.production.min.js.map +1 -1
  17. package/dist/react-sdk.esm.js +207 -3590
  18. package/dist/react-sdk.esm.js.map +1 -1
  19. package/dist/theme/getResolvedTheme.d.ts +0 -1
  20. package/dist/theme/types.d.ts +0 -1
  21. package/package.json +22 -11
  22. package/src/components/StiggProvider.tsx +2 -0
  23. package/src/components/common/Icon.tsx +22 -17
  24. package/src/components/common/PoweredByStigg.tsx +1 -1
  25. package/src/components/common/Typography.tsx +1 -11
  26. package/src/components/common/customIcons.ts +28 -17
  27. package/src/components/common/mapExternalTheme.ts +0 -6
  28. package/src/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.tsx +12 -6
  29. package/src/components/paywall/Paywall.tsx +1 -1
  30. package/src/components/paywall/PlanOffering.tsx +1 -1
  31. package/src/components/paywall/PlanOfferingButton.tsx +1 -1
  32. package/src/components/paywall/PlanPrice.tsx +13 -5
  33. package/src/components/{common/TiersSelectContainer.tsx → paywall/TiersLayout.tsx} +7 -8
  34. package/src/components/paywall/paywallTextOverrides.ts +1 -0
  35. package/src/components/{utils/priceTierUtils.ts → paywall/planPriceTier.ts} +3 -25
  36. package/src/components/paywall/utils/calculateUnitQuantityText.ts +4 -9
  37. package/src/components/utils/calculateDiscountRate.ts +1 -1
  38. package/src/components/utils/currencyUtils.ts +1 -1
  39. package/src/components/utils/getPaidPriceText.ts +2 -2
  40. package/src/index.ts +0 -1
  41. package/src/stories/CustomerPortal.stories.tsx +11 -11
  42. package/src/stories/Paywall.stories.tsx +4 -6
  43. package/src/stories/baseArgs.ts +1 -1
  44. package/src/theme/Fonts.tsx +1 -1
  45. package/src/theme/Theme.tsx +7 -9
  46. package/src/theme/getResolvedTheme.ts +0 -1
  47. package/src/theme/types.ts +0 -1
  48. package/dist/components/checkout/Checkout.d.ts +0 -5
  49. package/dist/components/checkout/CheckoutContainer.d.ts +0 -22
  50. package/dist/components/checkout/CheckoutContainer.style.d.ts +0 -29
  51. package/dist/components/checkout/CheckoutProvider.d.ts +0 -33
  52. package/dist/components/checkout/CheckoutSummary.d.ts +0 -9
  53. package/dist/components/checkout/components/Button.d.ts +0 -6
  54. package/dist/components/checkout/components/InputField.d.ts +0 -8
  55. package/dist/components/checkout/components/index.d.ts +0 -2
  56. package/dist/components/checkout/formatting.d.ts +0 -2
  57. package/dist/components/checkout/hooks/index.d.ts +0 -8
  58. package/dist/components/checkout/hooks/useAddonsStepModel.d.ts +0 -21
  59. package/dist/components/checkout/hooks/useCheckoutModel.d.ts +0 -9
  60. package/dist/components/checkout/hooks/useCouponModel.d.ts +0 -7
  61. package/dist/components/checkout/hooks/useLoadCheckout.d.ts +0 -13
  62. package/dist/components/checkout/hooks/usePaymentStepModel.d.ts +0 -16
  63. package/dist/components/checkout/hooks/usePlanStepModel.d.ts +0 -23
  64. package/dist/components/checkout/hooks/usePreviewSubscription.d.ts +0 -13
  65. package/dist/components/checkout/hooks/useProgressBarModel.d.ts +0 -26
  66. package/dist/components/checkout/hooks/useSubscriptionModel.d.ts +0 -5
  67. package/dist/components/checkout/hooks/useSubscriptionState.d.ts +0 -2
  68. package/dist/components/checkout/index.d.ts +0 -3
  69. package/dist/components/checkout/planHeader/PlanHeader.d.ts +0 -7
  70. package/dist/components/checkout/planHeader/PlanHeader.style.d.ts +0 -25
  71. package/dist/components/checkout/planHeader/index.d.ts +0 -1
  72. package/dist/components/checkout/progressBar/CheckoutProgressBar.d.ts +0 -2
  73. package/dist/components/checkout/progressBar/CheckoutProgressBar.style.d.ts +0 -45
  74. package/dist/components/checkout/promotionCode/AddPromotionCode.d.ts +0 -5
  75. package/dist/components/checkout/promotionCode/AddPromotionCodeButton.d.ts +0 -7
  76. package/dist/components/checkout/promotionCode/AppliedPromotionCode.d.ts +0 -6
  77. package/dist/components/checkout/promotionCode/PromotionCodeSection.d.ts +0 -5
  78. package/dist/components/checkout/promotionCode/index.d.ts +0 -1
  79. package/dist/components/checkout/steps/addons/CheckoutAddonsStep.d.ts +0 -2
  80. package/dist/components/checkout/steps/addons/CheckoutAddonsStep.style.d.ts +0 -93
  81. package/dist/components/checkout/steps/addons/addon.utils.d.ts +0 -15
  82. package/dist/components/checkout/steps/addons/index.d.ts +0 -1
  83. package/dist/components/checkout/steps/payment/PaymentMethods.d.ts +0 -19
  84. package/dist/components/checkout/steps/payment/PaymentMethods.style.d.ts +0 -113
  85. package/dist/components/checkout/steps/payment/PaymentStep.d.ts +0 -2
  86. package/dist/components/checkout/steps/payment/index.d.ts +0 -1
  87. package/dist/components/checkout/steps/payment/stripe/StripePaymentForm.d.ts +0 -2
  88. package/dist/components/checkout/steps/payment/stripe/index.d.ts +0 -3
  89. package/dist/components/checkout/steps/payment/stripe/stripe.utils.d.ts +0 -33
  90. package/dist/components/checkout/steps/payment/stripe/useStripeIntegration.d.ts +0 -5
  91. package/dist/components/checkout/steps/payment/stripe/useSubmit.d.ts +0 -10
  92. package/dist/components/checkout/steps/plan/BillingPeriodPicker.d.ts +0 -9
  93. package/dist/components/checkout/steps/plan/BillingPeriodPicker.style.d.ts +0 -52
  94. package/dist/components/checkout/steps/plan/CheckoutChargeList.d.ts +0 -16
  95. package/dist/components/checkout/steps/plan/CheckoutPlanStep.d.ts +0 -4
  96. package/dist/components/checkout/steps/plan/CheckoutPlanStep.style.d.ts +0 -12
  97. package/dist/components/checkout/steps/plan/index.d.ts +0 -1
  98. package/dist/components/checkout/steps/surprise/SurpriseStep.d.ts +0 -2
  99. package/dist/components/checkout/textOverrides.d.ts +0 -28
  100. package/dist/components/checkout/theme.d.ts +0 -8
  101. package/dist/components/checkout/types.d.ts +0 -7
  102. package/dist/components/hooks/useChargeSort.d.ts +0 -3
  103. package/dist/components/utils/priceUtils.d.ts +0 -2
  104. package/dist/stories/Checkout.stories.d.ts +0 -3
  105. package/src/assets/arrow-forward.svg +0 -3
  106. package/src/assets/arrow-right.svg +0 -6
  107. package/src/assets/close.svg +0 -3
  108. package/src/assets/nyancat.svg +0 -634
  109. package/src/assets/outlined-checked-circle.svg +0 -6
  110. package/src/assets/outlined-circle.svg +0 -3
  111. package/src/assets/payment-method.svg +0 -11
  112. package/src/assets/plus-icon.svg +0 -6
  113. package/src/assets/trash.svg +0 -8
  114. package/src/components/checkout/Checkout.tsx +0 -30
  115. package/src/components/checkout/CheckoutContainer.style.ts +0 -34
  116. package/src/components/checkout/CheckoutContainer.tsx +0 -92
  117. package/src/components/checkout/CheckoutProvider.tsx +0 -135
  118. package/src/components/checkout/CheckoutSummary.tsx +0 -361
  119. package/src/components/checkout/components/Button.tsx +0 -30
  120. package/src/components/checkout/components/InputField.tsx +0 -23
  121. package/src/components/checkout/components/index.ts +0 -2
  122. package/src/components/checkout/formatting.ts +0 -12
  123. package/src/components/checkout/hooks/index.ts +0 -8
  124. package/src/components/checkout/hooks/useAddonsStepModel.ts +0 -96
  125. package/src/components/checkout/hooks/useCheckoutModel.ts +0 -31
  126. package/src/components/checkout/hooks/useCouponModel.ts +0 -28
  127. package/src/components/checkout/hooks/useLoadCheckout.ts +0 -40
  128. package/src/components/checkout/hooks/usePaymentStepModel.ts +0 -49
  129. package/src/components/checkout/hooks/usePlanStepModel.ts +0 -170
  130. package/src/components/checkout/hooks/usePreviewSubscription.ts +0 -82
  131. package/src/components/checkout/hooks/useProgressBarModel.ts +0 -89
  132. package/src/components/checkout/hooks/useSubscriptionModel.ts +0 -16
  133. package/src/components/checkout/hooks/useSubscriptionState.ts +0 -26
  134. package/src/components/checkout/index.ts +0 -3
  135. package/src/components/checkout/planHeader/PlanHeader.style.tsx +0 -23
  136. package/src/components/checkout/planHeader/PlanHeader.tsx +0 -61
  137. package/src/components/checkout/planHeader/index.ts +0 -1
  138. package/src/components/checkout/progressBar/CheckoutProgressBar.style.ts +0 -29
  139. package/src/components/checkout/progressBar/CheckoutProgressBar.tsx +0 -48
  140. package/src/components/checkout/promotionCode/AddPromotionCode.tsx +0 -85
  141. package/src/components/checkout/promotionCode/AddPromotionCodeButton.tsx +0 -39
  142. package/src/components/checkout/promotionCode/AppliedPromotionCode.tsx +0 -37
  143. package/src/components/checkout/promotionCode/PromotionCodeSection.tsx +0 -27
  144. package/src/components/checkout/promotionCode/index.ts +0 -1
  145. package/src/components/checkout/steps/addons/CheckoutAddonsStep.style.tsx +0 -24
  146. package/src/components/checkout/steps/addons/CheckoutAddonsStep.tsx +0 -125
  147. package/src/components/checkout/steps/addons/addon.utils.ts +0 -68
  148. package/src/components/checkout/steps/addons/index.ts +0 -1
  149. package/src/components/checkout/steps/payment/PaymentMethods.style.ts +0 -26
  150. package/src/components/checkout/steps/payment/PaymentMethods.tsx +0 -83
  151. package/src/components/checkout/steps/payment/PaymentStep.tsx +0 -41
  152. package/src/components/checkout/steps/payment/index.ts +0 -1
  153. package/src/components/checkout/steps/payment/stripe/StripePaymentForm.tsx +0 -43
  154. package/src/components/checkout/steps/payment/stripe/index.ts +0 -3
  155. package/src/components/checkout/steps/payment/stripe/stripe.utils.ts +0 -109
  156. package/src/components/checkout/steps/payment/stripe/useStripeIntegration.ts +0 -27
  157. package/src/components/checkout/steps/payment/stripe/useSubmit.ts +0 -100
  158. package/src/components/checkout/steps/plan/BillingPeriodPicker.style.tsx +0 -46
  159. package/src/components/checkout/steps/plan/BillingPeriodPicker.tsx +0 -63
  160. package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +0 -138
  161. package/src/components/checkout/steps/plan/CheckoutPlanStep.style.tsx +0 -6
  162. package/src/components/checkout/steps/plan/CheckoutPlanStep.tsx +0 -22
  163. package/src/components/checkout/steps/plan/index.ts +0 -1
  164. package/src/components/checkout/steps/surprise/SurpriseStep.tsx +0 -27
  165. package/src/components/checkout/textOverrides.ts +0 -58
  166. package/src/components/checkout/theme.ts +0 -26
  167. package/src/components/checkout/types.ts +0 -7
  168. package/src/components/hooks/useChargeSort.ts +0 -17
  169. package/src/components/utils/priceUtils.ts +0 -10
  170. package/src/stories/Checkout.stories.tsx +0 -59
@@ -1,170 +0,0 @@
1
- import keyBy from 'lodash/keyBy';
2
-
3
- import { BillableFeatureInput, BillingPeriod } from '@stigg/api-client-js/src/generated/sdk';
4
- import { BillableFeature, BillingModel, Plan, Price, Subscription } from '@stigg/js-client-sdk';
5
-
6
- import { useCheckoutContext } from '../CheckoutProvider';
7
- import { getTierByQuantity } from '../../utils/priceTierUtils';
8
- import compact from 'lodash/compact';
9
- import { getValidPriceQuantity } from '../../utils/priceUtils';
10
-
11
- export type PlanStepState = {
12
- billingPeriod: BillingPeriod;
13
- billableFeatures: BillableFeatureInput[];
14
- billingCountryCode?: string;
15
- };
16
-
17
- type getPlanStepInitialStateProps = {
18
- preferredBillingPeriod?: BillingPeriod;
19
- plan?: Plan;
20
- activeSubscription?: Subscription | null;
21
- billingCountryCode?: string;
22
- preconfiguredBillableFeatures: BillableFeature[];
23
- };
24
-
25
- const isInAdvanceCommitmentCharge = ({ pricingModel }: Price) => {
26
- return pricingModel === BillingModel.PerUnit;
27
- };
28
-
29
- function getBillableFeatures(
30
- preconfiguredBillableFeatures: BillableFeature[],
31
- planPrices?: Price[],
32
- activeSubscription?: Subscription | null,
33
- ): BillableFeature[] {
34
- if (!planPrices) return [];
35
-
36
- const preconfBillableFeaturesByFeatureId = keyBy(preconfiguredBillableFeatures, 'featureId');
37
-
38
- const quantityByFeatureId = keyBy(
39
- compact(
40
- activeSubscription?.prices?.map(charge => {
41
- const { feature } = charge;
42
- if (!feature || !isInAdvanceCommitmentCharge(charge)) {
43
- return null;
44
- }
45
-
46
- return {
47
- featureId: feature.featureId,
48
- quantity: feature.unitQuantity || null,
49
- };
50
- }),
51
- ),
52
- 'featureId',
53
- );
54
-
55
- return compact(
56
- planPrices?.map(price => {
57
- const featureId = price.feature?.featureId;
58
- if (!featureId || !isInAdvanceCommitmentCharge(price)) {
59
- return null;
60
- }
61
-
62
- let quantity;
63
- const preconfiguredQuantity =
64
- preconfBillableFeaturesByFeatureId[featureId]?.quantity || quantityByFeatureId[featureId]?.quantity;
65
-
66
- quantity = getValidPriceQuantity(price, preconfiguredQuantity || 1);
67
-
68
- if (price.isTieredPrice) {
69
- const tier = getTierByQuantity(price.tiers!, quantity);
70
- quantity = tier!.upTo;
71
- }
72
-
73
- return {
74
- featureId,
75
- quantity,
76
- };
77
- }),
78
- );
79
- }
80
-
81
- function resolveBillingPeriod({
82
- plan,
83
- activeSubscription,
84
- preferredBillingPeriod,
85
- }: {
86
- plan?: Plan;
87
- activeSubscription?: Subscription | null;
88
- preferredBillingPeriod?: BillingPeriod;
89
- }) {
90
- const hasMonthlyPrices = plan?.pricePoints.some(pricePoint => pricePoint.billingPeriod === BillingPeriod.Monthly);
91
- const hasAnnualPrices = plan?.pricePoints.some(pricePoint => pricePoint.billingPeriod === BillingPeriod.Annually);
92
-
93
- const isUpdate = activeSubscription?.plan?.id === plan?.id;
94
- if (isUpdate) {
95
- return activeSubscription?.price?.billingPeriod || BillingPeriod.Monthly;
96
- }
97
-
98
- if (preferredBillingPeriod) {
99
- if (preferredBillingPeriod === BillingPeriod.Monthly && hasMonthlyPrices) {
100
- return BillingPeriod.Monthly;
101
- }
102
- if (preferredBillingPeriod === BillingPeriod.Annually && hasAnnualPrices) {
103
- return BillingPeriod.Annually;
104
- }
105
- }
106
-
107
- return hasAnnualPrices ? BillingPeriod.Annually : BillingPeriod.Monthly;
108
- }
109
-
110
- export function getPlanStepInitialState({
111
- preferredBillingPeriod,
112
- plan,
113
- activeSubscription,
114
- billingCountryCode,
115
- preconfiguredBillableFeatures,
116
- }: getPlanStepInitialStateProps): PlanStepState {
117
- const planBillingPeriod = resolveBillingPeriod({ plan, activeSubscription, preferredBillingPeriod });
118
-
119
- // TODO: add logic to determine billing period according to available prices if proffered not sent
120
- const billingPeriod = planBillingPeriod || preferredBillingPeriod || BillingPeriod.Annually;
121
- const planPrices = plan?.pricePoints.filter(pricePoint => pricePoint.billingPeriod === billingPeriod);
122
- const billableFeatures = getBillableFeatures(preconfiguredBillableFeatures, planPrices, activeSubscription);
123
-
124
- return {
125
- billingPeriod,
126
- billableFeatures,
127
- billingCountryCode,
128
- };
129
- }
130
-
131
- function usePlanState() {
132
- const [{ planStep }] = useCheckoutContext();
133
- return planStep;
134
- }
135
-
136
- function useSetBillableFeature() {
137
- const [, setState] = useCheckoutContext();
138
-
139
- return (featureId: string, quantity: number) =>
140
- setState(draft => {
141
- const billableFeature = draft.planStep.billableFeatures.find(
142
- billableFeature => billableFeature.featureId === featureId,
143
- );
144
-
145
- if (billableFeature) {
146
- billableFeature.quantity = quantity;
147
- } else {
148
- draft.planStep.billableFeatures.push({ featureId, quantity });
149
- }
150
- });
151
- }
152
-
153
- function useSetBillingPeriod() {
154
- const [, setState] = useCheckoutContext();
155
-
156
- return (billingPeriod: BillingPeriod) =>
157
- setState(draft => {
158
- draft.planStep.billingPeriod = billingPeriod;
159
- });
160
- }
161
-
162
- export function usePlanStepModel() {
163
- const state = usePlanState();
164
-
165
- return {
166
- ...state,
167
- setBillingPeriod: useSetBillingPeriod(),
168
- setBillableFeature: useSetBillableFeature(),
169
- };
170
- }
@@ -1,82 +0,0 @@
1
- import { useCallback, useEffect, useState } from 'react';
2
- import { PreviewSubscription, SubscriptionPreview } from '@stigg/js-client-sdk';
3
- import { useStiggContext } from '../../StiggProvider';
4
- import { useCheckoutContext } from '../CheckoutProvider';
5
- import { useCheckoutModel } from './useCheckoutModel';
6
- import { useSubscriptionModel } from './useSubscriptionModel';
7
-
8
- export const usePreviewSubscriptionAction = () => {
9
- const { stigg } = useStiggContext();
10
- const subscription = useSubscriptionModel();
11
- const [{ resourceId, planStep }] = useCheckoutContext();
12
- const { checkoutState } = useCheckoutModel();
13
- const { plan, activeSubscription, customer } = checkoutState || {};
14
-
15
- const previewSubscriptionAction = useCallback(
16
- async ({ promotionCode }: { promotionCode?: string | null } = {}) => {
17
- const estimateAddons = subscription.addons.map(({ addon, quantity }) => ({ addonId: addon.id, quantity }));
18
- let subscriptionPreview: SubscriptionPreview | null = null;
19
- let errorMessage: string | null = null;
20
-
21
- try {
22
- if (customer?.id && plan?.id) {
23
- const previewSubscriptionProps: PreviewSubscription = {
24
- customerId: customer.id,
25
- planId: plan?.id,
26
- billableFeatures: subscription.billableFeatures,
27
- addons: estimateAddons,
28
- billingPeriod: subscription.billingPeriod,
29
- promotionCode: promotionCode ?? subscription.promotionCode,
30
- resourceId,
31
- billingCountryCode: planStep.billingCountryCode,
32
- // TODO: Add billing information
33
- // billingInformation, // TaxId / Tax percentage
34
- };
35
- subscriptionPreview = await stigg.previewSubscription(previewSubscriptionProps);
36
- }
37
- } catch (error) {
38
- const [, errorMsg] = (error as any)?.message?.split('Error:') || [];
39
-
40
- errorMessage = errorMsg?.trim();
41
- }
42
-
43
- return { subscriptionPreview, errorMessage };
44
- },
45
- [
46
- activeSubscription,
47
- customer,
48
- plan,
49
- resourceId,
50
- stigg,
51
- subscription.addons,
52
- subscription.billingPeriod,
53
- subscription.billableFeatures,
54
- subscription.promotionCode,
55
- planStep.billingCountryCode,
56
- ],
57
- );
58
-
59
- return { previewSubscriptionAction };
60
- };
61
-
62
- export const usePreviewSubscription = () => {
63
- const [subscriptionPreview, setSubscriptionPreview] = useState<SubscriptionPreview | null>(null);
64
- const [isFetchingSubscriptionPreview, setIsFetchingSubscriptionPreview] = useState(false);
65
-
66
- const { previewSubscriptionAction } = usePreviewSubscriptionAction();
67
-
68
- useEffect(() => {
69
- const estimateSubscription = async () => {
70
- setIsFetchingSubscriptionPreview(true);
71
-
72
- const { subscriptionPreview } = await previewSubscriptionAction();
73
- setSubscriptionPreview(subscriptionPreview);
74
-
75
- setIsFetchingSubscriptionPreview(false);
76
- };
77
-
78
- void estimateSubscription();
79
- }, [previewSubscriptionAction]);
80
-
81
- return { subscriptionPreview, isFetchingSubscriptionPreview };
82
- };
@@ -1,89 +0,0 @@
1
- import { Addon } from '@stigg/js-client-sdk';
2
- import { useCheckoutContext } from '../CheckoutProvider';
3
-
4
- export enum CheckoutStepKey {
5
- PLAN = 'PLAN',
6
- ADDONS = 'ADDONS',
7
- PAYMENT = 'PAYMENT',
8
- }
9
-
10
- export type CheckoutStep = {
11
- key: CheckoutStepKey;
12
- label: string;
13
- };
14
-
15
- const CHECKOUT_STEPS: CheckoutStep[] = [
16
- { key: CheckoutStepKey.PLAN, label: 'Plan' },
17
- { key: CheckoutStepKey.ADDONS, label: 'Add-ons' },
18
- { key: CheckoutStepKey.PAYMENT, label: 'Payment details' },
19
- ];
20
-
21
- export type ProgressBarState = {
22
- activeStep: number;
23
- completedSteps: number[];
24
- steps: CheckoutStep[];
25
- };
26
-
27
- const INITIAL_STATE: ProgressBarState = {
28
- activeStep: 0,
29
- completedSteps: [],
30
- steps: CHECKOUT_STEPS,
31
- };
32
-
33
- export function getProgressBarInitialState({ availableAddons }: { availableAddons: Addon[] }) {
34
- if (availableAddons.length === 0) {
35
- return { ...INITIAL_STATE, steps: CHECKOUT_STEPS.filter(step => step.key !== CheckoutStepKey.ADDONS) };
36
- }
37
-
38
- return INITIAL_STATE;
39
- }
40
-
41
- function useProgressBarState() {
42
- const [{ progressBar }] = useCheckoutContext();
43
- return progressBar;
44
- }
45
-
46
- function useSetActiveStep() {
47
- const [, setState] = useCheckoutContext();
48
- return (stepNumber: number) =>
49
- setState(({ progressBar }) => {
50
- progressBar.activeStep = stepNumber;
51
- });
52
- }
53
- function useMarkStepAsCompleted() {
54
- const [, setState] = useCheckoutContext();
55
- return (stepNumber: number) =>
56
- setState(({ progressBar }) => {
57
- progressBar.completedSteps.push(stepNumber);
58
- });
59
- }
60
-
61
- function isCheckoutComplete(progressBar: ProgressBarState) {
62
- return progressBar.completedSteps.length >= progressBar.steps.length - 1;
63
- }
64
-
65
- function useGoNext() {
66
- const [, setState] = useCheckoutContext();
67
- return () =>
68
- setState(({ progressBar }) => {
69
- if (!progressBar.completedSteps.includes(progressBar.activeStep)) {
70
- progressBar.completedSteps.push(progressBar.activeStep);
71
- }
72
-
73
- if (progressBar.activeStep < progressBar.steps.length - 1) {
74
- progressBar.activeStep++;
75
- }
76
- });
77
- }
78
-
79
- export function useProgressBarModel() {
80
- const progressBarState = useProgressBarState();
81
- return {
82
- progressBarState,
83
- isLastStep: progressBarState.activeStep === progressBarState.steps.length - 1,
84
- isCheckoutComplete: isCheckoutComplete(progressBarState),
85
- setActiveStep: useSetActiveStep(),
86
- markStepAsCompleted: useMarkStepAsCompleted(),
87
- goNext: useGoNext(),
88
- };
89
- }
@@ -1,16 +0,0 @@
1
- import { useCheckoutContext } from '../CheckoutProvider';
2
- import { AddonsStepState } from './useAddonsStepModel';
3
- import { PromotionCodeState } from './useCouponModel';
4
- import { PlanStepState } from './usePlanStepModel';
5
-
6
- export type SubscriptionState = PlanStepState & PromotionCodeState & Pick<AddonsStepState, 'addons'>;
7
-
8
- export function useSubscriptionModel(): SubscriptionState {
9
- const [{ planStep, addonsStep, promotionCode }] = useCheckoutContext();
10
-
11
- return {
12
- ...planStep,
13
- addons: addonsStep.addons,
14
- promotionCode,
15
- };
16
- }
@@ -1,26 +0,0 @@
1
- import { ApplySubscription } from '@stigg/js-client-sdk';
2
- import { useCheckoutContext } from '../CheckoutProvider';
3
- import { useCheckoutModel } from './useCheckoutModel';
4
- import { useSubscriptionModel } from './useSubscriptionModel';
5
-
6
- export function useSubscriptionState(): ApplySubscription | undefined {
7
- const subscription = useSubscriptionModel();
8
- const [{ resourceId }] = useCheckoutContext();
9
- const { checkoutState } = useCheckoutModel();
10
- const { plan } = checkoutState || {};
11
- const addons = subscription.addons.map(({ addon, quantity }) => ({ addonId: addon.id, quantity }));
12
-
13
- if (!plan?.id) {
14
- return;
15
- }
16
-
17
- return {
18
- resourceId,
19
- planId: plan.id,
20
- billingPeriod: subscription.billingPeriod,
21
- billableFeatures: subscription.billableFeatures,
22
- addons,
23
- promotionCode: subscription.promotionCode,
24
- billingCountryCode: subscription.billingCountryCode,
25
- };
26
- }
@@ -1,3 +0,0 @@
1
- export { CheckoutConfiguration } from './types';
2
- export { Checkout, CheckoutProps } from './Checkout';
3
- export { CheckoutLocalization } from './textOverrides';
@@ -1,23 +0,0 @@
1
- import styled from '@emotion/styled/macro';
2
- import { Box } from '@mui/material';
3
-
4
- import ArrowRightIcon from '../../../assets/arrow-right.svg';
5
-
6
- export const PlanPathContainer = styled(Box)`
7
- display: flex;
8
- align-items: baseline;
9
- gap: 8px;
10
- `;
11
-
12
- export const StyledArrowRightIcon = styled(ArrowRightIcon)`
13
- path {
14
- stroke: ${({ theme }) => theme.stigg.palette.text.secondary};
15
- }
16
- `;
17
-
18
- export const PlanHeaderContainer = styled(Box)`
19
- display: flex;
20
- align-content: center;
21
- justify-content: space-between;
22
- margin-bottom: 32px;
23
- `;
@@ -1,61 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Button, Divider } from '@mui/material';
4
-
5
- import { Typography } from '../../common/Typography';
6
- import { useCheckoutModel } from '../hooks/useCheckoutModel';
7
- import { PlanHeaderContainer, PlanPathContainer, StyledArrowRightIcon } from './PlanHeader.style';
8
- import { CheckoutContainerProps } from '../CheckoutContainer';
9
-
10
- type PlanHeaderProps = {
11
- allowChangePlan?: boolean;
12
- } & Pick<CheckoutContainerProps, 'onChangePlan'>;
13
-
14
- export function PlanHeader({ allowChangePlan = false, onChangePlan }: PlanHeaderProps) {
15
- const { checkoutState, checkoutLocalization } = useCheckoutModel();
16
- const { plan, activeSubscription } = checkoutState || {};
17
- const isPlanChanged = plan?.id !== activeSubscription?.plan.id;
18
-
19
- return (
20
- <>
21
- <PlanHeaderContainer>
22
- <PlanPathContainer>
23
- {activeSubscription && isPlanChanged && (
24
- <>
25
- <Typography variant="h6" color="secondary">
26
- {activeSubscription.plan.displayName}
27
- </Typography>
28
- <StyledArrowRightIcon />
29
- </>
30
- )}
31
-
32
- <Typography variant="h3" bold>
33
- {plan?.displayName}
34
- </Typography>
35
- </PlanPathContainer>
36
-
37
- {allowChangePlan && onChangePlan && (
38
- <Button
39
- className="stigg-checkout-change-plan-button"
40
- sx={{ textTransform: 'none' }}
41
- variant="text"
42
- size="medium"
43
- onClick={() => {
44
- onChangePlan({ currentPlan: plan });
45
- }}
46
- >
47
- <Typography
48
- className="stigg-checkout-change-plan-button-text"
49
- color="primary.main"
50
- style={{ lineHeight: '24px' }}
51
- variant="body1"
52
- >
53
- {checkoutLocalization.changePlan}
54
- </Typography>
55
- </Button>
56
- )}
57
- </PlanHeaderContainer>
58
- <Divider className="stigg-checkout-plan-header-divider" />
59
- </>
60
- );
61
- }
@@ -1 +0,0 @@
1
- export * from './PlanHeader';
@@ -1,29 +0,0 @@
1
- import styled from '@emotion/styled/macro';
2
- import { Button, buttonClasses, LinearProgress, linearProgressClasses } from '@mui/material';
3
-
4
- import { Icon } from '../../common/Icon';
5
-
6
- export const StyledProgress = styled(LinearProgress)(({ theme }) => ({
7
- [`&.${linearProgressClasses.root}`]: {
8
- borderRadius: theme.stigg.border.radius,
9
- backgroundColor: theme.stigg.palette.outlinedBorder,
10
- },
11
- [`&.${linearProgressClasses.bar}`]: {
12
- backgroundColor: theme.stigg.palette.primary,
13
- },
14
- }));
15
-
16
- export const StyledStepButton = styled(Button)(() => ({
17
- [`&.${buttonClasses.root}`]: {
18
- textTransform: 'none',
19
- lineHeight: 'inherit',
20
- justifyContent: 'flex-start',
21
- padding: '8px 4px',
22
- },
23
- }));
24
-
25
- export const StyledIcon = styled(Icon)<{ $disabled?: boolean }>(({ theme, $disabled }) => ({
26
- circle: {
27
- stroke: $disabled ? theme.stigg.palette.text.disabled : theme.stigg.palette.primary,
28
- },
29
- }));
@@ -1,48 +0,0 @@
1
- import React from 'react';
2
-
3
- import { Box, StepIcon, Grid } from '@mui/material';
4
-
5
- import { useProgressBarModel } from '../hooks';
6
-
7
- import { Typography } from '../../common/Typography';
8
- import { StyledProgress, StyledStepButton, StyledIcon } from './CheckoutProgressBar.style';
9
-
10
- export const CheckoutProgressBar = () => {
11
- const { progressBarState, setActiveStep } = useProgressBarModel();
12
- const { activeStep, completedSteps } = progressBarState || {};
13
- const progress = ((activeStep + 1) * 100) / progressBarState.steps.length;
14
-
15
- return (
16
- <Box sx={{ width: '100%', my: 3 }}>
17
- <StyledProgress variant="determinate" value={progress} />
18
- <Grid container display="flex">
19
- {progressBarState.steps.map(({ key, label }, index) => {
20
- const isCompleted = completedSteps.includes(index);
21
- const isDisabled = index > activeStep && !isCompleted && !completedSteps.includes(index - 1);
22
-
23
- return (
24
- <Grid key={key} item display="flex" flexDirection="row" flex={1} justifyContent="flex-start">
25
- <StyledStepButton onClick={() => setActiveStep(index)} fullWidth disabled={isDisabled}>
26
- <Grid item display="flex" flexDirection="row" alignItems="center" gap={1}>
27
- <StepIcon
28
- icon={
29
- isCompleted ? (
30
- <StyledIcon icon="OutlinedCheckedCircle" />
31
- ) : (
32
- <StyledIcon icon="OutlinedCircle" $disabled={isDisabled} />
33
- )
34
- }
35
- />
36
-
37
- <Typography variant="h6" color={isDisabled ? 'disabled' : 'primary.main'}>
38
- {label}
39
- </Typography>
40
- </Grid>
41
- </StyledStepButton>
42
- </Grid>
43
- );
44
- })}
45
- </Grid>
46
- </Box>
47
- );
48
- };
@@ -1,85 +0,0 @@
1
- import React, { useState } from 'react';
2
-
3
- import styled from '@emotion/styled/macro';
4
- import { CircularProgress, Grid } from '@mui/material';
5
-
6
- import { Icon } from '../../common/Icon';
7
- import { Typography } from '../../common/Typography';
8
- import { Button, InputField } from '../components';
9
- import { usePreviewSubscriptionAction } from '../hooks';
10
- import { usePromotionCodeModel } from '../hooks/useCouponModel';
11
- import { AddPromotionCodeButton } from './AddPromotionCodeButton';
12
- import { CheckoutLocalization } from '../textOverrides';
13
-
14
- const CouponCodeAddButton = styled(Button)`
15
- padding: 4px 10px;
16
- min-width: unset;
17
- border-radius: ${({ theme }) => theme.stigg.border.radius};
18
- display: flex;
19
- align-items: center;
20
- `;
21
-
22
- export const AddPromotionCode = ({ checkoutLocalization }: { checkoutLocalization: CheckoutLocalization }) => {
23
- const { setPromotionCode: persistPromotionCode } = usePromotionCodeModel();
24
- const [showInput, setShowInput] = useState(false);
25
- const [promotionCode, setPromotionCode] = React.useState('');
26
- const [isLoading, setIsLoading] = React.useState(false);
27
- const [errorMessage, setErrorMessage] = React.useState('');
28
- const { previewSubscriptionAction } = usePreviewSubscriptionAction();
29
-
30
- const handlePromotionCode = async () => {
31
- setIsLoading(true);
32
- setErrorMessage('');
33
-
34
- const { subscriptionPreview, errorMessage } = await previewSubscriptionAction({ promotionCode });
35
-
36
- if (!errorMessage && subscriptionPreview?.discount) {
37
- persistPromotionCode(promotionCode.toUpperCase());
38
- setShowInput(false);
39
- } else if (!!errorMessage) {
40
- setErrorMessage(errorMessage);
41
- }
42
- setIsLoading(false);
43
- };
44
-
45
- if (!showInput) {
46
- return <AddPromotionCodeButton onAddClick={() => setShowInput(true)} checkoutLocalization={checkoutLocalization} />;
47
- }
48
-
49
- return (
50
- <Grid>
51
- <Typography variant="body1" color={errorMessage ? 'error' : 'primary.main'}>
52
- {checkoutLocalization.couponCodeTitle}
53
- </Typography>
54
-
55
- <InputField
56
- autoFocus
57
- variant="outlined"
58
- fullWidth
59
- error={!!errorMessage}
60
- value={promotionCode}
61
- onChange={(e) => {
62
- setPromotionCode(e.target.value);
63
- }}
64
- inputProps={{ maxLength: 20 }}
65
- InputProps={{
66
- endAdornment: (
67
- <CouponCodeAddButton
68
- variant="contained"
69
- disableRipple={isLoading}
70
- $isLoading={isLoading}
71
- onClick={handlePromotionCode}
72
- >
73
- {isLoading ? <CircularProgress size={18} /> : <Icon style={{ display: 'flex' }} icon="ArrowForward" />}
74
- </CouponCodeAddButton>
75
- ),
76
- }}
77
- />
78
- {!!errorMessage && (
79
- <Typography variant="body1" color="error">
80
- {errorMessage}
81
- </Typography>
82
- )}
83
- </Grid>
84
- );
85
- };
@@ -1,39 +0,0 @@
1
- import React from 'react';
2
- import styled from '@emotion/styled/macro';
3
-
4
- import PlusIcon from '../../../assets/plus-icon.svg';
5
- import { Typography } from '../../common/Typography';
6
- import { Button } from '../components';
7
- import { CheckoutLocalization } from '../textOverrides';
8
-
9
- const StyledPlusIcon = styled(PlusIcon)`
10
- path {
11
- stroke: ${({ theme }) => theme.stigg.palette.primary};
12
- }
13
- `;
14
-
15
- export type AddPromotionCodeButtonProps = {
16
- onAddClick: () => void;
17
- checkoutLocalization: CheckoutLocalization;
18
- };
19
-
20
- export const AddPromotionCodeButton = ({ onAddClick, checkoutLocalization }: AddPromotionCodeButtonProps) => (
21
- <Button
22
- fullWidth
23
- className="stigg-checkout-summary-add-coupon-code-button"
24
- sx={{ textTransform: 'none', justifyContent: 'flex-start' }}
25
- variant="text"
26
- size="medium"
27
- onClick={onAddClick}
28
- >
29
- <StyledPlusIcon className="stigg-checkout-summary-add-coupon-code-button-icon" />
30
- <Typography
31
- className="stigg-checkout-change-plan-button-text"
32
- color="primary.main"
33
- style={{ lineHeight: '24px' }}
34
- variant="body1"
35
- >
36
- {checkoutLocalization.addCouponCodeText}
37
- </Typography>
38
- </Button>
39
- );