@stigg/react-sdk 4.3.0 → 4.4.0-beta.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/README.md +1 -1
- package/dist/components/checkout/Checkout.d.ts +5 -0
- package/dist/components/checkout/CheckoutContainer.d.ts +22 -0
- package/dist/components/checkout/CheckoutContainer.style.d.ts +26 -0
- package/dist/components/checkout/CheckoutProvider.d.ts +34 -0
- package/dist/components/checkout/components/Button.d.ts +8 -0
- package/dist/components/checkout/components/ContentLoadingSkeleton.d.ts +2 -0
- package/dist/components/checkout/components/InputField.d.ts +8 -0
- package/dist/components/checkout/components/Skeletons.style.d.ts +97 -0
- package/dist/components/checkout/components/index.d.ts +3 -0
- package/dist/components/checkout/formatting.d.ts +2 -0
- package/dist/components/checkout/hooks/index.d.ts +8 -0
- package/dist/components/checkout/hooks/useAddonsStepModel.d.ts +21 -0
- package/dist/components/checkout/hooks/useCheckoutModel.d.ts +10 -0
- package/dist/components/checkout/hooks/useCouponModel.d.ts +7 -0
- package/dist/components/checkout/hooks/useLoadCheckout.d.ts +11 -0
- package/dist/components/checkout/hooks/usePaymentStepModel.d.ts +16 -0
- package/dist/components/checkout/hooks/usePlanStepModel.d.ts +23 -0
- package/dist/components/checkout/hooks/usePreviewSubscription.d.ts +13 -0
- package/dist/components/checkout/hooks/useProgressBarModel.d.ts +26 -0
- package/dist/components/checkout/hooks/useSubscriptionModel.d.ts +5 -0
- package/dist/components/checkout/hooks/useSubscriptionState.d.ts +2 -0
- package/dist/components/checkout/index.d.ts +3 -0
- package/dist/components/checkout/planHeader/PlanHeader.d.ts +7 -0
- package/dist/components/checkout/planHeader/PlanHeader.style.d.ts +25 -0
- package/dist/components/checkout/planHeader/index.d.ts +1 -0
- package/dist/components/checkout/progressBar/CheckoutProgressBar.d.ts +2 -0
- package/dist/components/checkout/progressBar/CheckoutProgressBar.style.d.ts +48 -0
- package/dist/components/checkout/promotionCode/AddPromotionCode.d.ts +5 -0
- package/dist/components/checkout/promotionCode/AddPromotionCodeButton.d.ts +7 -0
- package/dist/components/checkout/promotionCode/AppliedPromotionCode.d.ts +6 -0
- package/dist/components/checkout/promotionCode/PromotionCodeSection.d.ts +5 -0
- package/dist/components/checkout/promotionCode/index.d.ts +1 -0
- package/dist/components/checkout/steps/addons/CheckoutAddonsStep.d.ts +2 -0
- package/dist/components/checkout/steps/addons/CheckoutAddonsStep.style.d.ts +93 -0
- package/dist/components/checkout/steps/addons/addon.utils.d.ts +15 -0
- package/dist/components/checkout/steps/addons/index.d.ts +1 -0
- package/dist/components/checkout/steps/payment/PaymentMethods.d.ts +20 -0
- package/dist/components/checkout/steps/payment/PaymentMethods.style.d.ts +117 -0
- package/dist/components/checkout/steps/payment/PaymentStep.d.ts +2 -0
- package/dist/components/checkout/steps/payment/index.d.ts +1 -0
- package/dist/components/checkout/steps/payment/stripe/StripePaymentForm.d.ts +2 -0
- package/dist/components/checkout/steps/payment/stripe/index.d.ts +3 -0
- package/dist/components/checkout/steps/payment/stripe/stripe.utils.d.ts +33 -0
- package/dist/components/checkout/steps/payment/stripe/useStripeIntegration.d.ts +5 -0
- package/dist/components/checkout/steps/payment/stripe/useSubmit.d.ts +13 -0
- package/dist/components/checkout/steps/plan/BillingPeriodPicker.d.ts +9 -0
- package/dist/components/checkout/steps/plan/BillingPeriodPicker.style.d.ts +52 -0
- package/dist/components/checkout/steps/plan/CheckoutChargeList.d.ts +16 -0
- package/dist/components/checkout/steps/plan/CheckoutPlanStep.d.ts +2 -0
- package/dist/components/checkout/steps/plan/CheckoutPlanStep.style.d.ts +12 -0
- package/dist/components/checkout/steps/plan/index.d.ts +1 -0
- package/dist/components/checkout/steps/surprise/SurpriseStep.d.ts +2 -0
- package/dist/components/checkout/summary/CheckoutSuccess.d.ts +3 -0
- package/dist/components/checkout/summary/CheckoutSummary.d.ts +16 -0
- package/dist/components/checkout/summary/CheckoutSummarySkeleton.d.ts +2 -0
- package/dist/components/checkout/summary/components/CheckoutCaptions.d.ts +11 -0
- package/dist/components/checkout/summary/components/LineItems.d.ts +36 -0
- package/dist/components/checkout/summary/components/WithSkeleton.d.ts +6 -0
- package/dist/components/checkout/summary/index.d.ts +2 -0
- package/dist/components/checkout/textOverrides.d.ts +32 -0
- package/dist/components/checkout/theme.d.ts +12 -0
- package/dist/components/common/Icon.d.ts +3 -2
- package/dist/components/common/PoweredByStigg.d.ts +1 -1
- package/dist/components/{paywall/TiersLayout.d.ts → common/TiersSelectContainer.d.ts} +2 -3
- package/dist/components/common/customIcons.d.ts +19 -5
- package/dist/components/common/mapExternalTheme.d.ts +2 -1
- package/dist/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.d.ts +1 -1
- package/dist/components/hooks/useChargeSort.d.ts +3 -0
- package/dist/components/paywall/paywallTextOverrides.d.ts +0 -2
- package/dist/components/utils/calculateDiscountRate.d.ts +1 -0
- package/dist/components/utils/currencyUtils.d.ts +1 -1
- package/dist/components/{paywall/planPriceTier.d.ts → utils/priceTierUtils.d.ts} +3 -1
- package/dist/components/utils/priceUtils.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/react-sdk.cjs.development.js +6930 -228
- package/dist/react-sdk.cjs.development.js.map +1 -1
- package/dist/react-sdk.cjs.production.min.js +1 -1
- package/dist/react-sdk.cjs.production.min.js.map +1 -1
- package/dist/react-sdk.esm.js +7089 -232
- package/dist/react-sdk.esm.js.map +1 -1
- package/dist/stories/Checkout.stories.d.ts +3 -0
- package/dist/stories/CustomerPortal.stories.d.ts +1 -1
- package/dist/theme/getResolvedTheme.d.ts +4 -0
- package/dist/theme/types.d.ts +4 -0
- package/package.json +11 -5
- package/src/assets/arrow-forward.svg +3 -0
- package/src/assets/arrow-right.svg +6 -0
- package/src/assets/check.svg +5 -0
- package/src/assets/close.svg +3 -0
- package/src/assets/lottie/checkout-success.json +1 -0
- package/src/assets/nyancat.svg +634 -0
- package/src/assets/outlined-checked-circle-disabled.svg +6 -0
- package/src/assets/outlined-checked-circle.svg +6 -0
- package/src/assets/outlined-circle.svg +3 -0
- package/src/assets/payment-method.svg +11 -0
- package/src/assets/plus-icon.svg +6 -0
- package/src/assets/trash.svg +8 -0
- package/src/components/checkout/Checkout.tsx +30 -0
- package/src/components/checkout/CheckoutContainer.style.ts +35 -0
- package/src/components/checkout/CheckoutContainer.tsx +99 -0
- package/src/components/checkout/CheckoutProvider.tsx +149 -0
- package/src/components/checkout/components/Button.tsx +51 -0
- package/src/components/checkout/components/ContentLoadingSkeleton.tsx +41 -0
- package/src/components/checkout/components/InputField.tsx +22 -0
- package/src/components/checkout/components/Skeletons.style.ts +27 -0
- package/src/components/checkout/components/index.ts +3 -0
- package/src/components/checkout/formatting.ts +12 -0
- package/src/components/checkout/hooks/index.ts +8 -0
- package/src/components/checkout/hooks/useAddonsStepModel.ts +96 -0
- package/src/components/checkout/hooks/useCheckoutModel.ts +32 -0
- package/src/components/checkout/hooks/useCouponModel.ts +28 -0
- package/src/components/checkout/hooks/useLoadCheckout.ts +39 -0
- package/src/components/checkout/hooks/usePaymentStepModel.ts +49 -0
- package/src/components/checkout/hooks/usePlanStepModel.ts +169 -0
- package/src/components/checkout/hooks/usePreviewSubscription.ts +82 -0
- package/src/components/checkout/hooks/useProgressBarModel.ts +89 -0
- package/src/components/checkout/hooks/useSubscriptionModel.ts +16 -0
- package/src/components/checkout/hooks/useSubscriptionState.ts +26 -0
- package/src/components/checkout/index.ts +3 -0
- package/src/components/checkout/planHeader/PlanHeader.style.tsx +23 -0
- package/src/components/checkout/planHeader/PlanHeader.tsx +59 -0
- package/src/components/checkout/planHeader/index.ts +1 -0
- package/src/components/checkout/progressBar/CheckoutProgressBar.style.ts +34 -0
- package/src/components/checkout/progressBar/CheckoutProgressBar.tsx +53 -0
- package/src/components/checkout/promotionCode/AddPromotionCode.tsx +85 -0
- package/src/components/checkout/promotionCode/AddPromotionCodeButton.tsx +39 -0
- package/src/components/checkout/promotionCode/AppliedPromotionCode.tsx +37 -0
- package/src/components/checkout/promotionCode/PromotionCodeSection.tsx +27 -0
- package/src/components/checkout/promotionCode/index.ts +1 -0
- package/src/components/checkout/steps/addons/CheckoutAddonsStep.style.tsx +24 -0
- package/src/components/checkout/steps/addons/CheckoutAddonsStep.tsx +125 -0
- package/src/components/checkout/steps/addons/addon.utils.ts +68 -0
- package/src/components/checkout/steps/addons/index.ts +1 -0
- package/src/components/checkout/steps/payment/PaymentMethods.style.ts +26 -0
- package/src/components/checkout/steps/payment/PaymentMethods.tsx +86 -0
- package/src/components/checkout/steps/payment/PaymentStep.tsx +50 -0
- package/src/components/checkout/steps/payment/index.ts +1 -0
- package/src/components/checkout/steps/payment/stripe/StripePaymentForm.tsx +45 -0
- package/src/components/checkout/steps/payment/stripe/index.ts +3 -0
- package/src/components/checkout/steps/payment/stripe/stripe.utils.ts +109 -0
- package/src/components/checkout/steps/payment/stripe/useStripeIntegration.ts +27 -0
- package/src/components/checkout/steps/payment/stripe/useSubmit.ts +104 -0
- package/src/components/checkout/steps/plan/BillingPeriodPicker.style.tsx +46 -0
- package/src/components/checkout/steps/plan/BillingPeriodPicker.tsx +63 -0
- package/src/components/checkout/steps/plan/CheckoutChargeList.tsx +138 -0
- package/src/components/checkout/steps/plan/CheckoutPlanStep.style.tsx +6 -0
- package/src/components/checkout/steps/plan/CheckoutPlanStep.tsx +20 -0
- package/src/components/checkout/steps/plan/index.ts +1 -0
- package/src/components/checkout/steps/surprise/SurpriseStep.tsx +27 -0
- package/src/components/checkout/summary/CheckoutSuccess.tsx +32 -0
- package/src/components/checkout/summary/CheckoutSummary.tsx +288 -0
- package/src/components/checkout/summary/CheckoutSummarySkeleton.tsx +40 -0
- package/src/components/checkout/summary/components/CheckoutCaptions.tsx +120 -0
- package/src/components/checkout/summary/components/LineItems.tsx +177 -0
- package/src/components/checkout/summary/components/WithSkeleton.tsx +16 -0
- package/src/components/checkout/summary/index.ts +2 -0
- package/src/components/checkout/textOverrides.ts +62 -0
- package/src/components/checkout/theme.ts +43 -0
- package/src/components/common/Icon.tsx +17 -22
- package/src/components/common/PoweredByStigg.tsx +1 -1
- package/src/components/{paywall/TiersLayout.tsx → common/TiersSelectContainer.tsx} +8 -7
- package/src/components/common/Typography.tsx +11 -1
- package/src/components/common/customIcons.ts +19 -28
- package/src/components/common/mapExternalTheme.ts +29 -9
- package/src/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.tsx +6 -12
- package/src/components/hooks/useChargeSort.ts +17 -0
- package/src/components/paywall/Paywall.tsx +1 -1
- package/src/components/paywall/PlanOffering.tsx +1 -1
- package/src/components/paywall/PlanOfferingButton.tsx +1 -1
- package/src/components/paywall/PlanPrice.tsx +5 -13
- package/src/components/paywall/paywallTextOverrides.ts +0 -1
- package/src/components/paywall/utils/calculateUnitQuantityText.ts +9 -4
- package/src/components/utils/calculateDiscountRate.ts +1 -1
- package/src/components/utils/currencyUtils.ts +1 -1
- package/src/components/utils/getPaidPriceText.ts +2 -2
- package/src/components/{paywall/planPriceTier.ts → utils/priceTierUtils.ts} +25 -3
- package/src/components/utils/priceUtils.ts +10 -0
- package/src/index.ts +1 -0
- package/src/stories/Checkout.stories.tsx +61 -0
- package/src/stories/CustomerPortal.stories.tsx +1 -1
- package/src/theme/Theme.tsx +6 -6
- package/src/theme/getResolvedTheme.ts +7 -1
- package/src/theme/types.ts +4 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useCheckoutContext } from '../CheckoutProvider';
|
|
2
|
+
|
|
3
|
+
export type PromotionCodeState = {
|
|
4
|
+
promotionCode?: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
function usePromotionCodeState() {
|
|
8
|
+
const [{ promotionCode }] = useCheckoutContext();
|
|
9
|
+
return promotionCode;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function useSetPromotionCode() {
|
|
13
|
+
const [, setState] = useCheckoutContext();
|
|
14
|
+
|
|
15
|
+
return (promotionCode: string) =>
|
|
16
|
+
setState(draft => {
|
|
17
|
+
draft.promotionCode = promotionCode;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function usePromotionCodeModel() {
|
|
22
|
+
const promotionCode = usePromotionCodeState();
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
promotionCode,
|
|
26
|
+
setPromotionCode: useSetPromotionCode(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { GetCheckoutStateResults } from '@stigg/js-client-sdk';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import logger from '../../../services/logger';
|
|
4
|
+
import { useStiggContext } from '../../StiggProvider';
|
|
5
|
+
|
|
6
|
+
type UseLoadCheckoutProps = {
|
|
7
|
+
planId: string;
|
|
8
|
+
resourceId?: string;
|
|
9
|
+
billingCountryCode?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function useLoadCheckout({ planId, resourceId, billingCountryCode }: UseLoadCheckoutProps) {
|
|
13
|
+
const { stigg } = useStiggContext();
|
|
14
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
15
|
+
const [checkout, setCheckout] = useState<GetCheckoutStateResults | null>();
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
const loadCheckout = async () => {
|
|
19
|
+
try {
|
|
20
|
+
const checkout = await stigg.getCheckoutState({ planId, resourceId, billingCountryCode });
|
|
21
|
+
setCheckout(checkout);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
logger.error(`Failed to load checkout ${(err as any)?.message}`, err as any);
|
|
24
|
+
} finally {
|
|
25
|
+
setIsLoading(false);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
if (stigg.isCustomerLoaded) {
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
void loadCheckout();
|
|
32
|
+
}
|
|
33
|
+
}, [stigg, stigg.isCustomerLoaded, resourceId, planId, billingCountryCode]);
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
checkout,
|
|
37
|
+
isLoading,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Customer } from '@stigg/js-client-sdk';
|
|
2
|
+
|
|
3
|
+
import { useCheckoutContext } from '../CheckoutProvider';
|
|
4
|
+
|
|
5
|
+
export type PaymentStepState = {
|
|
6
|
+
useNewPaymentMethod: boolean;
|
|
7
|
+
errorMessage?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
type GetPaymentStepInitialStateProps = {
|
|
11
|
+
customer?: Customer;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function getPaymentStepInitialState({ customer }: GetPaymentStepInitialStateProps): PaymentStepState {
|
|
15
|
+
return { useNewPaymentMethod: !customer?.paymentMethodDetails };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function useSetUseNewPaymentMethod() {
|
|
19
|
+
const [, setState] = useCheckoutContext();
|
|
20
|
+
|
|
21
|
+
return (useNewPaymentMethod: boolean) =>
|
|
22
|
+
setState((draft) => {
|
|
23
|
+
draft.paymentStep.useNewPaymentMethod = useNewPaymentMethod;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function useSetErrorMessage() {
|
|
28
|
+
const [, setState] = useCheckoutContext();
|
|
29
|
+
|
|
30
|
+
return (errorMessage?: string) =>
|
|
31
|
+
setState((draft) => {
|
|
32
|
+
draft.paymentStep.errorMessage = errorMessage;
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function usePaymentState() {
|
|
37
|
+
const [{ paymentStep }] = useCheckoutContext();
|
|
38
|
+
return paymentStep;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function usePaymentStepModel() {
|
|
42
|
+
const state = usePaymentState();
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
...state,
|
|
46
|
+
setUseNewPaymentMethod: useSetUseNewPaymentMethod(),
|
|
47
|
+
setErrorMessage: useSetErrorMessage(),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import keyBy from 'lodash/keyBy';
|
|
2
|
+
import compact from 'lodash/compact';
|
|
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
|
+
import { useCheckoutContext } from '../CheckoutProvider';
|
|
6
|
+
import { getTierByQuantity } from '../../utils/priceTierUtils';
|
|
7
|
+
import { getValidPriceQuantity } from '../../utils/priceUtils';
|
|
8
|
+
|
|
9
|
+
export type PlanStepState = {
|
|
10
|
+
billingPeriod: BillingPeriod;
|
|
11
|
+
billableFeatures: BillableFeatureInput[];
|
|
12
|
+
billingCountryCode?: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type GetPlanStepInitialStateProps = {
|
|
16
|
+
preferredBillingPeriod?: BillingPeriod;
|
|
17
|
+
plan?: Plan;
|
|
18
|
+
activeSubscription?: Subscription | null;
|
|
19
|
+
billingCountryCode?: string;
|
|
20
|
+
preconfiguredBillableFeatures: BillableFeature[];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const isInAdvanceCommitmentCharge = ({ pricingModel }: Price) => {
|
|
24
|
+
return pricingModel === BillingModel.PerUnit;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
function getBillableFeatures(
|
|
28
|
+
preconfiguredBillableFeatures: BillableFeature[],
|
|
29
|
+
planPrices?: Price[],
|
|
30
|
+
activeSubscription?: Subscription | null,
|
|
31
|
+
): BillableFeature[] {
|
|
32
|
+
if (!planPrices) return [];
|
|
33
|
+
|
|
34
|
+
const preconfBillableFeaturesByFeatureId = keyBy(preconfiguredBillableFeatures, 'featureId');
|
|
35
|
+
|
|
36
|
+
const quantityByFeatureId = keyBy(
|
|
37
|
+
compact(
|
|
38
|
+
activeSubscription?.prices?.map((charge) => {
|
|
39
|
+
const { feature } = charge;
|
|
40
|
+
if (!feature || !isInAdvanceCommitmentCharge(charge)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
featureId: feature.featureId,
|
|
46
|
+
quantity: feature.unitQuantity || null,
|
|
47
|
+
};
|
|
48
|
+
}),
|
|
49
|
+
),
|
|
50
|
+
'featureId',
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return compact(
|
|
54
|
+
planPrices?.map((price) => {
|
|
55
|
+
const featureId = price.feature?.featureId;
|
|
56
|
+
if (!featureId || !isInAdvanceCommitmentCharge(price)) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let quantity;
|
|
61
|
+
const preconfiguredQuantity =
|
|
62
|
+
preconfBillableFeaturesByFeatureId[featureId]?.quantity || quantityByFeatureId[featureId]?.quantity;
|
|
63
|
+
|
|
64
|
+
quantity = getValidPriceQuantity(price, preconfiguredQuantity || 1);
|
|
65
|
+
|
|
66
|
+
if (price.isTieredPrice) {
|
|
67
|
+
const tier = getTierByQuantity(price.tiers!, quantity);
|
|
68
|
+
quantity = tier!.upTo;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
featureId,
|
|
73
|
+
quantity,
|
|
74
|
+
};
|
|
75
|
+
}),
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function resolveBillingPeriod({
|
|
80
|
+
plan,
|
|
81
|
+
activeSubscription,
|
|
82
|
+
preferredBillingPeriod,
|
|
83
|
+
}: {
|
|
84
|
+
plan?: Plan;
|
|
85
|
+
activeSubscription?: Subscription | null;
|
|
86
|
+
preferredBillingPeriod?: BillingPeriod;
|
|
87
|
+
}) {
|
|
88
|
+
const hasMonthlyPrices = plan?.pricePoints.some((pricePoint) => pricePoint.billingPeriod === BillingPeriod.Monthly);
|
|
89
|
+
const hasAnnualPrices = plan?.pricePoints.some((pricePoint) => pricePoint.billingPeriod === BillingPeriod.Annually);
|
|
90
|
+
|
|
91
|
+
const isUpdate = activeSubscription?.plan?.id === plan?.id;
|
|
92
|
+
if (isUpdate) {
|
|
93
|
+
return activeSubscription?.price?.billingPeriod || BillingPeriod.Monthly;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (preferredBillingPeriod) {
|
|
97
|
+
if (preferredBillingPeriod === BillingPeriod.Monthly && hasMonthlyPrices) {
|
|
98
|
+
return BillingPeriod.Monthly;
|
|
99
|
+
}
|
|
100
|
+
if (preferredBillingPeriod === BillingPeriod.Annually && hasAnnualPrices) {
|
|
101
|
+
return BillingPeriod.Annually;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (activeSubscription?.price?.billingPeriod) {
|
|
106
|
+
return activeSubscription?.price?.billingPeriod;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return hasAnnualPrices ? BillingPeriod.Annually : BillingPeriod.Monthly;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function getPlanStepInitialState({
|
|
113
|
+
preferredBillingPeriod,
|
|
114
|
+
plan,
|
|
115
|
+
activeSubscription,
|
|
116
|
+
billingCountryCode,
|
|
117
|
+
preconfiguredBillableFeatures,
|
|
118
|
+
}: GetPlanStepInitialStateProps): PlanStepState {
|
|
119
|
+
const billingPeriod = resolveBillingPeriod({ plan, activeSubscription, preferredBillingPeriod });
|
|
120
|
+
const planPrices = plan?.pricePoints.filter((pricePoint) => pricePoint.billingPeriod === billingPeriod);
|
|
121
|
+
const billableFeatures = getBillableFeatures(preconfiguredBillableFeatures, planPrices, activeSubscription);
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
billingPeriod,
|
|
125
|
+
billableFeatures,
|
|
126
|
+
billingCountryCode,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function usePlanState() {
|
|
131
|
+
const [{ planStep }] = useCheckoutContext();
|
|
132
|
+
return planStep;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function useSetBillableFeature() {
|
|
136
|
+
const [, setState] = useCheckoutContext();
|
|
137
|
+
|
|
138
|
+
return (featureId: string, quantity: number) =>
|
|
139
|
+
setState((draft) => {
|
|
140
|
+
const billableFeature = draft.planStep.billableFeatures.find(
|
|
141
|
+
(billableFeature) => billableFeature.featureId === featureId,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
if (billableFeature) {
|
|
145
|
+
billableFeature.quantity = quantity;
|
|
146
|
+
} else {
|
|
147
|
+
draft.planStep.billableFeatures.push({ featureId, quantity });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function useSetBillingPeriod() {
|
|
153
|
+
const [, setState] = useCheckoutContext();
|
|
154
|
+
|
|
155
|
+
return (billingPeriod: BillingPeriod) =>
|
|
156
|
+
setState((draft) => {
|
|
157
|
+
draft.planStep.billingPeriod = billingPeriod;
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export function usePlanStepModel() {
|
|
162
|
+
const state = usePlanState();
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
...state,
|
|
166
|
+
setBillingPeriod: useSetBillingPeriod(),
|
|
167
|
+
setBillableFeature: useSetBillableFeature(),
|
|
168
|
+
};
|
|
169
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
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
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
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 += 1;
|
|
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
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
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
|
+
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
<Typography
|
|
47
|
+
className="stigg-checkout-change-plan-button-text"
|
|
48
|
+
color="primary.main"
|
|
49
|
+
style={{ lineHeight: '24px' }}
|
|
50
|
+
variant="body1">
|
|
51
|
+
{checkoutLocalization.changePlan}
|
|
52
|
+
</Typography>
|
|
53
|
+
</Button>
|
|
54
|
+
)}
|
|
55
|
+
</PlanHeaderContainer>
|
|
56
|
+
<Divider className="stigg-checkout-plan-header-divider" />
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './PlanHeader';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import styled from '@emotion/styled/macro';
|
|
2
|
+
import { Button, buttonClasses, LinearProgress, linearProgressClasses } from '@mui/material';
|
|
3
|
+
import Color from 'color';
|
|
4
|
+
|
|
5
|
+
import { Icon } from '../../common/Icon';
|
|
6
|
+
|
|
7
|
+
export const StyledProgress = styled(LinearProgress)<{ $disabled?: boolean }>(({ theme, $disabled }) => ({
|
|
8
|
+
[`&.${linearProgressClasses.root}`]: {
|
|
9
|
+
borderRadius: theme.stigg.border.radius,
|
|
10
|
+
backgroundColor: theme.stigg.palette.outlinedBorder,
|
|
11
|
+
},
|
|
12
|
+
[`& .${linearProgressClasses.bar}`]: {
|
|
13
|
+
backgroundColor: $disabled
|
|
14
|
+
? Color(theme.stigg.palette.outlinedBorder).darken(0.2).hex()
|
|
15
|
+
: theme.stigg.palette.primary,
|
|
16
|
+
},
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
export const StyledStepButton = styled(Button)(() => ({
|
|
20
|
+
[`&.${buttonClasses.root}`]: {
|
|
21
|
+
textTransform: 'none',
|
|
22
|
+
lineHeight: 'inherit',
|
|
23
|
+
justifyContent: 'flex-start',
|
|
24
|
+
padding: '8px 4px',
|
|
25
|
+
},
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
export const StyledIcon = styled(Icon)<{ $disabled?: boolean; $shouldStroke?: boolean }>(
|
|
29
|
+
({ theme, $disabled, $shouldStroke = true }) => ({
|
|
30
|
+
circle: {
|
|
31
|
+
stroke: $shouldStroke ? ($disabled ? theme.stigg.palette.text.disabled : theme.stigg.palette.primary) : undefined,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, StepIcon, Grid } from '@mui/material';
|
|
3
|
+
import { useCheckoutModel, useProgressBarModel } from '../hooks';
|
|
4
|
+
import { Typography } from '../../common/Typography';
|
|
5
|
+
import { StyledProgress, StyledStepButton, StyledIcon } from './CheckoutProgressBar.style';
|
|
6
|
+
import { Icons } from '../../common/Icon';
|
|
7
|
+
import { Skeleton } from '../components/Skeletons.style';
|
|
8
|
+
|
|
9
|
+
export const CheckoutProgressBar = () => {
|
|
10
|
+
const { progressBarState, setActiveStep } = useProgressBarModel();
|
|
11
|
+
const { widgetState } = useCheckoutModel();
|
|
12
|
+
const { readOnly, isLoadingCheckoutData } = widgetState;
|
|
13
|
+
const { activeStep, completedSteps, steps } = progressBarState || {};
|
|
14
|
+
const progress = ((activeStep + 1) * 100) / steps.length;
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Box sx={{ width: '100%', my: 3 }}>
|
|
18
|
+
<StyledProgress variant="determinate" value={progress} $disabled={readOnly} />
|
|
19
|
+
<Grid container display="flex">
|
|
20
|
+
{steps.map(({ key, label }, index) => {
|
|
21
|
+
const isCompleted = completedSteps.includes(index);
|
|
22
|
+
const isDisabled = readOnly || (index > activeStep && !isCompleted && !completedSteps.includes(index - 1));
|
|
23
|
+
const checkedIcon: Icons = isDisabled ? 'OutlinedCheckedCircleDisabled' : 'OutlinedCheckedCircle';
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Grid key={key} item display="flex" flexDirection="row" flex={1} justifyContent="flex-start">
|
|
27
|
+
{isLoadingCheckoutData && <Skeleton width={120} height={20} style={{ marginTop: 8 }} />}
|
|
28
|
+
{!isLoadingCheckoutData && (
|
|
29
|
+
<StyledStepButton onClick={() => setActiveStep(index)} fullWidth disabled={isDisabled}>
|
|
30
|
+
<Grid item display="flex" flexDirection="row" alignItems="center" gap={1}>
|
|
31
|
+
<StepIcon
|
|
32
|
+
icon={
|
|
33
|
+
isCompleted ? (
|
|
34
|
+
<StyledIcon icon={checkedIcon} $shouldStroke={!isDisabled} />
|
|
35
|
+
) : (
|
|
36
|
+
<StyledIcon icon="OutlinedCircle" $disabled={isDisabled} />
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
/>
|
|
40
|
+
|
|
41
|
+
<Typography variant="h6" color={isDisabled ? 'disabled' : 'primary.main'}>
|
|
42
|
+
{label}
|
|
43
|
+
</Typography>
|
|
44
|
+
</Grid>
|
|
45
|
+
</StyledStepButton>
|
|
46
|
+
)}
|
|
47
|
+
</Grid>
|
|
48
|
+
);
|
|
49
|
+
})}
|
|
50
|
+
</Grid>
|
|
51
|
+
</Box>
|
|
52
|
+
);
|
|
53
|
+
};
|