@stigg/react-sdk 5.22.1 → 5.23.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/dist/components/checkout/Checkout.d.ts +1 -1
- package/dist/components/checkout/CheckoutProvider.d.ts +3 -1
- package/dist/components/checkout/configurations/steps.d.ts +1 -0
- package/dist/components/checkout/hooks/useProgressBarModel.d.ts +13 -3
- package/dist/components/checkout/progressBar/CheckoutProgressBar.d.ts +1 -1
- package/dist/components/checkout/steps/payment/PaymentMethods.d.ts +2 -3
- package/dist/components/checkout/steps/payment/PaymentMethods.style.d.ts +2 -0
- package/dist/components/utils/planPrices.d.ts +4 -0
- package/dist/react-sdk.cjs.development.js +116 -48
- 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 +116 -48
- package/dist/react-sdk.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/checkout/Checkout.tsx +3 -1
- package/src/components/checkout/CheckoutProvider.tsx +18 -2
- package/src/components/checkout/configurations/steps.ts +1 -0
- package/src/components/checkout/hooks/usePlanStepModel.ts +6 -9
- package/src/components/checkout/hooks/useProgressBarModel.ts +64 -5
- package/src/components/checkout/progressBar/CheckoutProgressBar.tsx +5 -1
- package/src/components/checkout/steps/payment/PaymentMethods.style.ts +8 -1
- package/src/components/checkout/steps/payment/PaymentMethods.tsx +11 -12
- package/src/components/checkout/steps/payment/PaymentStep.tsx +1 -0
- package/src/components/checkout/summary/CheckoutSummary.tsx +27 -20
- package/src/components/checkout/summary/components/LineItems.tsx +1 -1
- package/src/components/utils/planPrices.ts +10 -0
- package/src/stories/Checkout.stories.tsx +17 -2
- package/src/stories/mocks/checkout/mockCheckoutState.ts +1 -0
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ export const Checkout = ({
|
|
|
15
15
|
billableFeatures,
|
|
16
16
|
billingInformation,
|
|
17
17
|
onMockCheckoutState,
|
|
18
|
+
skipCheckoutSteps,
|
|
18
19
|
...containerProps
|
|
19
20
|
}: CheckoutProps) => {
|
|
20
21
|
return (
|
|
@@ -27,7 +28,8 @@ export const Checkout = ({
|
|
|
27
28
|
billingCountryCode={billingCountryCode}
|
|
28
29
|
billableFeatures={billableFeatures}
|
|
29
30
|
billingInformation={billingInformation}
|
|
30
|
-
onMockCheckoutState={onMockCheckoutState}
|
|
31
|
+
onMockCheckoutState={onMockCheckoutState}
|
|
32
|
+
skipCheckoutSteps={skipCheckoutSteps}>
|
|
31
33
|
<CheckoutContainer {...containerProps} />
|
|
32
34
|
</CheckoutProvider>
|
|
33
35
|
);
|
|
@@ -21,6 +21,7 @@ import { CheckoutTheme, getResolvedCheckoutTheme } from './configurations/theme'
|
|
|
21
21
|
import { StiggTheme } from '../../theme/types';
|
|
22
22
|
import { BillingInformation, MockCheckoutStateCallback } from './types';
|
|
23
23
|
import { defaultCheckoutTypography } from './configurations/typography';
|
|
24
|
+
import { CheckoutSteps } from './configurations/steps';
|
|
24
25
|
|
|
25
26
|
export interface CheckoutContextState {
|
|
26
27
|
checkout?: GetCheckoutStateResults | null;
|
|
@@ -82,6 +83,7 @@ export type CheckoutProviderProps = {
|
|
|
82
83
|
billableFeatures?: BillableFeature[];
|
|
83
84
|
billingInformation?: BillingInformation;
|
|
84
85
|
onMockCheckoutState?: MockCheckoutStateCallback;
|
|
86
|
+
skipCheckoutSteps?: CheckoutSteps[];
|
|
85
87
|
};
|
|
86
88
|
|
|
87
89
|
export function CheckoutProvider({
|
|
@@ -95,6 +97,7 @@ export function CheckoutProvider({
|
|
|
95
97
|
billingCountryCode,
|
|
96
98
|
billingInformation,
|
|
97
99
|
onMockCheckoutState,
|
|
100
|
+
skipCheckoutSteps,
|
|
98
101
|
}: {
|
|
99
102
|
children: React.ReactNode;
|
|
100
103
|
} & CheckoutProviderProps) {
|
|
@@ -124,7 +127,13 @@ export function CheckoutProvider({
|
|
|
124
127
|
taxPercentage: billingInformation?.taxDetails?.taxPercentage,
|
|
125
128
|
});
|
|
126
129
|
const progressBar = getProgressBarInitialState({
|
|
127
|
-
|
|
130
|
+
isLoading,
|
|
131
|
+
skipCheckoutSteps: skipCheckoutSteps ?? [],
|
|
132
|
+
plan: checkout?.plan,
|
|
133
|
+
availableAddons: addonsStep.availableAddons,
|
|
134
|
+
availableCharges: planStep.billableFeatures,
|
|
135
|
+
preferredBillingPeriod,
|
|
136
|
+
preconfiguredBillableFeatures: billableFeatures ?? [],
|
|
128
137
|
});
|
|
129
138
|
|
|
130
139
|
const initialState: CheckoutContextState = {
|
|
@@ -142,7 +151,14 @@ export function CheckoutProvider({
|
|
|
142
151
|
|
|
143
152
|
return initialState;
|
|
144
153
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
145
|
-
}, [
|
|
154
|
+
}, [
|
|
155
|
+
preferredBillingPeriod,
|
|
156
|
+
billingCountryCode,
|
|
157
|
+
checkout,
|
|
158
|
+
isLoading,
|
|
159
|
+
skipCheckoutSteps,
|
|
160
|
+
billingInformation?.taxDetails?.taxPercentage,
|
|
161
|
+
]);
|
|
146
162
|
|
|
147
163
|
return (
|
|
148
164
|
<SdkThemeProvider key={checkout?.plan.id} componentTheme={configuration}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type CheckoutSteps = 'PLAN' | 'ADDONS';
|
|
@@ -5,6 +5,7 @@ import { BillableFeature, BillingModel, Plan, Price, Subscription } from '@stigg
|
|
|
5
5
|
import { useCheckoutContext } from '../CheckoutProvider';
|
|
6
6
|
import { getTierByQuantity, hasTierWithUnitPrice } from '../../utils/priceTierUtils';
|
|
7
7
|
import { getValidPriceQuantity } from '../../utils/priceUtils';
|
|
8
|
+
import { hasAnnualPrices, hasMonthlyPrices } from '../../utils/planPrices';
|
|
8
9
|
|
|
9
10
|
export type PlanStepState = {
|
|
10
11
|
billingPeriod: BillingPeriod;
|
|
@@ -95,11 +96,11 @@ function resolveBillingPeriod({
|
|
|
95
96
|
activeSubscription?: Subscription | null;
|
|
96
97
|
preferredBillingPeriod?: BillingPeriod;
|
|
97
98
|
}) {
|
|
98
|
-
const
|
|
99
|
-
const
|
|
99
|
+
const hasMonthlyPlan = hasMonthlyPrices(plan);
|
|
100
|
+
const hasAnnualPlan = hasAnnualPrices(plan);
|
|
100
101
|
|
|
101
102
|
if (preferredBillingPeriod) {
|
|
102
|
-
const billingPeriod = getBillingPeriod(preferredBillingPeriod,
|
|
103
|
+
const billingPeriod = getBillingPeriod(preferredBillingPeriod, hasMonthlyPlan, hasAnnualPlan);
|
|
103
104
|
if (billingPeriod) {
|
|
104
105
|
return billingPeriod;
|
|
105
106
|
}
|
|
@@ -111,17 +112,13 @@ function resolveBillingPeriod({
|
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
if (activeSubscription?.prices && activeSubscription?.prices.length > 0) {
|
|
114
|
-
const billingPeriod = getBillingPeriod(
|
|
115
|
-
activeSubscription?.prices[0].billingPeriod,
|
|
116
|
-
hasMonthlyPrices,
|
|
117
|
-
hasAnnualPrices,
|
|
118
|
-
);
|
|
115
|
+
const billingPeriod = getBillingPeriod(activeSubscription?.prices[0].billingPeriod, hasMonthlyPlan, hasAnnualPlan);
|
|
119
116
|
if (billingPeriod) {
|
|
120
117
|
return billingPeriod;
|
|
121
118
|
}
|
|
122
119
|
}
|
|
123
120
|
|
|
124
|
-
return
|
|
121
|
+
return hasAnnualPlan ? BillingPeriod.Annually : BillingPeriod.Monthly;
|
|
125
122
|
}
|
|
126
123
|
|
|
127
124
|
export function getPlanStepInitialState({
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BillableFeatureInput } from '@stigg/api-client-js/src/generated/sdk';
|
|
2
|
+
import { Addon, BillableFeature, BillingPeriod, CheckoutStatePlan } from '@stigg/js-client-sdk';
|
|
2
3
|
import { useCheckoutContext } from '../CheckoutProvider';
|
|
4
|
+
import { CheckoutSteps } from '../configurations/steps';
|
|
5
|
+
import { hasMultipleBillingPeriods } from '../../utils/planPrices';
|
|
3
6
|
|
|
4
7
|
export enum CheckoutStepKey {
|
|
5
8
|
PLAN = 'PLAN',
|
|
@@ -32,12 +35,68 @@ const INITIAL_STATE: ProgressBarState = {
|
|
|
32
35
|
isDisabled: false,
|
|
33
36
|
};
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
type GetProgressBarInitialStateProps = {
|
|
39
|
+
isLoading: boolean;
|
|
40
|
+
skipCheckoutSteps: CheckoutSteps[];
|
|
41
|
+
plan?: CheckoutStatePlan;
|
|
42
|
+
availableAddons?: Addon[];
|
|
43
|
+
availableCharges: BillableFeatureInput[];
|
|
44
|
+
preferredBillingPeriod?: BillingPeriod;
|
|
45
|
+
preconfiguredBillableFeatures: BillableFeature[];
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const canSkipPlanStep = (
|
|
49
|
+
plan: CheckoutStatePlan,
|
|
50
|
+
availableCharges: BillableFeatureInput[],
|
|
51
|
+
preconfiguredBillableFeatures: BillableFeature[],
|
|
52
|
+
preferredBillingPeriod?: BillingPeriod,
|
|
53
|
+
) => {
|
|
54
|
+
// if multiple billing periods are available, a preferred billing period must be selected
|
|
55
|
+
if (hasMultipleBillingPeriods(plan) && !preferredBillingPeriod) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const availableChargesIds = availableCharges.map((charge) => charge.featureId);
|
|
60
|
+
const preconfiguredChargesIds = preconfiguredBillableFeatures.map((charge) => charge.featureId);
|
|
61
|
+
|
|
62
|
+
// if there are available charges, they must be preconfigured
|
|
63
|
+
if (
|
|
64
|
+
availableChargesIds.length !== preconfiguredChargesIds.length ||
|
|
65
|
+
!availableChargesIds.every((charge) => preconfiguredChargesIds.includes(charge))
|
|
66
|
+
) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export function getProgressBarInitialState({
|
|
74
|
+
isLoading,
|
|
75
|
+
skipCheckoutSteps,
|
|
76
|
+
plan,
|
|
77
|
+
availableAddons,
|
|
78
|
+
availableCharges,
|
|
79
|
+
preferredBillingPeriod,
|
|
80
|
+
preconfiguredBillableFeatures,
|
|
81
|
+
}: GetProgressBarInitialStateProps) {
|
|
82
|
+
if (isLoading || !plan) {
|
|
83
|
+
return INITIAL_STATE;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const stepsToFilter: CheckoutStepKey[] = [];
|
|
87
|
+
|
|
88
|
+
if (
|
|
89
|
+
skipCheckoutSteps.includes('PLAN') &&
|
|
90
|
+
canSkipPlanStep(plan, availableCharges, preconfiguredBillableFeatures, preferredBillingPeriod)
|
|
91
|
+
) {
|
|
92
|
+
stepsToFilter.push(CheckoutStepKey.PLAN);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (availableAddons?.length === 0 || skipCheckoutSteps.includes('ADDONS')) {
|
|
96
|
+
stepsToFilter.push(CheckoutStepKey.ADDONS);
|
|
38
97
|
}
|
|
39
98
|
|
|
40
|
-
return INITIAL_STATE;
|
|
99
|
+
return { ...INITIAL_STATE, steps: CHECKOUT_STEPS.filter((step) => !stepsToFilter.includes(step.key)) };
|
|
41
100
|
}
|
|
42
101
|
|
|
43
102
|
function useProgressBarState() {
|
|
@@ -15,8 +15,12 @@ export const CheckoutProgressBar = () => {
|
|
|
15
15
|
const { activeStep, completedSteps, steps } = progressBarState || {};
|
|
16
16
|
const progress = ((activeStep + 1) * 100) / steps.length;
|
|
17
17
|
|
|
18
|
+
if (progressBarState.steps.length === 1) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
|
|
18
22
|
return (
|
|
19
|
-
<Box sx={{ width: '100%', mb: 3 }}>
|
|
23
|
+
<Box className="stigg-checkout-progress-container" sx={{ width: '100%', mb: 3 }}>
|
|
20
24
|
<StyledProgress variant="determinate" value={progress} $disabled={readOnly} />
|
|
21
25
|
<Grid container display="flex">
|
|
22
26
|
{steps.map(({ key, label }, index) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
1
2
|
import styled from '@emotion/styled';
|
|
2
3
|
import Grid from '@mui/material/Grid';
|
|
3
4
|
|
|
@@ -11,9 +12,15 @@ export const PaymentMethodContainer = styled(Grid, { shouldForwardProp: (prop) =
|
|
|
11
12
|
opacity: ${({ $disabled }) => ($disabled ? 0.6 : 1)};
|
|
12
13
|
`;
|
|
13
14
|
|
|
14
|
-
export const NewPaymentMethodContainer = styled(PaymentMethodContainer)
|
|
15
|
+
export const NewPaymentMethodContainer = styled(PaymentMethodContainer)<{ $hideBorders?: boolean }>`
|
|
15
16
|
flex-direction: column;
|
|
16
17
|
align-items: unset;
|
|
18
|
+
${({ $hideBorders }) =>
|
|
19
|
+
$hideBorders &&
|
|
20
|
+
css`
|
|
21
|
+
border: none;
|
|
22
|
+
padding: 0;
|
|
23
|
+
`}
|
|
17
24
|
`;
|
|
18
25
|
|
|
19
26
|
export const PaymentMethodLayoutContainer = styled(Grid)`
|
|
@@ -5,7 +5,6 @@ import Grid from '@mui/material/Grid';
|
|
|
5
5
|
import Radio from '@mui/material/Radio';
|
|
6
6
|
import { Customer } from '@stigg/js-client-sdk';
|
|
7
7
|
|
|
8
|
-
import { Icon, Icons } from '../../../common/Icon';
|
|
9
8
|
import { Typography } from '../../../common/Typography';
|
|
10
9
|
import {
|
|
11
10
|
NewPaymentMethodContainer,
|
|
@@ -19,7 +18,6 @@ import { CheckoutContainerProps } from '../../CheckoutContainer';
|
|
|
19
18
|
|
|
20
19
|
export type PaymentMethodLayoutProps = {
|
|
21
20
|
checked: boolean;
|
|
22
|
-
icon: Icons;
|
|
23
21
|
text: React.ReactNode;
|
|
24
22
|
subtitle?: React.ReactNode;
|
|
25
23
|
readOnly?: boolean;
|
|
@@ -31,13 +29,13 @@ export type PaymentMethodProps = Pick<Customer, 'paymentMethodDetails'> &
|
|
|
31
29
|
export type NewPaymentMethodProps = Pick<PaymentMethodLayoutProps, 'checked' | 'readOnly'> & {
|
|
32
30
|
onSelect: () => void;
|
|
33
31
|
checkoutLocalization: CheckoutLocalization;
|
|
32
|
+
hasExistingPaymentMethod: boolean;
|
|
34
33
|
} & Pick<CheckoutContainerProps, 'onBillingAddressChange' | 'collectPhoneNumber'>;
|
|
35
34
|
|
|
36
|
-
function PaymentMethodLayout({ checked,
|
|
35
|
+
function PaymentMethodLayout({ checked, text, subtitle, readOnly }: PaymentMethodLayoutProps) {
|
|
37
36
|
return (
|
|
38
37
|
<PaymentMethodLayoutContainer>
|
|
39
38
|
<Radio checked={checked} disabled={readOnly} />
|
|
40
|
-
<Icon icon={icon} style={{ display: 'flex' }} />
|
|
41
39
|
<PaymentMethodTextContainer container>
|
|
42
40
|
<Grid item>{text}</Grid>
|
|
43
41
|
{subtitle && <Grid item>{subtitle}</Grid>}
|
|
@@ -57,7 +55,6 @@ export function ExistingPaymentMethod({ checked, paymentMethodDetails, readOnly,
|
|
|
57
55
|
<PaymentMethodLayout
|
|
58
56
|
checked={checked}
|
|
59
57
|
readOnly={readOnly}
|
|
60
|
-
icon="PaymentMethod"
|
|
61
58
|
text={<Typography variant="h6">{`Card ending in ${last4Digits}`}</Typography>}
|
|
62
59
|
subtitle={
|
|
63
60
|
!!expirationMonth &&
|
|
@@ -73,6 +70,7 @@ export function ExistingPaymentMethod({ checked, paymentMethodDetails, readOnly,
|
|
|
73
70
|
}
|
|
74
71
|
|
|
75
72
|
export function NewPaymentMethod({
|
|
73
|
+
hasExistingPaymentMethod,
|
|
76
74
|
checked,
|
|
77
75
|
onSelect,
|
|
78
76
|
readOnly,
|
|
@@ -81,13 +79,14 @@ export function NewPaymentMethod({
|
|
|
81
79
|
collectPhoneNumber,
|
|
82
80
|
}: NewPaymentMethodProps) {
|
|
83
81
|
return (
|
|
84
|
-
<NewPaymentMethodContainer item onClick={onSelect} $disabled={readOnly}>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
82
|
+
<NewPaymentMethodContainer item $hideBorders={!hasExistingPaymentMethod} onClick={onSelect} $disabled={readOnly}>
|
|
83
|
+
{hasExistingPaymentMethod && (
|
|
84
|
+
<PaymentMethodLayout
|
|
85
|
+
checked={checked}
|
|
86
|
+
readOnly={readOnly}
|
|
87
|
+
text={<Typography variant="h6">{checkoutLocalization.newPaymentMethodText}</Typography>}
|
|
88
|
+
/>
|
|
89
|
+
)}
|
|
91
90
|
<Collapse in={checked}>
|
|
92
91
|
<StripePaymentForm onBillingAddressChange={onBillingAddressChange} collectPhoneNumber={collectPhoneNumber} />
|
|
93
92
|
</Collapse>
|
|
@@ -44,6 +44,7 @@ export function PaymentStep({
|
|
|
44
44
|
onSelect={() => handleOnSelect(false)}
|
|
45
45
|
/>
|
|
46
46
|
<NewPaymentMethod
|
|
47
|
+
hasExistingPaymentMethod={!!customer?.paymentMethodDetails}
|
|
47
48
|
readOnly={readOnly}
|
|
48
49
|
checked={useNewPaymentMethod}
|
|
49
50
|
checkoutLocalization={checkoutLocalization}
|
|
@@ -181,7 +181,12 @@ export const CheckoutSummary = ({
|
|
|
181
181
|
<SummaryCard>
|
|
182
182
|
<SummaryTitle variant="h3">{checkoutLocalization.summary.title}</SummaryTitle>
|
|
183
183
|
|
|
184
|
-
<Grid
|
|
184
|
+
<Grid
|
|
185
|
+
className="stigg-checkout-summary-plan-title-container"
|
|
186
|
+
display="flex"
|
|
187
|
+
flexDirection="row"
|
|
188
|
+
alignItems="center"
|
|
189
|
+
marginY={2}>
|
|
185
190
|
<Typography variant="h6" color="primary" style={{ paddingRight: '8px' }}>
|
|
186
191
|
{checkoutLocalization.summary.planName({ plan: plan! })}
|
|
187
192
|
</Typography>
|
|
@@ -198,25 +203,27 @@ export const CheckoutSummary = ({
|
|
|
198
203
|
)}
|
|
199
204
|
{!baseCharge && isFreeDowngrade ? <FreeChargeLineItem label={baseChargeLabel} /> : null}
|
|
200
205
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
206
|
+
<Grid item className="stigg-checkout-summary-usage-charges-container">
|
|
207
|
+
{usageCharges.map((price) => {
|
|
208
|
+
const priceBillableFeature = subscription.billableFeatures?.find(
|
|
209
|
+
(billableFeature) => billableFeature.featureId === price.feature?.featureId,
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<BilledPriceLineItem
|
|
214
|
+
checkoutLocalization={checkoutLocalization}
|
|
215
|
+
key={price.feature?.featureId}
|
|
216
|
+
label={getFeatureDisplayNameText(
|
|
217
|
+
price.feature?.displayName || '',
|
|
218
|
+
price.feature?.units,
|
|
219
|
+
price.feature?.unitsPlural,
|
|
220
|
+
)}
|
|
221
|
+
quantity={priceBillableFeature?.quantity || 1}
|
|
222
|
+
price={price}
|
|
223
|
+
/>
|
|
224
|
+
);
|
|
225
|
+
})}
|
|
226
|
+
</Grid>
|
|
220
227
|
|
|
221
228
|
{!!subscription.addons?.length && (
|
|
222
229
|
<>
|
|
@@ -98,7 +98,7 @@ export const BilledPriceLineItem = ({
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
return (
|
|
101
|
-
<LineItemContainer>
|
|
101
|
+
<LineItemContainer className="stigg-checkout-summary-base-charges-container">
|
|
102
102
|
<LineItemRow style={{ alignItems: 'flex-start' }}>
|
|
103
103
|
<Grid item display="flex" gap={0.5} style={{ whiteSpace: 'nowrap' }}>
|
|
104
104
|
{title}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Plan } from '@stigg/js-client-sdk';
|
|
2
|
+
import { BillingPeriod } from '@stigg/api-client-js/src/generated/sdk';
|
|
3
|
+
|
|
4
|
+
export const hasMonthlyPrices = (plan?: Plan) =>
|
|
5
|
+
!!plan?.pricePoints.some((pricePoint) => pricePoint.billingPeriod === BillingPeriod.Monthly);
|
|
6
|
+
|
|
7
|
+
export const hasAnnualPrices = (plan?: Plan) =>
|
|
8
|
+
!!plan?.pricePoints.some((pricePoint) => pricePoint.billingPeriod === BillingPeriod.Annually);
|
|
9
|
+
|
|
10
|
+
export const hasMultipleBillingPeriods = (plan?: Plan) => hasMonthlyPrices(plan) && hasAnnualPrices(plan);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import styled from '@emotion/styled/macro';
|
|
3
|
+
import { BillingPeriod } from '@stigg/js-client-sdk';
|
|
3
4
|
import { ComponentMeta, ComponentStory } from '@storybook/react';
|
|
4
5
|
import { Checkout } from '../components/checkout';
|
|
5
6
|
import { StiggProvider } from '../components/StiggProvider';
|
|
@@ -23,6 +24,16 @@ export default {
|
|
|
23
24
|
</StiggProvider>
|
|
24
25
|
),
|
|
25
26
|
],
|
|
27
|
+
argTypes: {
|
|
28
|
+
billingPeriod: {
|
|
29
|
+
options: [BillingPeriod.Monthly, BillingPeriod.Annually, null],
|
|
30
|
+
control: { type: 'radio' },
|
|
31
|
+
},
|
|
32
|
+
skipSteps: {
|
|
33
|
+
options: ['PLAN', 'ADDONS'],
|
|
34
|
+
control: { type: 'check' },
|
|
35
|
+
},
|
|
36
|
+
},
|
|
26
37
|
parameters: {
|
|
27
38
|
controls: {
|
|
28
39
|
exclude: [
|
|
@@ -32,6 +43,8 @@ export default {
|
|
|
32
43
|
'onBillingAddressChange',
|
|
33
44
|
'onMockCheckoutState',
|
|
34
45
|
'onMockCheckoutPreview',
|
|
46
|
+
'preferredBillingPeriod',
|
|
47
|
+
'skipCheckoutSteps',
|
|
35
48
|
],
|
|
36
49
|
},
|
|
37
50
|
},
|
|
@@ -45,7 +58,7 @@ const Template: ComponentStory<any> = (args) => (
|
|
|
45
58
|
<Wrapper>
|
|
46
59
|
<Checkout
|
|
47
60
|
planId={args.planId}
|
|
48
|
-
preferredBillingPeriod={args.
|
|
61
|
+
preferredBillingPeriod={args.billingPeriod}
|
|
49
62
|
billingCountryCode={args.billingCountryCode}
|
|
50
63
|
resourceId={args.resourceId}
|
|
51
64
|
onCheckoutCompleted={(results) => {
|
|
@@ -62,10 +75,11 @@ const Template: ComponentStory<any> = (args) => (
|
|
|
62
75
|
const { success, errorMessage, results } = await checkoutAction(checkoutParams);
|
|
63
76
|
return { success, errorMessage, results };
|
|
64
77
|
}}
|
|
65
|
-
billableFeatures={
|
|
78
|
+
billableFeatures={args.billableFeatures || []}
|
|
66
79
|
onChangePlan={({ currentPlan }) => {
|
|
67
80
|
console.log('plan changed clicked!', { currentPlan });
|
|
68
81
|
}}
|
|
82
|
+
skipCheckoutSteps={args.skipSteps}
|
|
69
83
|
onMockCheckoutState={
|
|
70
84
|
args.useMockData
|
|
71
85
|
? (params) => {
|
|
@@ -74,6 +88,7 @@ const Template: ComponentStory<any> = (args) => (
|
|
|
74
88
|
}
|
|
75
89
|
: undefined
|
|
76
90
|
}
|
|
91
|
+
disablePromotionCode={args.disablePromotionCode}
|
|
77
92
|
onMockCheckoutPreview={
|
|
78
93
|
args.useMockData
|
|
79
94
|
? (params) => {
|