@stigg/react-sdk 4.9.0 → 4.11.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/hooks/useAddonsStepModel.d.ts +2 -2
- package/dist/components/checkout/steps/addons/addon.utils.d.ts +3 -3
- package/dist/components/common/LongText.d.ts +3 -4
- package/dist/components/customerPortal/CustomerPortal.d.ts +1 -1
- package/dist/components/customerPortal/billing/InformationGrid.d.ts +1 -1
- package/dist/components/customerPortal/hooks/useCustomerPortal.d.ts +2 -2
- package/dist/components/customerPortal/subscriptionOverview/SubscriptionsOverviewHeader.d.ts +0 -2
- package/dist/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.d.ts +1 -1
- package/dist/components/customerPortal/usage/featureUsage/EntitlementCTAButton.d.ts +1 -1
- package/dist/components/paywall/hooks/useLoadPaywallData.d.ts +2 -2
- package/dist/components/paywall/utils/hasPricePoints.d.ts +2 -2
- package/dist/components/utils/getFeatureName.d.ts +1 -1
- package/dist/components/utils/getPlanPrice.d.ts +1 -2
- package/dist/components/utils/priceTierUtils.d.ts +1 -1
- package/dist/react-sdk.cjs.development.js +111 -85
- 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 +111 -85
- package/dist/react-sdk.esm.js.map +1 -1
- package/package.json +7 -5
- package/src/components/checkout/CheckoutContainer.tsx +2 -0
- package/src/components/checkout/components/Button.tsx +4 -2
- package/src/components/checkout/hooks/useAddonsStepModel.ts +2 -2
- package/src/components/checkout/hooks/useCouponModel.ts +1 -1
- package/src/components/checkout/steps/addons/addon.utils.ts +30 -30
- package/src/components/common/LongText.tsx +2 -4
- package/src/components/common/PoweredByStigg.tsx +2 -3
- package/src/components/common/Typography.tsx +1 -1
- package/src/components/common/iconColor.ts +2 -4
- package/src/components/customerPortal/CustomerPortal.style.ts +2 -2
- package/src/components/customerPortal/CustomerPortal.tsx +1 -1
- package/src/components/customerPortal/CustomerPortalProvider.tsx +2 -2
- package/src/components/customerPortal/billing/InformationGrid.tsx +2 -3
- package/src/components/customerPortal/billing/InvoicesSection.tsx +9 -4
- package/src/components/customerPortal/billing/PaymentDetailsSection.tsx +3 -3
- package/src/components/customerPortal/common/ExternalLinkButton.tsx +3 -4
- package/src/components/customerPortal/common/SectionContainer.tsx +1 -1
- package/src/components/customerPortal/common/SectionHeader.ts +4 -2
- package/src/components/customerPortal/common/SectionTitle.tsx +2 -2
- package/src/components/customerPortal/common/SkeletonButton.tsx +1 -1
- package/src/components/customerPortal/hooks/useCustomerPortal.ts +3 -3
- package/src/components/customerPortal/subscriptionOverview/ContactCustomerSupport.tsx +5 -4
- package/src/components/customerPortal/subscriptionOverview/SubscriptionsOverview.tsx +3 -3
- package/src/components/customerPortal/subscriptionOverview/SubscriptionsOverviewHeader.tsx +4 -11
- package/src/components/customerPortal/subscriptionOverview/charges/ChargeItem.tsx +3 -3
- package/src/components/customerPortal/subscriptionOverview/charges/ChargeList.tsx +3 -3
- package/src/components/customerPortal/subscriptionOverview/subscriptionScheduledUpdates/SubscriptionScheduledUpdateRow.tsx +1 -1
- package/src/components/customerPortal/subscriptionOverview/subscriptionScheduledUpdates/SubscriptionScheduledUpdatesAlert.tsx +2 -2
- package/src/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.tsx +9 -5
- package/src/components/customerPortal/subscriptionOverview/subscriptionView/TrialPanel.tsx +2 -2
- package/src/components/customerPortal/subscriptionOverview/tabs/AddonsList.tsx +1 -1
- package/src/components/customerPortal/subscriptionOverview/tabs/Promotions.tsx +2 -2
- package/src/components/customerPortal/subscriptionOverview/tabs/SubscriptionTabs.tsx +3 -3
- package/src/components/customerPortal/subscriptionOverview/upcomingBilling/NextEstimatedBill.tsx +2 -2
- package/src/components/customerPortal/subscriptionOverview/upcomingBilling/NoUpcomingBilling.tsx +5 -3
- package/src/components/customerPortal/subscriptionOverview/upcomingBilling/UpcomingBilling.tsx +1 -1
- package/src/components/customerPortal/types.ts +2 -2
- package/src/components/customerPortal/usage/CustomerUsageData.tsx +4 -4
- package/src/components/customerPortal/usage/featureUsage/EntitlementCTAButton.tsx +13 -6
- package/src/components/customerPortal/usage/featureUsage/FeatureUsage.style.ts +1 -1
- package/src/components/customerPortal/usage/featureUsage/FeatureUsage.tsx +5 -7
- package/src/components/customerPortal/usage/featureUsage/FeatureUsageProgressBar.tsx +1 -1
- package/src/components/hooks/useChargeSort.ts +2 -2
- package/src/components/hooks/useWaitForCheckoutCompleted.ts +12 -4
- package/src/components/paywall/PlanEntitlements.tsx +4 -4
- package/src/components/paywall/hooks/useLoadPaywallData.ts +4 -4
- package/src/components/paywall/paywallTextOverrides.ts +2 -2
- package/src/components/paywall/utils/computeDefaultBillingPeriod.ts +2 -2
- package/src/components/paywall/utils/hasPricePoints.ts +6 -6
- package/src/components/utils/calculateDiscountRate.ts +3 -3
- package/src/components/utils/getFeatureName.ts +11 -7
- package/src/components/utils/getPaidPriceText.ts +4 -4
- package/src/components/utils/getPlanPrice.ts +4 -5
- package/src/components/utils/getSubscriptionScheduleUpdateTexts.tsx +1 -1
- package/src/components/utils/priceTierUtils.ts +18 -16
- package/src/components/utils/priceUtils.ts +2 -1
- package/src/custom.d.ts +1 -0
- package/src/types.ts +1 -1
|
@@ -3,7 +3,7 @@ import Box from '@mui/material/Box';
|
|
|
3
3
|
import Grid from '@mui/material/Grid';
|
|
4
4
|
import { CustomerPortalSubscription } from '@stigg/js-client-sdk';
|
|
5
5
|
import styled from '@emotion/styled/macro';
|
|
6
|
-
import {
|
|
6
|
+
import { useTheme } from '@emotion/react';
|
|
7
7
|
import ClipLoader from 'react-spinners/ClipLoader';
|
|
8
8
|
import { CustomerPortalTheme } from '../../customerPortalTheme';
|
|
9
9
|
import Restore from '../../../../assets/restore.svg';
|
|
@@ -103,7 +103,7 @@ export function SubscriptionScheduledUpdatesAlert({
|
|
|
103
103
|
theme,
|
|
104
104
|
cancelScheduledUpdatesButtonTitle,
|
|
105
105
|
}: SubscriptionScheduledUpdatesAlertProps) {
|
|
106
|
-
const stiggTheme = useTheme()
|
|
106
|
+
const stiggTheme = useTheme();
|
|
107
107
|
const [isLoading, setIsLoading] = useState(false);
|
|
108
108
|
const { scheduledUpdates } = subscription;
|
|
109
109
|
|
package/src/components/customerPortal/subscriptionOverview/subscriptionView/SubscriptionView.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Typography } from '../../../common/Typography';
|
|
3
2
|
import { CustomerPortalSubscription } from '@stigg/js-client-sdk';
|
|
3
|
+
import { Typography } from '../../../common/Typography';
|
|
4
4
|
import { TrialPanel } from './TrialPanel';
|
|
5
5
|
import { CustomerPortalTheme } from '../../customerPortalTheme';
|
|
6
6
|
|
|
@@ -11,15 +11,19 @@ type SubscriptionViewProps = {
|
|
|
11
11
|
theme: CustomerPortalTheme;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
export function SubscriptionView({
|
|
14
|
+
export function SubscriptionView({
|
|
15
|
+
mainSubscription,
|
|
16
|
+
trialSubscription,
|
|
17
|
+
onManageSubscription,
|
|
18
|
+
theme,
|
|
19
|
+
}: SubscriptionViewProps) {
|
|
15
20
|
return (
|
|
16
21
|
<div className="stigg-subscription-view-layout">
|
|
17
22
|
<Typography
|
|
18
23
|
className="stigg-subscription-plan-name"
|
|
19
|
-
variant=
|
|
24
|
+
variant="h1"
|
|
20
25
|
overrideColor={theme.planNameColor}
|
|
21
|
-
style={{ marginTop: 8 }}
|
|
22
|
-
>
|
|
26
|
+
style={{ marginTop: 8 }}>
|
|
23
27
|
{mainSubscription.planName} plan
|
|
24
28
|
</Typography>
|
|
25
29
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import styled from '@emotion/styled/macro';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import SandClockIcon from '../../../../assets/sand-clock.svg';
|
|
4
|
-
import { Typography } from '../../../common/Typography';
|
|
5
3
|
import { CustomerPortalSubscription, SubscriptionStatus } from '@stigg/js-client-sdk';
|
|
6
4
|
import Link from '@mui/material/Link';
|
|
5
|
+
import SandClockIcon from '../../../../assets/sand-clock.svg';
|
|
6
|
+
import { Typography } from '../../../common/Typography';
|
|
7
7
|
import { LongText } from '../../../common/LongText';
|
|
8
8
|
|
|
9
9
|
const OnTrialBadge = styled.div`
|
|
@@ -6,7 +6,7 @@ import { useCustomerPortalContext } from '../../CustomerPortalProvider';
|
|
|
6
6
|
|
|
7
7
|
export function AddonsList() {
|
|
8
8
|
const { customerPortal } = useCustomerPortalContext();
|
|
9
|
-
const addons = flatMap(customerPortal?.subscriptions, subscription => subscription.addons);
|
|
9
|
+
const addons = flatMap(customerPortal?.subscriptions, (subscription) => subscription.addons);
|
|
10
10
|
if (isEmpty(addons)) {
|
|
11
11
|
return null;
|
|
12
12
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CustomerPortalPromotionalEntitlement } from '@stigg/js-client-sdk';
|
|
2
2
|
import moment from 'moment';
|
|
3
3
|
import React from 'react';
|
|
4
|
+
import styled from '@emotion/styled/macro';
|
|
4
5
|
import { Typography } from '../../../common/Typography';
|
|
5
6
|
import { useCustomerPortalContext } from '../../CustomerPortalProvider';
|
|
6
|
-
import styled from '@emotion/styled/macro';
|
|
7
7
|
|
|
8
8
|
const Row = styled.div<{ $borderColor: string }>`
|
|
9
9
|
display: flex;
|
|
@@ -47,7 +47,7 @@ export function Promotions() {
|
|
|
47
47
|
Expiration date
|
|
48
48
|
</Typography>
|
|
49
49
|
</Row>
|
|
50
|
-
{promotionalEntitlements?.map(promotionalEntitlement => (
|
|
50
|
+
{promotionalEntitlements?.map((promotionalEntitlement) => (
|
|
51
51
|
<Row $borderColor={theme.borderColor}>
|
|
52
52
|
<Typography variant="body1">{getPromotionTitle(promotionalEntitlement)}</Typography>
|
|
53
53
|
<Typography variant="body1" color="disabled">
|
|
@@ -3,6 +3,7 @@ import { CustomerPortal } from '@stigg/js-client-sdk';
|
|
|
3
3
|
import flatMap from 'lodash/flatMap';
|
|
4
4
|
import Box from '@mui/material/Box';
|
|
5
5
|
import Tab from '@mui/material/Tab';
|
|
6
|
+
import { FontWeight } from 'styled-typography';
|
|
6
7
|
import { Typography } from '../../../common/Typography';
|
|
7
8
|
import { AddonsList } from './AddonsList';
|
|
8
9
|
import { Promotions } from './Promotions';
|
|
@@ -11,7 +12,6 @@ import { CustomerPortalLocalization } from '../../customerPortalTextOverrides';
|
|
|
11
12
|
import { StyledTabs, TabContent, TabsLayout } from './SubscriptionTabs.style';
|
|
12
13
|
import { CustomerPortalTheme } from '../../customerPortalTheme';
|
|
13
14
|
import { Icon, Icons } from '../../../common/Icon';
|
|
14
|
-
import { FontWeight } from 'styled-typography';
|
|
15
15
|
|
|
16
16
|
type TabPanelProps = {
|
|
17
17
|
children?: React.ReactNode;
|
|
@@ -50,9 +50,9 @@ function TabTitle({ isSelected, label, icon }: { isSelected: boolean; label: str
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export function SubscriptionTabs({ customerPortal, hiddenSections, textOverrides, theme }: SubscriptionTabsProps) {
|
|
53
|
-
const allAddons = flatMap(customerPortal.subscriptions, subscription => subscription.addons);
|
|
53
|
+
const allAddons = flatMap(customerPortal.subscriptions, (subscription) => subscription.addons);
|
|
54
54
|
const isSectionHidden = (sectionName: CustomerPortalSection) =>
|
|
55
|
-
hiddenSections?.some(section => section === sectionName);
|
|
55
|
+
hiddenSections?.some((section) => section === sectionName);
|
|
56
56
|
const showAddons = allAddons.length > 0 && !isSectionHidden('addons');
|
|
57
57
|
const showPromotions =
|
|
58
58
|
customerPortal.promotionalEntitlements.length > 0 && !isSectionHidden('promotionalEntitlements');
|
package/src/components/customerPortal/subscriptionOverview/upcomingBilling/NextEstimatedBill.tsx
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Typography } from '../../../common/Typography';
|
|
2
|
-
import { currencyPriceFormatter } from '../../../utils/currencyUtils';
|
|
3
1
|
import { BillingPeriod, Currency } from '@stigg/js-client-sdk';
|
|
4
2
|
import moment from 'moment';
|
|
5
3
|
import React from 'react';
|
|
4
|
+
import { currencyPriceFormatter } from '../../../utils/currencyUtils';
|
|
5
|
+
import { Typography } from '../../../common/Typography';
|
|
6
6
|
|
|
7
7
|
export type NextEstimatedBillProps = {
|
|
8
8
|
billingPeriod: BillingPeriod;
|
package/src/components/customerPortal/subscriptionOverview/upcomingBilling/NoUpcomingBilling.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Typography } from '../../../common/Typography';
|
|
2
1
|
import React from 'react';
|
|
2
|
+
import { Typography } from '../../../common/Typography';
|
|
3
3
|
|
|
4
4
|
type NoUpcomingBillingProps = {
|
|
5
5
|
description: string;
|
|
@@ -8,8 +8,10 @@ type NoUpcomingBillingProps = {
|
|
|
8
8
|
export function NoUpcomingBilling({ description }: NoUpcomingBillingProps) {
|
|
9
9
|
return (
|
|
10
10
|
<>
|
|
11
|
-
<Typography variant=
|
|
12
|
-
|
|
11
|
+
<Typography variant="h6" color="secondary">
|
|
12
|
+
No upcoming bill
|
|
13
|
+
</Typography>
|
|
14
|
+
<Typography variant="body1" color="secondary">
|
|
13
15
|
{description}
|
|
14
16
|
</Typography>
|
|
15
17
|
</>
|
package/src/components/customerPortal/subscriptionOverview/upcomingBilling/UpcomingBilling.tsx
CHANGED
|
@@ -35,7 +35,7 @@ export function UpcomingBilling({ subscription, theme, textOverrides, onContactS
|
|
|
35
35
|
const { pricingType } = subscription;
|
|
36
36
|
let content: ReactNode;
|
|
37
37
|
const noUsageBasedPrices =
|
|
38
|
-
subscription.prices?.every(price => price.billingModel !== BillingModel.UsageBased) ?? true;
|
|
38
|
+
subscription.prices?.every((price) => price.billingModel !== BillingModel.UsageBased) ?? true;
|
|
39
39
|
const scheduledDowngradeToFree = subscription.scheduledUpdates?.find(
|
|
40
40
|
({ subscriptionScheduleType, targetPackage }) =>
|
|
41
41
|
subscriptionScheduleType === SubscriptionScheduleType.Downgrade &&
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { CustomerPortalEntitlement } from '@stigg/js-client-sdk';
|
|
2
|
-
import { FeatureFragment
|
|
2
|
+
import { FeatureFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
3
3
|
|
|
4
|
-
export type OnBuyMoreCallbackFn = (feature: FeatureFragment, entitlement: CustomerPortalEntitlement) => void
|
|
4
|
+
export type OnBuyMoreCallbackFn = (feature: FeatureFragment, entitlement: CustomerPortalEntitlement) => void;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { useCustomerPortalContext } from '../CustomerPortalProvider';
|
|
2
1
|
import { MeterType, PricingType, SubscriptionStatus } from '@stigg/js-client-sdk';
|
|
3
2
|
import React from 'react';
|
|
3
|
+
import { compact, keyBy } from 'lodash';
|
|
4
|
+
import { Minus, Plus } from 'react-feather';
|
|
5
|
+
import Grid from '@mui/material/Grid';
|
|
6
|
+
import { useCustomerPortalContext } from '../CustomerPortalProvider';
|
|
4
7
|
import { FeatureUsage } from './featureUsage/FeatureUsage';
|
|
5
8
|
import { Footer, CustomerUsageLoader } from './CustomerUsageData.style';
|
|
6
9
|
import { SectionContainer } from '../common/SectionContainer';
|
|
7
10
|
import { SectionHeader } from '../common/SectionHeader';
|
|
8
11
|
import { SectionTitle } from '../common/SectionTitle';
|
|
9
|
-
import { compact, keyBy } from 'lodash';
|
|
10
12
|
import { StyledButton } from '../common/StyledButton';
|
|
11
|
-
import { Minus, Plus } from 'react-feather';
|
|
12
|
-
import Grid from '@mui/material/Grid';
|
|
13
13
|
import { OnBuyMoreCallbackFn } from '../types';
|
|
14
14
|
|
|
15
15
|
const MAX_BOXES = 6;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { CustomerPortalEntitlement } from '@stigg/js-client-sdk';
|
|
2
2
|
import { FeatureFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
3
|
-
import { getUsagePercentage, USAGE_PERCENTAGE_WARNING_THRESHOLD } from './FeatureUsage.helper';
|
|
4
3
|
import Button from '@mui/material/Button';
|
|
5
|
-
import { Typography } from '../../../common/Typography';
|
|
6
4
|
import React from 'react';
|
|
7
|
-
import { OnBuyMoreCallbackFn } from '../../types';
|
|
8
5
|
import styled from 'styled-components';
|
|
6
|
+
import { getUsagePercentage, USAGE_PERCENTAGE_WARNING_THRESHOLD } from './FeatureUsage.helper';
|
|
7
|
+
import { Typography } from '../../../common/Typography';
|
|
8
|
+
import { OnBuyMoreCallbackFn } from '../../types';
|
|
9
9
|
|
|
10
10
|
const StyledButton = styled(Button)`
|
|
11
11
|
text-transform: none;
|
|
@@ -23,8 +23,15 @@ export type EntitlementCtaButtonProps = {
|
|
|
23
23
|
hasCustomSubscription: boolean;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export function EntitlementCtaButton({
|
|
27
|
-
|
|
26
|
+
export function EntitlementCtaButton({
|
|
27
|
+
entitlement,
|
|
28
|
+
feature,
|
|
29
|
+
onManageSubscription,
|
|
30
|
+
onBuyMore,
|
|
31
|
+
canBuyMore,
|
|
32
|
+
canUpgradeSubscription,
|
|
33
|
+
hasCustomSubscription,
|
|
34
|
+
}: EntitlementCtaButtonProps) {
|
|
28
35
|
if (hasCustomSubscription || entitlement.hasUnlimitedUsage) {
|
|
29
36
|
return null;
|
|
30
37
|
}
|
|
@@ -50,4 +57,4 @@ export function EntitlementCtaButton({ entitlement, feature, onManageSubscriptio
|
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
return null;
|
|
53
|
-
}
|
|
60
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { Typography } from '../../../common/Typography';
|
|
2
1
|
import isUndefined from 'lodash/isUndefined';
|
|
3
2
|
import React from 'react';
|
|
4
|
-
import { useCustomerPortalContext } from '../../CustomerPortalProvider';
|
|
5
3
|
import { BillingModel, CustomerPortalEntitlement } from '@stigg/js-client-sdk';
|
|
4
|
+
import { CustomerPortalSubscriptionPriceFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
5
|
+
import { Typography } from '../../../common/Typography';
|
|
6
|
+
import { useCustomerPortalContext } from '../../CustomerPortalProvider';
|
|
6
7
|
import { getResetUsageText, getUsagePercentage } from './FeatureUsage.helper';
|
|
7
8
|
import { getFeatureDisplayName } from '../../../utils/getFeatureName';
|
|
8
9
|
import { FeatureUsageContainer } from './FeatureUsage.style';
|
|
9
10
|
import { FeatureUsageProgressBar } from './FeatureUsageProgressBar';
|
|
10
11
|
import { Icon } from '../../../common/Icon';
|
|
11
12
|
import { InformationTooltip } from '../../../common/InformationTooltip';
|
|
12
|
-
import { CustomerPortalSubscriptionPriceFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
13
13
|
import { LongText } from '../../../common/LongText';
|
|
14
14
|
import { EntitlementCtaButton } from './EntitlementCTAButton';
|
|
15
15
|
import { OnBuyMoreCallbackFn } from '../../types';
|
|
@@ -51,8 +51,7 @@ export function FeatureUsage({
|
|
|
51
51
|
? 'Billed for committed usage'
|
|
52
52
|
: 'Billed for actual usage'}
|
|
53
53
|
</Typography>
|
|
54
|
-
}
|
|
55
|
-
>
|
|
54
|
+
}>
|
|
56
55
|
<Icon icon="DollarCoin" svgStrokeColor={theme.iconsColor} />
|
|
57
56
|
</InformationTooltip>
|
|
58
57
|
)}
|
|
@@ -62,8 +61,7 @@ export function FeatureUsage({
|
|
|
62
61
|
<LongText
|
|
63
62
|
variant="body1"
|
|
64
63
|
color={hasOverageUsage ? 'error' : 'primary'}
|
|
65
|
-
data-testid={`usage-data-${entitlement.feature?.refId}`}
|
|
66
|
-
>
|
|
64
|
+
data-testid={`usage-data-${entitlement.feature?.refId}`}>
|
|
67
65
|
{entitlement.currentUsage?.toLocaleString()}
|
|
68
66
|
{!entitlement.hasUnlimitedUsage &&
|
|
69
67
|
` / ${entitlement.usageLimit?.toLocaleString()} (${getUsagePercentage(
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import styled from '@emotion/styled/macro';
|
|
2
2
|
import LinearProgress from '@mui/material/LinearProgress';
|
|
3
|
-
import { getUsagePercentage, getUsageProgressStatus } from './FeatureUsage.helper';
|
|
4
3
|
import React from 'react';
|
|
5
4
|
import { CustomerPortalEntitlement } from '@stigg/js-client-sdk';
|
|
6
5
|
import Divider from '@mui/material/Divider';
|
|
7
6
|
import Color from 'color';
|
|
7
|
+
import { getUsagePercentage, getUsageProgressStatus } from './FeatureUsage.helper';
|
|
8
8
|
|
|
9
9
|
export const StyledLinearProgress = styled(LinearProgress)<{ $progressStatus: 'standard' | 'warning' | 'error' }>`
|
|
10
10
|
height: 4px;
|
|
@@ -7,8 +7,8 @@ const CHARGES_BILLING_MODEL_ORDER = [BillingModel.FlatFee, BillingModel.PerUnit,
|
|
|
7
7
|
|
|
8
8
|
export const sortCharges = (charges: Price[]) => {
|
|
9
9
|
return sortBy(charges, [
|
|
10
|
-
charge => CHARGES_BILLING_MODEL_ORDER.indexOf(charge.pricingModel),
|
|
11
|
-
charge => charge.feature?.displayName,
|
|
10
|
+
(charge) => CHARGES_BILLING_MODEL_ORDER.indexOf(charge.pricingModel),
|
|
11
|
+
(charge) => charge.feature?.displayName,
|
|
12
12
|
]);
|
|
13
13
|
};
|
|
14
14
|
|
|
@@ -6,6 +6,7 @@ function useQueryParams(paramName?: string) {
|
|
|
6
6
|
return useMemo(() => {
|
|
7
7
|
const urlSearchParams = new URLSearchParams(window.location.search);
|
|
8
8
|
return paramName ? urlSearchParams.get(paramName) : urlSearchParams;
|
|
9
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
9
10
|
}, [paramName, window.location.search]);
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -36,21 +37,28 @@ export const useWaitForCheckoutCompleted = ({
|
|
|
36
37
|
}
|
|
37
38
|
|
|
38
39
|
setIsAwaitingCheckout(true);
|
|
39
|
-
|
|
40
|
+
if (onProvisionStart) {
|
|
41
|
+
onProvisionStart();
|
|
42
|
+
}
|
|
40
43
|
try {
|
|
41
44
|
const subscription = await stigg.waitForCheckoutCompleted();
|
|
42
45
|
setProvisionStatus(ProvisionStatus.SUCCEEDED);
|
|
43
|
-
|
|
46
|
+
if (onProvisionSucceeded) {
|
|
47
|
+
onProvisionSucceeded(subscription);
|
|
48
|
+
}
|
|
44
49
|
} catch (err) {
|
|
45
50
|
console.error('Failed to wait for checkout to complete', err);
|
|
46
51
|
setProvisionStatus(ProvisionStatus.FAILED);
|
|
47
|
-
|
|
52
|
+
if (onProvisionFailed) {
|
|
53
|
+
onProvisionFailed(err);
|
|
54
|
+
}
|
|
48
55
|
} finally {
|
|
49
56
|
setIsAwaitingCheckout(false);
|
|
50
57
|
}
|
|
51
58
|
};
|
|
52
59
|
|
|
53
|
-
waitForCheckoutToComplete();
|
|
60
|
+
void waitForCheckoutToComplete();
|
|
61
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
62
|
}, [stigg, checkoutCompleted]);
|
|
55
63
|
|
|
56
64
|
return { isAwaitingCheckout, provisionStatus };
|
|
@@ -33,8 +33,8 @@ export function PlanEntitlements({
|
|
|
33
33
|
billingPeriod: BillingPeriod;
|
|
34
34
|
paywallLocale: PaywallLocalization;
|
|
35
35
|
}) {
|
|
36
|
-
const prices = plan.pricePoints?.filter(price => price.billingPeriod === billingPeriod);
|
|
37
|
-
const unitBasedEntitlements = prices?.map(price => {
|
|
36
|
+
const prices = plan.pricePoints?.filter((price) => price.billingPeriod === billingPeriod);
|
|
37
|
+
const unitBasedEntitlements = prices?.map((price) => {
|
|
38
38
|
const shouldRenderUnitBasedEntitlement =
|
|
39
39
|
(price?.minUnitQuantity && price?.minUnitQuantity > 1) || price?.maxUnitQuantity;
|
|
40
40
|
|
|
@@ -59,8 +59,8 @@ export function PlanEntitlements({
|
|
|
59
59
|
</Typography>
|
|
60
60
|
{unitBasedEntitlements}
|
|
61
61
|
{plan.entitlements
|
|
62
|
-
.filter(entitlement => !(entitlement.hiddenFromWidgets || []).includes(WidgetType.Paywall))
|
|
63
|
-
.map(entitlement => (
|
|
62
|
+
.filter((entitlement) => !(entitlement.hiddenFromWidgets || []).includes(WidgetType.Paywall))
|
|
63
|
+
.map((entitlement) => (
|
|
64
64
|
<EntitlementRow
|
|
65
65
|
key={entitlement.feature?.id}
|
|
66
66
|
displayNameOverride={entitlement.displayNameOverride}
|
|
@@ -6,7 +6,7 @@ import { PaywallData } from '../types';
|
|
|
6
6
|
import { computeBillingPeriods } from '../utils/computeDefaultBillingPeriod';
|
|
7
7
|
import { mapPaywallData } from '../utils/mapPaywallData';
|
|
8
8
|
|
|
9
|
-
type
|
|
9
|
+
type UseLoadPaywallDataProps = {
|
|
10
10
|
productId?: string;
|
|
11
11
|
resourceId?: string;
|
|
12
12
|
showOnlyEligiblePlans?: boolean;
|
|
@@ -20,7 +20,7 @@ export function useLoadPaywallData({
|
|
|
20
20
|
showOnlyEligiblePlans,
|
|
21
21
|
billingCountryCode,
|
|
22
22
|
preferredBillingPeriod,
|
|
23
|
-
}:
|
|
23
|
+
}: UseLoadPaywallDataProps): PaywallData {
|
|
24
24
|
const { stigg, locale } = useStiggContext();
|
|
25
25
|
const [selectedBillingPeriod, setSelectedBillingPeriod] = useState(BillingPeriod.Annually);
|
|
26
26
|
const [availableBillingPeriods, setAvailableBillingPeriods] = useState<BillingPeriod[]>([]);
|
|
@@ -55,13 +55,13 @@ export function useLoadPaywallData({
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
void loadPaywall();
|
|
58
|
-
}, [stigg, productId, stigg.isCustomerLoaded, billingCountryCode, resourceId]);
|
|
58
|
+
}, [stigg, productId, stigg.isCustomerLoaded, billingCountryCode, resourceId, preferredBillingPeriod]);
|
|
59
59
|
|
|
60
60
|
const paywallData = mapPaywallData(paywall, showOnlyEligiblePlans);
|
|
61
61
|
|
|
62
62
|
return {
|
|
63
63
|
customer: paywall?.customer || null,
|
|
64
|
-
isLoading
|
|
64
|
+
isLoading,
|
|
65
65
|
selectedBillingPeriod,
|
|
66
66
|
setSelectedBillingPeriod,
|
|
67
67
|
availableBillingPeriods,
|
|
@@ -51,7 +51,7 @@ export function getResolvedPaywallLocalize(localizeOverride?: DeepPartial<Paywal
|
|
|
51
51
|
custom: 'Contact us',
|
|
52
52
|
currentPlan: 'Current plan',
|
|
53
53
|
startNew: 'Get started',
|
|
54
|
-
switchToBillingPeriod: billingPeriod => {
|
|
54
|
+
switchToBillingPeriod: (billingPeriod) => {
|
|
55
55
|
return billingPeriod === BillingPeriod.Monthly ? 'Switch to monthly billing' : 'Switch to annual billing';
|
|
56
56
|
},
|
|
57
57
|
cancelScheduledUpdate: 'Cancel',
|
|
@@ -59,7 +59,7 @@ export function getResolvedPaywallLocalize(localizeOverride?: DeepPartial<Paywal
|
|
|
59
59
|
price: {
|
|
60
60
|
startingAtCaption: 'Starts at',
|
|
61
61
|
pricePeriod: (billingPeriod: BillingPeriod) => (billingPeriod === BillingPeriod.Monthly ? '/ month' : '/ year'),
|
|
62
|
-
free: currency => ({
|
|
62
|
+
free: (currency) => ({
|
|
63
63
|
price: `${currency?.symbol}0`,
|
|
64
64
|
}),
|
|
65
65
|
custom: 'Custom',
|
|
@@ -6,7 +6,7 @@ export function computeBillingPeriods(
|
|
|
6
6
|
activeSubscriptions?: Subscription[] | null,
|
|
7
7
|
preferredBillingPeriod?: BillingPeriod,
|
|
8
8
|
): { defaultBillingPeriod: BillingPeriod; availableBillingPeriods: BillingPeriod[] } {
|
|
9
|
-
const billingPeriods = plans.flatMap(x => x.pricePoints).map(x => x.billingPeriod);
|
|
9
|
+
const billingPeriods = plans.flatMap((x) => x.pricePoints).map((x) => x.billingPeriod);
|
|
10
10
|
const counts = countBy(billingPeriods);
|
|
11
11
|
|
|
12
12
|
const availableBillingPeriods = uniq(billingPeriods);
|
|
@@ -15,7 +15,7 @@ export function computeBillingPeriods(
|
|
|
15
15
|
if (preferredBillingPeriod && availableBillingPeriods.includes(preferredBillingPeriod)) {
|
|
16
16
|
defaultBillingPeriod = preferredBillingPeriod;
|
|
17
17
|
} else if (activeSubscriptions) {
|
|
18
|
-
const activeSubscription = activeSubscriptions.find(x => x.status
|
|
18
|
+
const activeSubscription = activeSubscriptions.find((x) => x.status === SubscriptionStatus.Active);
|
|
19
19
|
|
|
20
20
|
if (activeSubscription && activeSubscription.prices.length > 0) {
|
|
21
21
|
defaultBillingPeriod = activeSubscription?.prices[0].billingPeriod;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { PaywallPlan } from '../types';
|
|
2
1
|
import { BillingPeriod } from '@stigg/js-client-sdk';
|
|
2
|
+
import { PaywallPlan } from '../types';
|
|
3
3
|
|
|
4
|
-
export function
|
|
5
|
-
return
|
|
4
|
+
export function hasPricePoints(plan: PaywallPlan, billingPeriod: BillingPeriod): boolean {
|
|
5
|
+
return plan.pricePoints.some((pricePoint) => pricePoint.billingPeriod === billingPeriod);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export function
|
|
9
|
-
return
|
|
10
|
-
}
|
|
8
|
+
export function hasPricePointsForPlans(plans: PaywallPlan[], billingPeriod: BillingPeriod): boolean {
|
|
9
|
+
return plans.some((plan) => hasPricePoints(plan, billingPeriod));
|
|
10
|
+
}
|
|
@@ -14,14 +14,14 @@ export function calculateDiscountRate(monthlyPrice?: number | null, annuallyPric
|
|
|
14
14
|
function getPlanBillingPeriodAmount(plan: PaywallPlan, billingPeriod: BillingPeriod) {
|
|
15
15
|
let pricePoint: PaywallCalculatedPricePoint | Price | undefined;
|
|
16
16
|
|
|
17
|
-
pricePoint = plan.paywallCalculatedPricePoints?.find(price => price.billingPeriod === billingPeriod);
|
|
17
|
+
pricePoint = plan.paywallCalculatedPricePoints?.find((price) => price.billingPeriod === billingPeriod);
|
|
18
18
|
|
|
19
19
|
if (!pricePoint) {
|
|
20
|
-
pricePoint = plan.pricePoints.find(price => price.billingPeriod === billingPeriod);
|
|
20
|
+
pricePoint = plan.pricePoints.find((price) => price.billingPeriod === billingPeriod);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
if (!pricePoint?.amount) {
|
|
24
|
-
const tieredPrice = plan.pricePoints.find(price => {
|
|
24
|
+
const tieredPrice = plan.pricePoints.find((price) => {
|
|
25
25
|
return price.isTieredPrice && price.billingPeriod === billingPeriod;
|
|
26
26
|
});
|
|
27
27
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { FeatureFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
2
2
|
import lowercase from 'lodash/lowerCase';
|
|
3
3
|
|
|
4
|
-
export function
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if(!featureUnits && !featureUnitsPlural) {
|
|
4
|
+
export function getFeatureDisplayNameText(
|
|
5
|
+
featureDisplayName: string,
|
|
6
|
+
featureUnits: string | undefined | null,
|
|
7
|
+
featureUnitsPlural: string | undefined | null,
|
|
8
|
+
) {
|
|
9
|
+
if (!featureUnits && !featureUnitsPlural) {
|
|
10
10
|
return featureDisplayName;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -19,4 +19,8 @@ export function getFeatureDisplayNameText(featureDisplayName: string, featureUni
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
return `${featureDisplayName} (${featureUnitsPlural})`;
|
|
22
|
-
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getFeatureDisplayName(feature: FeatureFragment) {
|
|
25
|
+
return getFeatureDisplayNameText(feature.displayName, feature.featureUnits, feature.featureUnitsPlural);
|
|
26
|
+
}
|
|
@@ -69,9 +69,9 @@ export function getPaidPriceText({
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
return {
|
|
72
|
-
price: currencyPriceFormatter({ amount: priceNumber, currency
|
|
73
|
-
unit
|
|
74
|
-
tiers
|
|
75
|
-
tierUnits
|
|
72
|
+
price: currencyPriceFormatter({ amount: priceNumber, currency, locale }),
|
|
73
|
+
unit,
|
|
74
|
+
tiers,
|
|
75
|
+
tierUnits,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { BillingPeriod, PriceTierFragment, PricingType } from '@stigg/js-client-sdk';
|
|
2
|
-
import { PaywallPlan } from '../paywall';
|
|
3
|
-
import { PaywallLocalization } from '../paywall';
|
|
2
|
+
import { PaywallPlan, PaywallLocalization } from '../paywall';
|
|
4
3
|
import { getPaidPriceText } from './getPaidPriceText';
|
|
5
4
|
|
|
6
5
|
export type PlanPriceText = {
|
|
@@ -24,15 +23,15 @@ export function getPlanPrice(
|
|
|
24
23
|
return paywallLocale.price.free(plan.paywallCurrency);
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
return paywallLocale.price.free
|
|
26
|
+
return paywallLocale.price.free;
|
|
28
27
|
case PricingType.Custom:
|
|
29
28
|
return {
|
|
30
29
|
price: paywallLocale.price.custom,
|
|
31
30
|
};
|
|
32
31
|
case PricingType.Paid: {
|
|
33
|
-
const planPrices = plan.pricePoints.filter(pricePoint => pricePoint.billingPeriod === billingPeriod);
|
|
32
|
+
const planPrices = plan.pricePoints.filter((pricePoint) => pricePoint.billingPeriod === billingPeriod);
|
|
34
33
|
const paywallCalculatedPrice = plan.paywallCalculatedPricePoints?.find(
|
|
35
|
-
pricePoint => pricePoint.billingPeriod === billingPeriod,
|
|
34
|
+
(pricePoint) => pricePoint.billingPeriod === billingPeriod,
|
|
36
35
|
);
|
|
37
36
|
|
|
38
37
|
if (!planPrices?.length && !paywallCalculatedPrice) {
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
CustomerPortalSubscriptionScheduledUpdateDataFragment,
|
|
7
7
|
SubscriptionScheduleType,
|
|
8
8
|
} from '@stigg/js-client-sdk';
|
|
9
|
-
import { BillingPeriodChangeVariables, UnitAmountChangeVariables } from '../../types';
|
|
10
9
|
import { CustomerPortalSubscriptionPriceFragment } from '@stigg/api-client-js/src/generated/sdk';
|
|
11
10
|
import { compact, map } from 'lodash';
|
|
11
|
+
import { BillingPeriodChangeVariables, UnitAmountChangeVariables } from '../../types';
|
|
12
12
|
|
|
13
13
|
const formatDate = (date: string) => moment.utc(date).format('MMMM Do, yyyy');
|
|
14
14
|
|