@bunnyapp/components 1.7.0-beta.32 → 1.7.0-beta.34
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/cjs/index.js +1621 -1663
- package/dist/cjs/types/src/components/Signup/CheckoutSummary.d.ts +29 -3
- package/dist/cjs/types/src/components/Signup/PaymentForms.d.ts +1 -1
- package/dist/cjs/types/src/components/Signup/PriceListDisplay.d.ts +2 -0
- package/dist/cjs/types/src/components/Signup/fragments/Signup_PriceListFragment.d.ts +1 -0
- package/dist/cjs/types/src/components/Signup/fragments/Signup_QuoteFragment.d.ts +17 -0
- package/dist/cjs/types/src/components/Signup/mutations/accountSignup.d.ts +58 -0
- package/dist/cjs/types/src/components/Signup/mutations/quoteAccountSignup.d.ts +31 -0
- package/dist/cjs/types/src/{graphql → components/Signup}/mutations/quoteRecalculateTaxes.d.ts +5 -1
- package/dist/cjs/types/src/components/Signup/queries/getQuote.d.ts +10 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +8 -3
- package/dist/cjs/types/src/utils/couponUtils.d.ts +2 -1
- package/dist/esm/index.js +1623 -1665
- package/dist/esm/types/src/components/Signup/CheckoutSummary.d.ts +29 -3
- package/dist/esm/types/src/components/Signup/PaymentForms.d.ts +1 -1
- package/dist/esm/types/src/components/Signup/PriceListDisplay.d.ts +2 -0
- package/dist/esm/types/src/components/Signup/fragments/Signup_PriceListFragment.d.ts +1 -0
- package/dist/esm/types/src/components/Signup/fragments/Signup_QuoteFragment.d.ts +17 -0
- package/dist/esm/types/src/components/Signup/mutations/accountSignup.d.ts +58 -0
- package/dist/esm/types/src/components/Signup/mutations/quoteAccountSignup.d.ts +31 -0
- package/dist/esm/types/src/{graphql → components/Signup}/mutations/quoteRecalculateTaxes.d.ts +5 -1
- package/dist/esm/types/src/components/Signup/queries/getQuote.d.ts +10 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +8 -3
- package/dist/esm/types/src/utils/couponUtils.d.ts +2 -1
- package/package.json +2 -2
- package/dist/cjs/types/src/graphql/mutations/accountSignup.d.ts +0 -11
- package/dist/cjs/types/src/graphql/mutations/quoteAccountSignup.d.ts +0 -15
- package/dist/cjs/types/src/graphql/queries/getQuote.d.ts +0 -36
- package/dist/esm/types/src/graphql/mutations/accountSignup.d.ts +0 -11
- package/dist/esm/types/src/graphql/mutations/quoteAccountSignup.d.ts +0 -15
- package/dist/esm/types/src/graphql/queries/getQuote.d.ts +0 -36
package/dist/esm/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { useState, useEffect, isValidElement, createContext, useContext, useMemo, createElement, useRef, useCallback, Fragment as Fragment$1 } from 'react';
|
|
3
|
-
import { WarningOutlined, CheckCircleOutlined, CreditCardOutlined, EllipsisOutlined, BankOutlined, DownloadOutlined, SearchOutlined,
|
|
4
|
-
import { notification, theme, ConfigProvider, Tag, Button, Dropdown, Typography, Input, Modal, Checkbox, Skeleton, Collapse, Spin, Form, Tooltip, Drawer, Card as Card$1,
|
|
3
|
+
import { WarningOutlined, CheckCircleOutlined, CreditCardOutlined, EllipsisOutlined, BankOutlined, DownloadOutlined, SearchOutlined, CheckCircleFilled, InfoCircleOutlined, CloseOutlined } from '@ant-design/icons';
|
|
4
|
+
import { notification, theme, ConfigProvider, Tag, Button, Dropdown, Typography, Input, Modal, Checkbox, Skeleton, Collapse, Spin, Form, Tooltip, Drawer, Card as Card$1, Divider, Select, Popconfirm, Table, Radio, Space, Switch } from 'antd';
|
|
5
5
|
import { QueryClient, QueryCache, QueryClientProvider, useQuery, useMutation, useQueryClient, keepPreviousData } from '@tanstack/react-query';
|
|
6
6
|
import request$1 from 'graphql-request';
|
|
7
7
|
import { RecoilRoot } from 'recoil';
|
|
@@ -1281,7 +1281,7 @@ const DEFAULT_CONFIG = {
|
|
|
1281
1281
|
};
|
|
1282
1282
|
|
|
1283
1283
|
// This will be replaced at build time by rollup-plugin-replace
|
|
1284
|
-
const PACKAGE_VERSION = '1.7.0-beta.
|
|
1284
|
+
const PACKAGE_VERSION = '1.7.0-beta.33';
|
|
1285
1285
|
const createRequestHeaders = (token) => {
|
|
1286
1286
|
const headers = createClientDevHeaders({ token });
|
|
1287
1287
|
// Add the components version header
|
|
@@ -1331,7 +1331,7 @@ const createClientDevHeaders = ({ token, componentsVersion, additionalHeaders, }
|
|
|
1331
1331
|
return headers;
|
|
1332
1332
|
};
|
|
1333
1333
|
|
|
1334
|
-
const MUTATION$
|
|
1334
|
+
const MUTATION$5 = `
|
|
1335
1335
|
query FormattedInvoice($id: ID) {
|
|
1336
1336
|
formattedInvoice(id: $id) {
|
|
1337
1337
|
amount
|
|
@@ -1399,7 +1399,7 @@ query FormattedInvoice($id: ID) {
|
|
|
1399
1399
|
const getFormattedInvoice = async ({ id, token, apiHost, }) => {
|
|
1400
1400
|
const vars = { id };
|
|
1401
1401
|
const response = await gqlRequest({
|
|
1402
|
-
query: MUTATION$
|
|
1402
|
+
query: MUTATION$5,
|
|
1403
1403
|
token,
|
|
1404
1404
|
vars,
|
|
1405
1405
|
apiHost,
|
|
@@ -2246,7 +2246,7 @@ function readFragment(...r) {
|
|
|
2246
2246
|
|
|
2247
2247
|
var t = initGraphQLTada();
|
|
2248
2248
|
|
|
2249
|
-
const query$
|
|
2249
|
+
const query$a = t(`
|
|
2250
2250
|
query entityBranding {
|
|
2251
2251
|
entityBranding {
|
|
2252
2252
|
accentColor
|
|
@@ -2256,13 +2256,17 @@ const query$9 = t(`
|
|
|
2256
2256
|
}
|
|
2257
2257
|
`);
|
|
2258
2258
|
const getBranding = async ({ token, apiHost }) => {
|
|
2259
|
-
return await execute(query$
|
|
2259
|
+
return await execute(query$a, { apiHost, token }, {});
|
|
2260
2260
|
};
|
|
2261
2261
|
|
|
2262
2262
|
const BunnyContext = createContext({});
|
|
2263
2263
|
// Every component shares similar props and functionality, which this wrapper handles.
|
|
2264
2264
|
function BunnyProvider({ children, darkMode = false, queryClient, apiHost, token, onTokenExpired, onUserUnavailable, onInvalidOrMissingAuthorization, suppressUserUnavailableErrorNotification = false, configProviderProps, }) {
|
|
2265
|
-
return (jsx(BunnyProviderCallbacksProvider, { value: {
|
|
2265
|
+
return (jsx(BunnyProviderCallbacksProvider, { value: {
|
|
2266
|
+
onUserUnavailable,
|
|
2267
|
+
onInvalidOrMissingAuthorization,
|
|
2268
|
+
suppressUserUnavailableErrorNotification,
|
|
2269
|
+
}, children: jsx(BunnyProviderContent, { darkMode: darkMode, queryClient: queryClient, apiHost: apiHost, token: token, onTokenExpired: onTokenExpired, configProviderProps: configProviderProps, children: children }) }));
|
|
2266
2270
|
}
|
|
2267
2271
|
function BunnyProviderContent({ children, darkMode = false, queryClient, apiHost, token, onTokenExpired, configProviderProps, }) {
|
|
2268
2272
|
const createQueryClient = useCreateQueryClient();
|
|
@@ -19830,7 +19834,7 @@ const PaymentForm_PaymentMethodsFragment = t(`
|
|
|
19830
19834
|
}
|
|
19831
19835
|
`, [MiniCreditCard_PaymentMethodFragment]);
|
|
19832
19836
|
|
|
19833
|
-
const query$
|
|
19837
|
+
const query$9 = t(`
|
|
19834
19838
|
query PaymentMethods($accountId: ID) {
|
|
19835
19839
|
paymentMethods(accountId: $accountId) {
|
|
19836
19840
|
nodes {
|
|
@@ -19859,7 +19863,7 @@ const query$8 = t(`
|
|
|
19859
19863
|
`, [PaymentForm_PaymentMethodsFragment]);
|
|
19860
19864
|
const getPaymentMethods = async ({ apiHost, token, accountId, }) => {
|
|
19861
19865
|
var _a, _b, _c;
|
|
19862
|
-
const response = await execute(query$
|
|
19866
|
+
const response = await execute(query$9, { apiHost, token }, { accountId });
|
|
19863
19867
|
// Filter out null values that are technically possible due to api schema
|
|
19864
19868
|
return (_c = (_b = (_a = response === null || response === void 0 ? void 0 : response.paymentMethods) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.filter(paymentMethod => paymentMethod !== null)) !== null && _c !== void 0 ? _c : [];
|
|
19865
19869
|
};
|
|
@@ -19884,7 +19888,7 @@ const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
|
19884
19888
|
};
|
|
19885
19889
|
};
|
|
19886
19890
|
|
|
19887
|
-
const mutation$
|
|
19891
|
+
const mutation$g = t(`
|
|
19888
19892
|
query PaymentPlugins($accountId: ID) {
|
|
19889
19893
|
paymentPlugins(accountId: $accountId) {
|
|
19890
19894
|
enabled
|
|
@@ -19912,7 +19916,7 @@ const mutation$e = t(`
|
|
|
19912
19916
|
// }[];
|
|
19913
19917
|
// };
|
|
19914
19918
|
const getPaymentPlugins = async ({ apiHost, token, accountId, }) => {
|
|
19915
|
-
const response = await execute(mutation$
|
|
19919
|
+
const response = await execute(mutation$g, { apiHost, token }, { accountId });
|
|
19916
19920
|
return response === null || response === void 0 ? void 0 : response.paymentPlugins;
|
|
19917
19921
|
};
|
|
19918
19922
|
const usePaymentPlugins = (accountId) => {
|
|
@@ -20131,7 +20135,7 @@ function useSave$1({ onSaveSuccess, onSaveError, accountId, }) {
|
|
|
20131
20135
|
return { save, isSaving };
|
|
20132
20136
|
}
|
|
20133
20137
|
|
|
20134
|
-
const MUTATION$
|
|
20138
|
+
const MUTATION$4 = `
|
|
20135
20139
|
mutation checkout(
|
|
20136
20140
|
$invoiceId: ID,
|
|
20137
20141
|
$quoteId: ID,
|
|
@@ -20180,7 +20184,7 @@ const checkout = async ({ quoteId, invoiceId, paymentMethodId, paymentMethodData
|
|
|
20180
20184
|
};
|
|
20181
20185
|
}
|
|
20182
20186
|
const response = await gqlRequest({
|
|
20183
|
-
query: MUTATION$
|
|
20187
|
+
query: MUTATION$4,
|
|
20184
20188
|
token,
|
|
20185
20189
|
vars: mutationVars,
|
|
20186
20190
|
apiHost: apiHost,
|
|
@@ -21181,7 +21185,7 @@ const useAutoSetDefaultPaymentMethod = ({ handleSetDefault, setDefaultPaymentMet
|
|
|
21181
21185
|
]);
|
|
21182
21186
|
};
|
|
21183
21187
|
|
|
21184
|
-
const query$
|
|
21188
|
+
const query$8 = t(`
|
|
21185
21189
|
query GetCurrentUserData {
|
|
21186
21190
|
company {
|
|
21187
21191
|
name
|
|
@@ -21204,7 +21208,7 @@ const query$7 = t(`
|
|
|
21204
21208
|
`);
|
|
21205
21209
|
const getCurrentUserData = async ({ token, apiHost }) => {
|
|
21206
21210
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
21207
|
-
const response = await execute(query$
|
|
21211
|
+
const response = await execute(query$8, { apiHost, token }, {});
|
|
21208
21212
|
return {
|
|
21209
21213
|
authObjectName: (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.authObjectName,
|
|
21210
21214
|
account: (_b = response === null || response === void 0 ? void 0 : response.currentUser) === null || _b === void 0 ? void 0 : _b.account,
|
|
@@ -21971,7 +21975,7 @@ const StyledModal$2 = (props) => {
|
|
|
21971
21975
|
return jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
21972
21976
|
};
|
|
21973
21977
|
|
|
21974
|
-
const query$
|
|
21978
|
+
const query$7 = t(`
|
|
21975
21979
|
query formattedQuote($id: ID) {
|
|
21976
21980
|
formattedQuote(id: $id) {
|
|
21977
21981
|
quote {
|
|
@@ -22122,7 +22126,7 @@ const query$6 = t(`
|
|
|
22122
22126
|
QuoteButtons_FormattedQuoteFragment,
|
|
22123
22127
|
]);
|
|
22124
22128
|
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
22125
|
-
const response = await execute(query$
|
|
22129
|
+
const response = await execute(query$7, { apiHost, token }, { id });
|
|
22126
22130
|
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
22127
22131
|
};
|
|
22128
22132
|
|
|
@@ -22936,6 +22940,110 @@ function QuotesWrapper() {
|
|
|
22936
22940
|
return (jsx(TransactionsDisplay, { transactions: quotesAsTransactions, onSearchValueChanged: setSearch, search: search }));
|
|
22937
22941
|
}
|
|
22938
22942
|
|
|
22943
|
+
const shouldShowCouponEditor_QuoteFragment = t(`
|
|
22944
|
+
fragment shouldShowCouponEditor_QuoteFragment on Quote {
|
|
22945
|
+
id
|
|
22946
|
+
kind
|
|
22947
|
+
amountDue
|
|
22948
|
+
}
|
|
22949
|
+
`, []);
|
|
22950
|
+
const shouldShowCouponEditor_SubscriptionFragment = t(`
|
|
22951
|
+
fragment shouldShowCouponEditor_SubscriptionFragment on Subscription {
|
|
22952
|
+
id
|
|
22953
|
+
state
|
|
22954
|
+
charges {
|
|
22955
|
+
discountedPrice
|
|
22956
|
+
}
|
|
22957
|
+
}
|
|
22958
|
+
`, []);
|
|
22959
|
+
function shouldShowCouponEditor(maskedQuote, activeCouponsExist, maskedUpgradingSubscription) {
|
|
22960
|
+
var _a, _b;
|
|
22961
|
+
const quote = readFragment(shouldShowCouponEditor_QuoteFragment, maskedQuote);
|
|
22962
|
+
const upgradingSubscription = readFragment(shouldShowCouponEditor_SubscriptionFragment, maskedUpgradingSubscription);
|
|
22963
|
+
const upgradingFromTrial = ((_a = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') ||
|
|
22964
|
+
((_b = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) ===
|
|
22965
|
+
t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
22966
|
+
const signingUpForNewSubscription = upgradingSubscription === undefined;
|
|
22967
|
+
function upgradingFromFree() {
|
|
22968
|
+
var _a;
|
|
22969
|
+
const totalPrice = (_a = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.charges) === null || _a === void 0 ? void 0 : _a.reduce((acc, charge) => acc + Number((charge === null || charge === void 0 ? void 0 : charge.discountedPrice) || 0), 0);
|
|
22970
|
+
return totalPrice === 0;
|
|
22971
|
+
}
|
|
22972
|
+
const quoteKindIsValid = (quote === null || quote === void 0 ? void 0 : quote.kind) === t.scalar('QuoteChangeKind', 'SUBSCRIBE') ||
|
|
22973
|
+
(quote === null || quote === void 0 ? void 0 : quote.kind) === t.scalar('QuoteChangeKind', 'ADJUSTMENT') ||
|
|
22974
|
+
(quote === null || quote === void 0 ? void 0 : quote.kind) === t.scalar('QuoteChangeKind', 'ACTIVATE');
|
|
22975
|
+
// if amount due is 0 do not show coupon editor
|
|
22976
|
+
if ((quote === null || quote === void 0 ? void 0 : quote.amountDue) == 0) {
|
|
22977
|
+
return false;
|
|
22978
|
+
}
|
|
22979
|
+
if (quoteKindIsValid) {
|
|
22980
|
+
return activeCouponsExist && (upgradingFromTrial || upgradingFromFree() || signingUpForNewSubscription);
|
|
22981
|
+
}
|
|
22982
|
+
return false;
|
|
22983
|
+
}
|
|
22984
|
+
|
|
22985
|
+
function CouponEditor({ className, onAddCoupon, isAddingCoupon, couponCode, setCouponCode, }) {
|
|
22986
|
+
async function handleAddCoupon() {
|
|
22987
|
+
onAddCoupon(couponCode);
|
|
22988
|
+
}
|
|
22989
|
+
return (jsx("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 ${className}`, children: jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2", children: [jsx(Input, { value: couponCode, onChange: e => setCouponCode(e.target.value), placeholder: "Coupon code", disabled: isAddingCoupon, size: "small" }), jsx(Button, { loading: isAddingCoupon, type: "primary", onClick: handleAddCoupon, disabled: couponCode.length === 0, children: "Apply" })] }) }));
|
|
22990
|
+
}
|
|
22991
|
+
|
|
22992
|
+
const { Text: Text$q } = Typography;
|
|
22993
|
+
const CheckoutSummary_PriceListFragment = t(`
|
|
22994
|
+
fragment CheckoutSummary_PriceListFragment on PriceList {
|
|
22995
|
+
product {
|
|
22996
|
+
name
|
|
22997
|
+
}
|
|
22998
|
+
name
|
|
22999
|
+
}
|
|
23000
|
+
`);
|
|
23001
|
+
const CheckoutSummary_QuoteFragment = t(`
|
|
23002
|
+
fragment CheckoutSummary_QuoteFragment on Quote {
|
|
23003
|
+
id
|
|
23004
|
+
amountDue
|
|
23005
|
+
subtotal
|
|
23006
|
+
taxAmount
|
|
23007
|
+
currencyId
|
|
23008
|
+
quoteChanges {
|
|
23009
|
+
charges {
|
|
23010
|
+
id
|
|
23011
|
+
kind
|
|
23012
|
+
name
|
|
23013
|
+
coupon {
|
|
23014
|
+
couponCode
|
|
23015
|
+
}
|
|
23016
|
+
quantity
|
|
23017
|
+
subtotal
|
|
23018
|
+
currencyId
|
|
23019
|
+
}
|
|
23020
|
+
}
|
|
23021
|
+
...shouldShowCouponEditor_QuoteFragment
|
|
23022
|
+
}
|
|
23023
|
+
`, [shouldShowCouponEditor_QuoteFragment]);
|
|
23024
|
+
function CheckoutSummary({ quote: maskedQuote, className, onAddCoupon, onRemoveCoupon, isRemovingCoupon, priceList: maskedPriceList, isAddingCoupon, couponCode, setCouponCode, activeCouponsExist, }) {
|
|
23025
|
+
var _a, _b;
|
|
23026
|
+
const priceList = readFragment(CheckoutSummary_PriceListFragment, maskedPriceList);
|
|
23027
|
+
const quote = readFragment(CheckoutSummary_QuoteFragment, maskedQuote);
|
|
23028
|
+
return (jsxs("div", { className: `${className} bunny-space-y-4`, children: [jsxs(Text$q, { children: [jsxs("div", { className: "bunny-text-lg bunny-font-medium bunny-mb-4", children: ["Checkout summary - ", (_a = priceList === null || priceList === void 0 ? void 0 : priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList === null || priceList === void 0 ? void 0 : priceList.name] }), jsx("div", { className: "bunny-space-y-4", children: (_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.map(quoteChange => quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges.map(charge => {
|
|
23029
|
+
var _a;
|
|
23030
|
+
const multiplier = charge.kind === 'COUPON' ? -1 : 1;
|
|
23031
|
+
return (jsxs("div", { className: "bunny-grid bunny-grid-cols-3 bunny-gap-4 bunny-items-center", children: [jsx("div", { className: "bunny-col-span-1", children: charge.name }), jsx("div", { className: "bunny-col-span-1 bunny-text-center", children: ((_a = charge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode) ? (jsx("button", { onClick: () => {
|
|
23032
|
+
var _a, _b;
|
|
23033
|
+
if (isRemovingCoupon) {
|
|
23034
|
+
return;
|
|
23035
|
+
}
|
|
23036
|
+
if (!((_a = charge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode)) {
|
|
23037
|
+
throw new Error('Coupon code not found');
|
|
23038
|
+
}
|
|
23039
|
+
onRemoveCoupon((_b = charge.coupon) === null || _b === void 0 ? void 0 : _b.couponCode);
|
|
23040
|
+
}, className: "bunny-text-orange-500 hover:bunny-text-orange-400 bunny-cursor-pointer bunny-bg-transparent bunny-border-none", children: "Remove" })) : (jsx("div", { children: charge.quantity })) }), jsx("div", { className: "bunny-col-span-1 bunny-text-right", children: formatCurrency(multiplier * (charge.subtotal || 0), charge.currencyId) })] }, charge.id));
|
|
23041
|
+
})) }), jsx(CheckoutSummaryDivider, {}), jsxs("div", { className: "bunny-space-y-4", children: [jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Subtotal" }), jsx("div", { children: formatCurrency(quote.subtotal, quote.currencyId) })] }), jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Taxes" }), jsx("div", { children: formatCurrency(quote.taxAmount, quote.currencyId) })] })] }), jsx(CheckoutSummaryDivider, {}), jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Total" }), jsx("div", { children: formatCurrency(quote.amountDue, quote.currencyId) })] })] }), shouldShowCouponEditor(quote, activeCouponsExist) && (jsx(CouponEditor, { className: "bunny-w-full", onAddCoupon: onAddCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode }))] }));
|
|
23042
|
+
}
|
|
23043
|
+
const CheckoutSummaryDivider = () => {
|
|
23044
|
+
return (jsx("div", { className: "bunny-my-2", children: jsx(Divider, { className: "m-0" }) }));
|
|
23045
|
+
};
|
|
23046
|
+
|
|
22939
23047
|
const { Title: Title$1 } = Typography;
|
|
22940
23048
|
const PaymentForms_QuoteFragment = t(`
|
|
22941
23049
|
fragment PaymentForms_QuoteFragment on Quote {
|
|
@@ -22981,404 +23089,77 @@ function InitialSignupForm({ className, onSubmit, submitting, defaultValues, })
|
|
|
22981
23089
|
} }) }) }) }), jsx(Form.Item, { children: jsx(Button, { type: "primary", onClick: handleSubmit, loading: submitting, className: "bunny-w-full", children: "Proceed to payment" }) })] }) }));
|
|
22982
23090
|
}
|
|
22983
23091
|
|
|
22984
|
-
const
|
|
22985
|
-
|
|
22986
|
-
|
|
22987
|
-
|
|
22988
|
-
|
|
22989
|
-
|
|
22990
|
-
|
|
22991
|
-
|
|
22992
|
-
|
|
22993
|
-
})(ChargeType || (ChargeType = {}));
|
|
22994
|
-
var ChargeType$1 = ChargeType;
|
|
22995
|
-
|
|
22996
|
-
const canSubscriptionUpgradeFromTrial_SubscriptionFragment = t(`
|
|
22997
|
-
fragment canSubscriptionUpgradeFromTrial_SubscriptionFragment on Subscription {
|
|
22998
|
-
state
|
|
22999
|
-
plan {
|
|
23000
|
-
selfServiceBuy
|
|
23092
|
+
const Signup_QuoteFragment = t(`
|
|
23093
|
+
fragment Signup_QuoteFragment on Quote {
|
|
23094
|
+
...CheckoutSummary_QuoteFragment
|
|
23095
|
+
...PaymentForms_QuoteFragment
|
|
23096
|
+
id
|
|
23097
|
+
currencyId
|
|
23098
|
+
amountDue
|
|
23099
|
+
quoteChanges {
|
|
23100
|
+
id
|
|
23001
23101
|
}
|
|
23002
23102
|
}
|
|
23003
|
-
|
|
23004
|
-
const canSubscriptionUpgradeFromTrial = (maskedSubscription) => {
|
|
23005
|
-
var _a, _b;
|
|
23006
|
-
const subscription = readFragment(canSubscriptionUpgradeFromTrial_SubscriptionFragment, maskedSubscription);
|
|
23007
|
-
return ((((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
23008
|
-
((_b = subscription.plan) === null || _b === void 0 ? void 0 : _b.selfServiceBuy)) ||
|
|
23009
|
-
false);
|
|
23010
|
-
};
|
|
23103
|
+
`, [CheckoutSummary_QuoteFragment, PaymentForms_QuoteFragment]);
|
|
23011
23104
|
|
|
23012
|
-
const
|
|
23013
|
-
|
|
23014
|
-
|
|
23015
|
-
|
|
23016
|
-
selfServiceBuy
|
|
23105
|
+
const query$6 = t(`
|
|
23106
|
+
query quote($id: ID) {
|
|
23107
|
+
quote(id: $id) {
|
|
23108
|
+
...Signup_QuoteFragment
|
|
23017
23109
|
}
|
|
23018
23110
|
}
|
|
23019
|
-
|
|
23020
|
-
const
|
|
23021
|
-
|
|
23022
|
-
|
|
23023
|
-
return ((((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
23024
|
-
((_b = subscription.plan) === null || _b === void 0 ? void 0 : _b.selfServiceBuy)) ||
|
|
23025
|
-
false);
|
|
23111
|
+
`, [Signup_QuoteFragment]);
|
|
23112
|
+
const getQuote$1 = async ({ id, token, apiHost, }) => {
|
|
23113
|
+
const response = await execute(query$6, { apiHost, token }, { id });
|
|
23114
|
+
return response === null || response === void 0 ? void 0 : response.quote;
|
|
23026
23115
|
};
|
|
23027
23116
|
|
|
23028
|
-
const
|
|
23029
|
-
|
|
23030
|
-
|
|
23031
|
-
|
|
23032
|
-
|
|
23033
|
-
|
|
23034
|
-
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
23035
|
-
else if (period === 3)
|
|
23036
|
-
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
23037
|
-
else if (period === 6)
|
|
23038
|
-
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
23039
|
-
else if (period === 12)
|
|
23040
|
-
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
23041
|
-
else
|
|
23042
|
-
return null;
|
|
23043
|
-
};
|
|
23044
|
-
const billingPeriodConverter = (period) => {
|
|
23045
|
-
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
23046
|
-
return 0;
|
|
23047
|
-
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
23048
|
-
return 1;
|
|
23049
|
-
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
23050
|
-
return 3;
|
|
23051
|
-
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
23052
|
-
return 6;
|
|
23053
|
-
else
|
|
23054
|
-
return 12;
|
|
23117
|
+
const useHasTaxPlugin = ({ apiHost, token }) => {
|
|
23118
|
+
const { data: plugins } = usePlugins({
|
|
23119
|
+
apiHost,
|
|
23120
|
+
token,
|
|
23121
|
+
});
|
|
23122
|
+
return Boolean(plugins === null || plugins === void 0 ? void 0 : plugins.some((plugin) => plugin.type === 'taxation'));
|
|
23055
23123
|
};
|
|
23056
23124
|
|
|
23057
|
-
|
|
23058
|
-
|
|
23059
|
-
|
|
23060
|
-
}
|
|
23061
|
-
|
|
23062
|
-
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
23063
|
-
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
23064
|
-
priceLists {
|
|
23125
|
+
const MUTATION$3 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
23126
|
+
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
23127
|
+
quoteChange {
|
|
23065
23128
|
id
|
|
23066
|
-
|
|
23067
|
-
|
|
23129
|
+
charges {
|
|
23130
|
+
id
|
|
23131
|
+
amount
|
|
23132
|
+
couponId
|
|
23133
|
+
}
|
|
23068
23134
|
}
|
|
23069
23135
|
}
|
|
23070
|
-
|
|
23071
|
-
|
|
23072
|
-
|
|
23073
|
-
const
|
|
23074
|
-
const
|
|
23075
|
-
|
|
23076
|
-
|
|
23077
|
-
|
|
23136
|
+
}`;
|
|
23137
|
+
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
23138
|
+
var _a;
|
|
23139
|
+
const vars = { couponCode, quoteChangeId };
|
|
23140
|
+
const response = await gqlRequest({
|
|
23141
|
+
query: MUTATION$3,
|
|
23142
|
+
token,
|
|
23143
|
+
vars,
|
|
23144
|
+
apiHost,
|
|
23078
23145
|
});
|
|
23079
|
-
|
|
23080
|
-
|
|
23081
|
-
|
|
23082
|
-
|
|
23083
|
-
|
|
23084
|
-
QuoteChangeKind["ADJUSTMENT"] = "ADJUSTMENT";
|
|
23085
|
-
QuoteChangeKind["COUPON"] = "COUPON";
|
|
23086
|
-
QuoteChangeKind["CREDIT"] = "CREDIT";
|
|
23087
|
-
QuoteChangeKind["DISCOUNT"] = "DISCOUNT";
|
|
23088
|
-
QuoteChangeKind["FREE_PERIOD_DISCOUNT"] = "FREE_PERIOD_DISCOUNT";
|
|
23089
|
-
QuoteChangeKind["PRICE_UPDATE"] = "PRICE_UPDATE";
|
|
23090
|
-
QuoteChangeKind["QUANTITY_UPDATE"] = "QUANTITY_UPDATE";
|
|
23091
|
-
QuoteChangeKind["REINSTATE"] = "REINSTATE";
|
|
23092
|
-
QuoteChangeKind["RENEW"] = "RENEW";
|
|
23093
|
-
QuoteChangeKind["SUBSCRIBE"] = "SUBSCRIBE";
|
|
23094
|
-
QuoteChangeKind["UNSUBSCRIBE"] = "UNSUBSCRIBE";
|
|
23095
|
-
QuoteChangeKind["UPDATE"] = "UPDATE";
|
|
23096
|
-
QuoteChangeKind["ACTIVATE"] = "ACTIVATE";
|
|
23097
|
-
})(QuoteChangeKind || (QuoteChangeKind = {}));
|
|
23098
|
-
var QuoteChangeKind$1 = QuoteChangeKind;
|
|
23146
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
23147
|
+
if (errors)
|
|
23148
|
+
throw errors;
|
|
23149
|
+
return response.quote;
|
|
23150
|
+
};
|
|
23099
23151
|
|
|
23100
|
-
|
|
23101
|
-
|
|
23102
|
-
|
|
23103
|
-
|
|
23104
|
-
return unpurchasedFeatureAddons.length > 0;
|
|
23105
|
-
}
|
|
23106
|
-
function findQuoteChangeForFeatureAddon(quote) {
|
|
23107
|
-
return quote === null || quote === void 0 ? void 0 : quote.quoteChanges.find(qc => qc.kind === QuoteChangeKind$1.UPDATE ||
|
|
23108
|
-
qc.kind === QuoteChangeKind$1.SUBSCRIBE ||
|
|
23109
|
-
qc.kind === QuoteChangeKind$1.ACTIVATE);
|
|
23110
|
-
}
|
|
23111
|
-
function featureAddonInQuote(selectedPriceList, priceListCharge, quote) {
|
|
23112
|
-
var _a, _b, _c;
|
|
23113
|
-
const quoteChange = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.find(qc => { var _a; return ((_a = qc === null || qc === void 0 ? void 0 : qc.priceList) === null || _a === void 0 ? void 0 : _a.id) === selectedPriceList.id; });
|
|
23114
|
-
if (!quoteChange)
|
|
23115
|
-
return false;
|
|
23116
|
-
return (_c = (_b = quoteChange.charges) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return ((_a = c.priceListCharge) === null || _a === void 0 ? void 0 : _a.id) === priceListCharge.id; })) !== null && _c !== void 0 ? _c : false;
|
|
23117
|
-
}
|
|
23118
|
-
// ID Cucumber will use to find the feature addon switch
|
|
23119
|
-
function featureAddonSwitchTestId(addonName) {
|
|
23120
|
-
const name = addonName.toLowerCase().replace(/ /g, '-');
|
|
23121
|
-
return `feature-addon-switch-${name}`;
|
|
23122
|
-
}
|
|
23123
|
-
|
|
23124
|
-
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
23125
|
-
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
23126
|
-
const createPlanDescription = (planDescription) => {
|
|
23127
|
-
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
23128
|
-
};
|
|
23129
|
-
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
23130
|
-
if (!priceList) {
|
|
23131
|
-
return;
|
|
23132
|
-
}
|
|
23133
|
-
// If a period option is selected, return the charge that matches the selected period option
|
|
23134
|
-
let activeBillingPLCharge;
|
|
23135
|
-
// Default to first price list charge
|
|
23136
|
-
let lowestPLCharge;
|
|
23137
|
-
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
23138
|
-
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
23139
|
-
activeBillingPLCharge = priceList.charges[0];
|
|
23140
|
-
}
|
|
23141
|
-
for (let j = 0; j < priceList.charges.length; j++) {
|
|
23142
|
-
const charge = priceList.charges[j];
|
|
23143
|
-
if (charge.chargeType === ChargeType$1.USAGE || charge.featureAddon === true)
|
|
23144
|
-
continue;
|
|
23145
|
-
if (activeBillingPLCharge) {
|
|
23146
|
-
// If we already found a charge with the same billing period check if this charge is lower
|
|
23147
|
-
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
23148
|
-
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
23149
|
-
activeBillingPLCharge = charge;
|
|
23150
|
-
}
|
|
23151
|
-
}
|
|
23152
|
-
// If a period option is selected, only return the charge if it matches the selected period option
|
|
23153
|
-
else if (selectedPriceList &&
|
|
23154
|
-
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
23155
|
-
activeBillingPLCharge = charge;
|
|
23156
|
-
}
|
|
23157
|
-
// Otherwise, return the lowest price list charge
|
|
23158
|
-
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
23159
|
-
lowestPLCharge = charge;
|
|
23160
|
-
}
|
|
23161
|
-
}
|
|
23162
|
-
return {
|
|
23163
|
-
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
23164
|
-
};
|
|
23165
|
-
};
|
|
23166
|
-
const showErrorNotification$3 = useErrorNotification();
|
|
23167
|
-
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
23168
|
-
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
23169
|
-
if (!priceListAddonPlans) {
|
|
23170
|
-
showErrorNotification$3('Price list addon plans are undefined');
|
|
23171
|
-
return false;
|
|
23172
|
-
}
|
|
23173
|
-
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
23174
|
-
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
23175
|
-
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription); // TODO: set type properly later
|
|
23176
|
-
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription); // TODO: set type properly later
|
|
23177
|
-
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
23178
|
-
// When should priceList be disabled?
|
|
23179
|
-
// if upgradingSubscription?.priceList.id === priceList.id
|
|
23180
|
-
// AND the upgradingSubscription is not in trial
|
|
23181
|
-
// AND cannot purchase feature addons
|
|
23182
|
-
// AND cannot purchase add-on plans
|
|
23183
|
-
// AND selfServiceBuy is false
|
|
23184
|
-
// if upgradingSubscription?.priceList.id != priceList.id
|
|
23185
|
-
// AND upgradingSubscription is expired trial
|
|
23186
|
-
// AND priceList is not deprecated
|
|
23187
|
-
if (isUpgradingSubscriptionPriceList) {
|
|
23188
|
-
return (!existingSubscriptionInTrial &&
|
|
23189
|
-
!existingSubscriptionInTrialExpired &&
|
|
23190
|
-
!canPurchaseFeatureAddons &&
|
|
23191
|
-
!canPurchasePlanAddons);
|
|
23192
|
-
}
|
|
23193
|
-
else if (priceList === null || priceList === void 0 ? void 0 : priceList.deprecated) {
|
|
23194
|
-
return true;
|
|
23195
|
-
}
|
|
23196
|
-
else {
|
|
23197
|
-
return false;
|
|
23198
|
-
}
|
|
23199
|
-
};
|
|
23200
|
-
|
|
23201
|
-
const CheckoutButton = ({ disabled, onClickCheckout, loading, tooltipText, }) => {
|
|
23202
|
-
const isMobile = useIsMobile();
|
|
23203
|
-
const TooltipWrapper = ({ children }) => {
|
|
23204
|
-
if (tooltipText) {
|
|
23205
|
-
return jsx(Tooltip, { title: tooltipText, children: children });
|
|
23206
|
-
}
|
|
23207
|
-
return jsx("div", { children: children });
|
|
23208
|
-
};
|
|
23209
|
-
return (jsx(TooltipWrapper, { children: jsx(Button, { className: isMobile ? 'w-full' : '', disabled: disabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
23210
|
-
};
|
|
23211
|
-
|
|
23212
|
-
const CheckoutPrice_QuoteFragment = t(`
|
|
23213
|
-
fragment CheckoutPrice_QuoteFragment on Quote {
|
|
23214
|
-
periodAmount
|
|
23215
|
-
amountDue
|
|
23216
|
-
}
|
|
23217
|
-
`);
|
|
23218
|
-
const CheckoutPrice = ({ isUsage, quote: maskedQuote, selectedPriceList, }) => {
|
|
23219
|
-
var _a;
|
|
23220
|
-
// Read fragments
|
|
23221
|
-
const quote = readFragment(CheckoutPrice_QuoteFragment, maskedQuote);
|
|
23222
|
-
// Hooks
|
|
23223
|
-
const isMobile = useIsMobile();
|
|
23224
|
-
// amountDue might not be available, so we use periodAmount as a fallback
|
|
23225
|
-
const displayAmount = (_a = quote === null || quote === void 0 ? void 0 : quote.amountDue) !== null && _a !== void 0 ? _a : quote === null || quote === void 0 ? void 0 : quote.periodAmount;
|
|
23226
|
-
if (!isUsage && (!selectedPriceList || displayAmount === undefined))
|
|
23227
|
-
return null;
|
|
23228
|
-
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
23229
|
-
const periodLabel = convertedPeriodMonths ? PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
23230
|
-
return (jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
23231
|
-
? 'Usage based pricing'
|
|
23232
|
-
: selectedPriceList && displayAmount !== undefined
|
|
23233
|
-
? `${formatCurrency(displayAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, undefined)} / ${periodLabel}`
|
|
23234
|
-
: '' }));
|
|
23235
|
-
};
|
|
23236
|
-
|
|
23237
|
-
const { Text: Text$q } = Typography;
|
|
23238
|
-
const CheckoutBarSummarySection_QuoteFragment = t(`
|
|
23239
|
-
fragment CheckoutBarSummarySection_QuoteFragment on Quote {
|
|
23240
|
-
quoteChanges {
|
|
23241
|
-
charges {
|
|
23242
|
-
id
|
|
23243
|
-
}
|
|
23244
|
-
}
|
|
23245
|
-
...CheckoutPrice_QuoteFragment
|
|
23246
|
-
}
|
|
23247
|
-
`, [CheckoutPrice_QuoteFragment]);
|
|
23248
|
-
const CheckoutBarSummarySection = ({ selectedPriceList, onClickCheckout, }) => {
|
|
23249
|
-
var _a, _b;
|
|
23250
|
-
// Context
|
|
23251
|
-
const { quote: maskedQuote, isQuotePending, isUpdatingQuote } = useContext(QuoteContext);
|
|
23252
|
-
const quote = readFragment(CheckoutBarSummarySection_QuoteFragment, maskedQuote);
|
|
23253
|
-
const { isInPreviewMode } = useSubscriptionProps();
|
|
23254
|
-
// Hooks
|
|
23255
|
-
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
23256
|
-
const isMobile = useIsMobile();
|
|
23257
|
-
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
23258
|
-
const quoteHasCharges = Boolean((_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.some(qc => qc.charges.length > 0));
|
|
23259
|
-
const checkoutButtonDisabled = Boolean(!selectedPriceList || !quoteHasCharges || !hasPaymentPlugins || isInPreviewMode);
|
|
23260
|
-
const activeCharge = (_b = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _b === void 0 ? void 0 : _b.activeCharge;
|
|
23261
|
-
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === ChargeType$1.USAGE;
|
|
23262
|
-
return (jsxs(Text$q, { className: `bunny-flex bunny-items-center bunny-gap-4 ${isMobile ? 'bunny-flex-col' : ''}`, children: [quote && (jsxs("div", { className: `bunny-flex ${isMobile ? 'items-center justify-between w-full' : 'flex-col'}`, children: [jsx("div", { className: "bunny-text-slate-500 bunny-font-medium bunny-text-right", style: { fontSize: '11px' }, children: "TOTAL" }), jsx(CheckoutPrice, { isUsage: isUsage, quote: quote, selectedPriceList: selectedPriceList })] })), jsx(CheckoutButton, { disabled: checkoutButtonDisabled, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
23263
|
-
? 'Checkout is disabled in preview mode'
|
|
23264
|
-
: !hasPaymentPlugins
|
|
23265
|
-
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
23266
|
-
: undefined })] }));
|
|
23267
|
-
};
|
|
23268
|
-
|
|
23269
|
-
const accountQuery = (id) => `
|
|
23270
|
-
query account {
|
|
23271
|
-
account(id: ${id}) {
|
|
23272
|
-
billingCountry
|
|
23273
|
-
billingState
|
|
23274
|
-
billingStreet
|
|
23275
|
-
billingCity
|
|
23276
|
-
billingZip
|
|
23277
|
-
}
|
|
23278
|
-
}`;
|
|
23279
|
-
const getAccount$1 = async ({ id, apiHost, token, }) => {
|
|
23280
|
-
const response = await gqlRequest({
|
|
23281
|
-
query: accountQuery(id),
|
|
23282
|
-
token,
|
|
23283
|
-
apiHost,
|
|
23284
|
-
});
|
|
23285
|
-
return response === null || response === void 0 ? void 0 : response.account;
|
|
23286
|
-
};
|
|
23287
|
-
|
|
23288
|
-
const MUTATION$5 = `{
|
|
23289
|
-
currentUser {
|
|
23290
|
-
taxationRequiredAccountFields
|
|
23291
|
-
}
|
|
23292
|
-
}`;
|
|
23293
|
-
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
23294
|
-
var _a, _b;
|
|
23295
|
-
const response = await gqlRequest({
|
|
23296
|
-
query: MUTATION$5,
|
|
23297
|
-
token,
|
|
23298
|
-
apiHost: apiHost,
|
|
23299
|
-
});
|
|
23300
|
-
return ((_b = (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.taxationRequiredAccountFields) === null || _b === void 0 ? void 0 : _b.length) > 0
|
|
23301
|
-
? response.currentUser.taxationRequiredAccountFields
|
|
23302
|
-
: null;
|
|
23303
|
-
};
|
|
23304
|
-
|
|
23305
|
-
const useHasTaxPlugin = ({ apiHost, token }) => {
|
|
23306
|
-
const { data: plugins } = usePlugins({
|
|
23307
|
-
apiHost,
|
|
23308
|
-
token,
|
|
23309
|
-
});
|
|
23310
|
-
return Boolean(plugins === null || plugins === void 0 ? void 0 : plugins.some((plugin) => plugin.type === 'taxation'));
|
|
23311
|
-
};
|
|
23312
|
-
|
|
23313
|
-
const BunnyFooterIcon = ({ color }) => {
|
|
23314
|
-
return (jsxs("svg", { width: "45", height: "15", viewBox: "0 0 39 13", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxs("g", { clipPath: "url(#clip0_6_851)", children: [jsx("path", { className: "bunny-icon-path", d: "M14.5898 7.19708C14.5898 9.35053 13.0926 10.325 11.2495 10.325C9.39955 10.325 7.90234 9.35001 7.90234 7.18967V3.26221H10.1125V7.00052C10.1125 7.87719 10.5855 8.27725 11.2495 8.27725C11.9061 8.27725 12.3865 7.87719 12.3865 7.00052V3.26221H14.5898V7.19708Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M31.8943 12.9625H29.4793L31.8523 8.62816L28.9355 3.26221H31.4708L33.0457 6.35524L34.5924 3.26221H37.0075L31.8943 12.9625Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M15.1602 5.96827C15.1602 3.8148 16.6574 2.84033 18.5005 2.84033C20.3504 2.84033 21.8476 3.81533 21.8476 5.97568V10.1473H19.6374V6.16483C19.6374 5.28815 19.1645 4.8881 18.5005 4.8881C17.8439 4.8881 17.3634 5.28815 17.3634 6.16483V10.1473H15.1602V5.96827Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M22.4316 5.96827C22.4316 3.8148 23.9289 2.84033 25.7719 2.84033C27.6219 2.84033 29.1191 3.81533 29.1191 5.97568V10.1473H26.9089V6.16483C26.9089 5.28815 26.4359 4.8881 25.7719 4.8881C25.1154 4.8881 24.6349 5.28815 24.6349 6.16483V10.1473H22.4316V5.96827Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M7.40511 6.68957C7.40511 8.7236 6.02815 10.3227 4.17816 10.3227C3.23907 10.3227 2.61071 9.94378 2.19358 9.40371V10.1404H0.0605469V0.0405273H2.26381V3.91939C2.68041 3.42158 3.28802 3.07069 4.17763 3.07069C6.02759 3.07069 7.40511 4.66981 7.40511 6.68957ZM2.17229 6.69642C2.17229 7.60802 2.77937 8.2744 3.64823 8.2744C4.53783 8.2744 5.13107 7.59372 5.13107 6.69642C5.13107 5.79912 4.53783 5.11844 3.64823 5.11844C2.77937 5.11844 2.17229 5.78482 2.17229 6.69642Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M38.966 8.94801C38.966 9.76181 38.2668 10.4631 37.4618 10.4631C36.6499 10.4631 35.9434 9.76181 35.9434 8.94801C35.9434 8.14846 36.6494 7.46094 37.4618 7.46094C38.2668 7.46094 38.966 8.14846 38.966 8.94801Z", fill: color })] }), jsx("defs", { children: jsx("clipPath", { id: "clip0_6_851", children: jsx("rect", { width: "39", height: "13", fill: "white" }) }) })] }));
|
|
23315
|
-
};
|
|
23316
|
-
|
|
23317
|
-
const { Text: Text$p } = Typography;
|
|
23318
|
-
const Footer = ({ className }) => {
|
|
23319
|
-
const token = useToken();
|
|
23320
|
-
const { currentUser } = useCurrentUserData(token);
|
|
23321
|
-
const { privacyUrl, termsUrl } = currentUser;
|
|
23322
|
-
const isMobile = useIsMobile();
|
|
23323
|
-
return (jsxs("div", { className: `bunny-flex bunny-items-center bunny-justify-between bunny-shrink-0 ${isMobile ? 'bunny-flex-col bunny-gap-2' : ''} ${className}`, children: [(termsUrl || privacyUrl) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsx(BunnyMarketingLink, {})] }));
|
|
23324
|
-
};
|
|
23325
|
-
const BunnyMarketingLink = () => {
|
|
23326
|
-
const [isHovered, setIsHovered] = useState(false);
|
|
23327
|
-
const isMobile = useIsMobile();
|
|
23328
|
-
return (jsx("div", { className: `bunny-flex bunny-items-end bunny-justify-end ${isMobile ? '' : 'grow'}`, children: jsx(StyledBunnyLink, { className: "bunny-flex bunny-items-end bunny-justify-end bunny-text-slate-400", href: "https://bunny.com/", rel: "noopener noreferrer", target: "_blank", children: jsxs("div", { className: "bunny-flex bunny-items-center", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsx(Text$p, { className: "bunny-text-slate-400", children: "Powered by\u00A0" }), jsx("div", { style: { paddingTop: '5px' }, children: jsx(BunnyFooterIcon, { color: isHovered ? PRIMARY_COLOR : SLATE_400 }) })] }) }) }));
|
|
23329
|
-
};
|
|
23330
|
-
const StyedLink = styled.a `
|
|
23331
|
-
color: ${SLATE_400};
|
|
23332
|
-
transition: color 0.3s;
|
|
23333
|
-
&:hover {
|
|
23334
|
-
color: ${SLATE_500};
|
|
23335
|
-
}
|
|
23336
|
-
text-decoration: none;
|
|
23337
|
-
`;
|
|
23338
|
-
const StyledBunnyLink = styled(StyedLink) `
|
|
23339
|
-
&:hover {
|
|
23340
|
-
color: ${PRIMARY_COLOR} !important;
|
|
23341
|
-
}
|
|
23342
|
-
`;
|
|
23343
|
-
|
|
23344
|
-
const MUTATION$4 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
23345
|
-
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
23346
|
-
quoteChange {
|
|
23347
|
-
id
|
|
23348
|
-
charges {
|
|
23349
|
-
id
|
|
23350
|
-
amount
|
|
23351
|
-
couponId
|
|
23352
|
-
}
|
|
23353
|
-
}
|
|
23354
|
-
}
|
|
23355
|
-
}`;
|
|
23356
|
-
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
23357
|
-
var _a;
|
|
23358
|
-
const vars = { couponCode, quoteChangeId };
|
|
23359
|
-
const response = await gqlRequest({
|
|
23360
|
-
query: MUTATION$4,
|
|
23361
|
-
token,
|
|
23362
|
-
vars,
|
|
23363
|
-
apiHost,
|
|
23364
|
-
});
|
|
23365
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
23366
|
-
if (errors)
|
|
23367
|
-
throw errors;
|
|
23368
|
-
return response.quote;
|
|
23369
|
-
};
|
|
23370
|
-
|
|
23371
|
-
const MUTATION$3 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
|
|
23372
|
-
quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
|
|
23373
|
-
errors
|
|
23374
|
-
}
|
|
23152
|
+
const MUTATION$2 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
|
|
23153
|
+
quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
|
|
23154
|
+
errors
|
|
23155
|
+
}
|
|
23375
23156
|
}
|
|
23376
23157
|
`;
|
|
23377
23158
|
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
23378
23159
|
var _a;
|
|
23379
23160
|
const vars = { couponCode, quoteChangeId };
|
|
23380
23161
|
const response = await gqlRequest({
|
|
23381
|
-
query: MUTATION$
|
|
23162
|
+
query: MUTATION$2,
|
|
23382
23163
|
token,
|
|
23383
23164
|
vars,
|
|
23384
23165
|
apiHost,
|
|
@@ -23406,7 +23187,7 @@ const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
|
23406
23187
|
return response === null || response === void 0 ? void 0 : response.coupons;
|
|
23407
23188
|
};
|
|
23408
23189
|
|
|
23409
|
-
const showErrorNotification$
|
|
23190
|
+
const showErrorNotification$3 = useErrorNotification();
|
|
23410
23191
|
const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCouponRemoved, }) => {
|
|
23411
23192
|
const { data: coupons } = useQuery({
|
|
23412
23193
|
queryKey: ['coupons', token],
|
|
@@ -23432,7 +23213,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
23432
23213
|
},
|
|
23433
23214
|
onError: (error) => {
|
|
23434
23215
|
var _a, _b;
|
|
23435
|
-
showErrorNotification$
|
|
23216
|
+
showErrorNotification$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error adding coupon');
|
|
23436
23217
|
},
|
|
23437
23218
|
});
|
|
23438
23219
|
const { mutate: removeCoupon, isPending: isRemovingCoupon } = useMutation({
|
|
@@ -23452,7 +23233,7 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
23452
23233
|
},
|
|
23453
23234
|
onError: (error) => {
|
|
23454
23235
|
var _a, _b;
|
|
23455
|
-
showErrorNotification$
|
|
23236
|
+
showErrorNotification$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error removing coupon');
|
|
23456
23237
|
},
|
|
23457
23238
|
});
|
|
23458
23239
|
return {
|
|
@@ -23464,1090 +23245,384 @@ const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCoup
|
|
|
23464
23245
|
};
|
|
23465
23246
|
};
|
|
23466
23247
|
|
|
23467
|
-
const
|
|
23468
|
-
|
|
23469
|
-
|
|
23470
|
-
|
|
23471
|
-
|
|
23472
|
-
|
|
23473
|
-
const
|
|
23474
|
-
|
|
23475
|
-
|
|
23476
|
-
|
|
23477
|
-
|
|
23478
|
-
|
|
23248
|
+
const BunnyFooterIcon = ({ color }) => {
|
|
23249
|
+
return (jsxs("svg", { width: "45", height: "15", viewBox: "0 0 39 13", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxs("g", { clipPath: "url(#clip0_6_851)", children: [jsx("path", { className: "bunny-icon-path", d: "M14.5898 7.19708C14.5898 9.35053 13.0926 10.325 11.2495 10.325C9.39955 10.325 7.90234 9.35001 7.90234 7.18967V3.26221H10.1125V7.00052C10.1125 7.87719 10.5855 8.27725 11.2495 8.27725C11.9061 8.27725 12.3865 7.87719 12.3865 7.00052V3.26221H14.5898V7.19708Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M31.8943 12.9625H29.4793L31.8523 8.62816L28.9355 3.26221H31.4708L33.0457 6.35524L34.5924 3.26221H37.0075L31.8943 12.9625Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M15.1602 5.96827C15.1602 3.8148 16.6574 2.84033 18.5005 2.84033C20.3504 2.84033 21.8476 3.81533 21.8476 5.97568V10.1473H19.6374V6.16483C19.6374 5.28815 19.1645 4.8881 18.5005 4.8881C17.8439 4.8881 17.3634 5.28815 17.3634 6.16483V10.1473H15.1602V5.96827Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M22.4316 5.96827C22.4316 3.8148 23.9289 2.84033 25.7719 2.84033C27.6219 2.84033 29.1191 3.81533 29.1191 5.97568V10.1473H26.9089V6.16483C26.9089 5.28815 26.4359 4.8881 25.7719 4.8881C25.1154 4.8881 24.6349 5.28815 24.6349 6.16483V10.1473H22.4316V5.96827Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M7.40511 6.68957C7.40511 8.7236 6.02815 10.3227 4.17816 10.3227C3.23907 10.3227 2.61071 9.94378 2.19358 9.40371V10.1404H0.0605469V0.0405273H2.26381V3.91939C2.68041 3.42158 3.28802 3.07069 4.17763 3.07069C6.02759 3.07069 7.40511 4.66981 7.40511 6.68957ZM2.17229 6.69642C2.17229 7.60802 2.77937 8.2744 3.64823 8.2744C4.53783 8.2744 5.13107 7.59372 5.13107 6.69642C5.13107 5.79912 4.53783 5.11844 3.64823 5.11844C2.77937 5.11844 2.17229 5.78482 2.17229 6.69642Z", fill: color }), jsx("path", { className: "bunny-icon-path", d: "M38.966 8.94801C38.966 9.76181 38.2668 10.4631 37.4618 10.4631C36.6499 10.4631 35.9434 9.76181 35.9434 8.94801C35.9434 8.14846 36.6494 7.46094 37.4618 7.46094C38.2668 7.46094 38.966 8.14846 38.966 8.94801Z", fill: color })] }), jsx("defs", { children: jsx("clipPath", { id: "clip0_6_851", children: jsx("rect", { width: "39", height: "13", fill: "white" }) }) })] }));
|
|
23250
|
+
};
|
|
23251
|
+
|
|
23252
|
+
const { Text: Text$p } = Typography;
|
|
23253
|
+
const Footer = ({ className }) => {
|
|
23254
|
+
const token = useToken();
|
|
23255
|
+
const { currentUser } = useCurrentUserData(token);
|
|
23256
|
+
const { privacyUrl, termsUrl } = currentUser;
|
|
23257
|
+
const isMobile = useIsMobile();
|
|
23258
|
+
return (jsxs("div", { className: `bunny-flex bunny-items-center bunny-justify-between bunny-shrink-0 ${isMobile ? 'bunny-flex-col bunny-gap-2' : ''} ${className}`, children: [(termsUrl || privacyUrl) && (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsx(BunnyMarketingLink, {})] }));
|
|
23259
|
+
};
|
|
23260
|
+
const BunnyMarketingLink = () => {
|
|
23261
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
23262
|
+
const isMobile = useIsMobile();
|
|
23263
|
+
return (jsx("div", { className: `bunny-flex bunny-items-end bunny-justify-end ${isMobile ? '' : 'grow'}`, children: jsx(StyledBunnyLink, { className: "bunny-flex bunny-items-end bunny-justify-end bunny-text-slate-400", href: "https://bunny.com/", rel: "noopener noreferrer", target: "_blank", children: jsxs("div", { className: "bunny-flex bunny-items-center", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsx(Text$p, { className: "bunny-text-slate-400", children: "Powered by\u00A0" }), jsx("div", { style: { paddingTop: '5px' }, children: jsx(BunnyFooterIcon, { color: isHovered ? PRIMARY_COLOR : SLATE_400 }) })] }) }) }));
|
|
23264
|
+
};
|
|
23265
|
+
const StyedLink = styled.a `
|
|
23266
|
+
color: ${SLATE_400};
|
|
23267
|
+
transition: color 0.3s;
|
|
23268
|
+
&:hover {
|
|
23269
|
+
color: ${SLATE_500};
|
|
23270
|
+
}
|
|
23271
|
+
text-decoration: none;
|
|
23272
|
+
`;
|
|
23273
|
+
const StyledBunnyLink = styled(StyedLink) `
|
|
23274
|
+
&:hover {
|
|
23275
|
+
color: ${PRIMARY_COLOR} !important;
|
|
23276
|
+
}
|
|
23277
|
+
`;
|
|
23278
|
+
|
|
23279
|
+
const SelfServiceBuyWarning_PriceListFragment = t(`
|
|
23280
|
+
fragment SelfServiceBuyWarning_PriceListFragment on PriceList {
|
|
23281
|
+
plan {
|
|
23282
|
+
selfServiceBuy
|
|
23479
23283
|
}
|
|
23480
23284
|
}
|
|
23481
|
-
|
|
23482
|
-
function
|
|
23483
|
-
|
|
23484
|
-
const
|
|
23485
|
-
|
|
23486
|
-
|
|
23487
|
-
((_b = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) ===
|
|
23488
|
-
t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
23489
|
-
function upgradingFromFree() {
|
|
23285
|
+
`);
|
|
23286
|
+
function SelfServiceBuyWarning({ priceList: maskedPriceList, onShowSelfServiceBuyWarning, }) {
|
|
23287
|
+
const priceList = readFragment(SelfServiceBuyWarning_PriceListFragment, maskedPriceList);
|
|
23288
|
+
const hasShownRef = useRef(false);
|
|
23289
|
+
// Only show the warning when component is first mounted
|
|
23290
|
+
useEffect(() => {
|
|
23490
23291
|
var _a;
|
|
23491
|
-
|
|
23492
|
-
|
|
23493
|
-
|
|
23494
|
-
|
|
23495
|
-
|
|
23496
|
-
|
|
23497
|
-
|
|
23498
|
-
|
|
23499
|
-
}
|
|
23500
|
-
return false;
|
|
23292
|
+
if (!priceList || hasShownRef.current)
|
|
23293
|
+
return;
|
|
23294
|
+
if (((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.selfServiceBuy) === false) {
|
|
23295
|
+
hasShownRef.current = true;
|
|
23296
|
+
onShowSelfServiceBuyWarning();
|
|
23297
|
+
}
|
|
23298
|
+
}, [priceList, onShowSelfServiceBuyWarning]);
|
|
23299
|
+
return null;
|
|
23501
23300
|
}
|
|
23502
23301
|
|
|
23503
|
-
|
|
23504
|
-
|
|
23505
|
-
|
|
23302
|
+
const TAG_COLORS = {
|
|
23303
|
+
ACTIVE: 'green',
|
|
23304
|
+
TRIAL: 'blue',
|
|
23305
|
+
CANCELED: 'red',
|
|
23306
|
+
EXPIRED: 'gray',
|
|
23307
|
+
TRIAL_EXPIRED: 'red',
|
|
23308
|
+
PENDING: 'yellow',
|
|
23309
|
+
};
|
|
23310
|
+
|
|
23311
|
+
const { Text: Text$o } = Typography;
|
|
23312
|
+
const PriceListDisplay_PriceListFragment = t(`
|
|
23313
|
+
fragment PriceListDisplay_PriceListFragment on PriceList {
|
|
23314
|
+
product {
|
|
23315
|
+
name
|
|
23316
|
+
}
|
|
23317
|
+
name
|
|
23318
|
+
basePrice
|
|
23319
|
+
currencyId
|
|
23320
|
+
trialAllowed
|
|
23321
|
+
trialLengthDays
|
|
23506
23322
|
}
|
|
23507
|
-
|
|
23323
|
+
`);
|
|
23324
|
+
function PriceListDisplay({ priceList: maskedPriceList }) {
|
|
23325
|
+
var _a, _b;
|
|
23326
|
+
const priceList = readFragment(PriceListDisplay_PriceListFragment, maskedPriceList);
|
|
23327
|
+
if (!priceList)
|
|
23328
|
+
return null;
|
|
23329
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-4", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-0", children: [jsxs(Text$o, { className: "bunny-text-slate-500 bunny-font-bold bunny-text-lg", children: [(_a = priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList.name] }), jsxs(Text$o, { className: "bunny-font-bold bunny-text-xl", children: [formatCurrency(priceList.basePrice, priceList.currencyId), " / month"] })] }), priceList.trialAllowed ? (jsx("div", { className: "bunny-flex", children: jsx(CustomizedTag, { color: TAG_COLORS["TRIAL"], children: `${(_b = priceList.trialLengthDays) !== null && _b !== void 0 ? _b : 'N/A'} day trial` }) })) : null] }));
|
|
23508
23330
|
}
|
|
23509
23331
|
|
|
23510
|
-
const
|
|
23511
|
-
fragment
|
|
23512
|
-
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
23516
|
-
|
|
23517
|
-
id
|
|
23518
|
-
payableId
|
|
23519
|
-
periodAmount
|
|
23520
|
-
subtotal
|
|
23521
|
-
taxAmount
|
|
23522
|
-
startDate
|
|
23523
|
-
formattedQuote {
|
|
23524
|
-
html
|
|
23332
|
+
const Signup_PriceListFragment = t(`
|
|
23333
|
+
fragment Signup_PriceListFragment on PriceList {
|
|
23334
|
+
...CheckoutSummary_PriceListFragment
|
|
23335
|
+
...PriceListDisplay_PriceListFragment
|
|
23336
|
+
...SelfServiceBuyWarning_PriceListFragment
|
|
23337
|
+
plan {
|
|
23338
|
+
selfServiceBuy
|
|
23525
23339
|
}
|
|
23526
|
-
|
|
23340
|
+
trialAllowed
|
|
23341
|
+
}
|
|
23342
|
+
`, [
|
|
23343
|
+
CheckoutSummary_PriceListFragment,
|
|
23344
|
+
PriceListDisplay_PriceListFragment,
|
|
23345
|
+
SelfServiceBuyWarning_PriceListFragment,
|
|
23346
|
+
]);
|
|
23347
|
+
|
|
23348
|
+
const graphql = initGraphQLTada();
|
|
23349
|
+
|
|
23350
|
+
const mutation$f = graphql(`
|
|
23351
|
+
mutation AccountSignup (
|
|
23352
|
+
$pluginId: String!,
|
|
23353
|
+
$paymentMethodId: String,
|
|
23354
|
+
$priceListCode: String!,
|
|
23355
|
+
$accountId: ID!,
|
|
23356
|
+
$quoteId: ID!,
|
|
23357
|
+
) {
|
|
23358
|
+
accountSignup(
|
|
23359
|
+
pluginId: $pluginId,
|
|
23360
|
+
paymentMethodId: $paymentMethodId,
|
|
23361
|
+
priceListCode: $priceListCode,
|
|
23362
|
+
accountId: $accountId,
|
|
23363
|
+
quoteId: $quoteId,
|
|
23364
|
+
) {
|
|
23365
|
+
errors
|
|
23366
|
+
quote {
|
|
23367
|
+
accountId
|
|
23527
23368
|
amount
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23369
|
+
amountDue
|
|
23370
|
+
applicationDate
|
|
23371
|
+
applied
|
|
23372
|
+
backdatedPeriods
|
|
23373
|
+
backdatedQuote
|
|
23374
|
+
billingDay
|
|
23375
|
+
contactId
|
|
23376
|
+
createdAt
|
|
23377
|
+
credits
|
|
23532
23378
|
currencyId
|
|
23379
|
+
dealId
|
|
23380
|
+
discount
|
|
23381
|
+
discountValue
|
|
23382
|
+
endDate
|
|
23383
|
+
evergreen
|
|
23384
|
+
expiresAt
|
|
23533
23385
|
id
|
|
23386
|
+
invoiceImmediately
|
|
23387
|
+
invoiceImmediatelyAvailable
|
|
23388
|
+
invoiceUntil
|
|
23389
|
+
isPendingApprovalRequest
|
|
23534
23390
|
kind
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
|
|
23553
|
-
|
|
23554
|
-
}
|
|
23555
|
-
coupon {
|
|
23556
|
-
couponCode
|
|
23557
|
-
}
|
|
23558
|
-
quantity
|
|
23559
|
-
kind
|
|
23560
|
-
}
|
|
23561
|
-
priceList {
|
|
23562
|
-
id
|
|
23563
|
-
plan {
|
|
23564
|
-
name
|
|
23565
|
-
}
|
|
23566
|
-
product {
|
|
23567
|
-
name
|
|
23568
|
-
}
|
|
23569
|
-
}
|
|
23391
|
+
message
|
|
23392
|
+
name
|
|
23393
|
+
netPaymentDays
|
|
23394
|
+
notes
|
|
23395
|
+
number
|
|
23396
|
+
ownerId
|
|
23397
|
+
payableId
|
|
23398
|
+
periodAmount
|
|
23399
|
+
poNumber
|
|
23400
|
+
requiresApproval
|
|
23401
|
+
smallUnitAmountDue
|
|
23402
|
+
splitInvoice
|
|
23403
|
+
startDate
|
|
23404
|
+
state
|
|
23405
|
+
subtotal
|
|
23406
|
+
taxAmount
|
|
23407
|
+
taxCode
|
|
23408
|
+
updatedAt
|
|
23409
|
+
uuid
|
|
23570
23410
|
}
|
|
23571
23411
|
}
|
|
23572
|
-
`);
|
|
23573
|
-
|
|
23574
|
-
const [UpgradingSubscriptionProvider, useUpgradingSubscription] = createValueContext();
|
|
23575
|
-
|
|
23576
|
-
const MUTATION$2 = `
|
|
23577
|
-
mutation accountUpdate(
|
|
23578
|
-
$id: ID!,
|
|
23579
|
-
$attributes: AccountAttributes!) {
|
|
23580
|
-
accountUpdate(
|
|
23581
|
-
id: $id,
|
|
23582
|
-
attributes: $attributes
|
|
23583
|
-
) {
|
|
23584
|
-
account {
|
|
23585
|
-
id
|
|
23586
|
-
billingCountry
|
|
23587
|
-
billingState
|
|
23588
|
-
billingStreet
|
|
23589
|
-
billingCity
|
|
23590
|
-
billingZip
|
|
23591
|
-
name
|
|
23592
|
-
}
|
|
23593
|
-
errors
|
|
23594
|
-
}
|
|
23595
|
-
}
|
|
23596
|
-
`;
|
|
23597
|
-
const accountUpdate$1 = async ({ accountId, attributes, token, apiHost, }) => {
|
|
23412
|
+
}`);
|
|
23413
|
+
const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken, paymentMethodId, pluginId, priceListCode, }) => {
|
|
23598
23414
|
var _a;
|
|
23599
|
-
const
|
|
23600
|
-
|
|
23601
|
-
|
|
23602
|
-
|
|
23603
|
-
|
|
23604
|
-
|
|
23415
|
+
const response = await execute(mutation$f, { apiHost, token }, {
|
|
23416
|
+
accountId,
|
|
23417
|
+
quoteId,
|
|
23418
|
+
paymentToken,
|
|
23419
|
+
pluginId,
|
|
23420
|
+
paymentMethodId,
|
|
23421
|
+
priceListCode,
|
|
23605
23422
|
});
|
|
23606
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.
|
|
23423
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.accountSignup) === null || _a === void 0 ? void 0 : _a.errors;
|
|
23607
23424
|
if (errors)
|
|
23608
23425
|
throw errors;
|
|
23609
|
-
return response.
|
|
23426
|
+
return response === null || response === void 0 ? void 0 : response.accountSignup;
|
|
23610
23427
|
};
|
|
23611
23428
|
|
|
23612
|
-
const
|
|
23613
|
-
|
|
23614
|
-
|
|
23615
|
-
|
|
23616
|
-
|
|
23617
|
-
|
|
23618
|
-
|
|
23619
|
-
|
|
23620
|
-
|
|
23621
|
-
|
|
23622
|
-
|
|
23623
|
-
|
|
23624
|
-
|
|
23625
|
-
|
|
23626
|
-
|
|
23627
|
-
|
|
23628
|
-
|
|
23629
|
-
|
|
23630
|
-
|
|
23631
|
-
|
|
23632
|
-
|
|
23633
|
-
|
|
23634
|
-
|
|
23429
|
+
const mutation$e = t(`
|
|
23430
|
+
mutation QuoteAccountSignup (
|
|
23431
|
+
$accountName: String!,
|
|
23432
|
+
$billingContact: ContactAttributes!,
|
|
23433
|
+
$priceListCode: String!,
|
|
23434
|
+
$billingDetails: BillingDetailsAttributes
|
|
23435
|
+
$trial: Boolean,
|
|
23436
|
+
) {
|
|
23437
|
+
quoteAccountSignup(
|
|
23438
|
+
priceListCode: $priceListCode,
|
|
23439
|
+
accountName: $accountName,
|
|
23440
|
+
billingContact: $billingContact,
|
|
23441
|
+
billingDetails: $billingDetails,
|
|
23442
|
+
trial: $trial,
|
|
23443
|
+
) {
|
|
23444
|
+
account {
|
|
23445
|
+
id
|
|
23446
|
+
}
|
|
23447
|
+
quote {
|
|
23448
|
+
...Signup_QuoteFragment
|
|
23449
|
+
id
|
|
23450
|
+
}
|
|
23451
|
+
tenant {
|
|
23452
|
+
code
|
|
23453
|
+
}
|
|
23454
|
+
portalSessionToken
|
|
23455
|
+
errors
|
|
23456
|
+
}
|
|
23457
|
+
}`, [Signup_QuoteFragment]);
|
|
23458
|
+
const quoteAccountSignup = async ({ token, apiHost, priceListCode, accountName, billingContact, billingDetails, trial, }) => {
|
|
23459
|
+
var _a;
|
|
23460
|
+
const response = await execute(mutation$e, { apiHost, token }, {
|
|
23461
|
+
priceListCode,
|
|
23462
|
+
accountName,
|
|
23463
|
+
billingContact,
|
|
23464
|
+
billingDetails,
|
|
23465
|
+
trial,
|
|
23635
23466
|
});
|
|
23636
|
-
|
|
23637
|
-
|
|
23638
|
-
|
|
23639
|
-
|
|
23640
|
-
} }) }), jsx(Form.Item, { label: "Billing zip", name: "billingZip", children: jsx(Input, { placeholder: "Zip" }) }), jsx(Form.Item, { children: jsx(Button, { className: "bunny-w-full", disabled: isUpdatingAccount, htmlType: "submit", type: "primary", children: "Submit" }) })] }));
|
|
23641
|
-
};
|
|
23642
|
-
const FormBillingState = () => {
|
|
23643
|
-
const billingCountry = Form.useWatch('billingCountry');
|
|
23644
|
-
const billingStateRequired = COUNTRIES_REQUIRING_STATE.includes(billingCountry);
|
|
23645
|
-
return (jsx(Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsx(Input, { placeholder: "State" }) }));
|
|
23467
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAccountSignup) === null || _a === void 0 ? void 0 : _a.errors;
|
|
23468
|
+
if (errors)
|
|
23469
|
+
throw errors;
|
|
23470
|
+
return response === null || response === void 0 ? void 0 : response.quoteAccountSignup;
|
|
23646
23471
|
};
|
|
23647
23472
|
|
|
23648
|
-
const
|
|
23649
|
-
|
|
23650
|
-
|
|
23651
|
-
|
|
23652
|
-
|
|
23653
|
-
|
|
23654
|
-
const { Text: Text$o } = Typography;
|
|
23655
|
-
// HACK: I have imported QuoteFields_QuoteFragment here as a hack to ensure I have all of the quote data needed for
|
|
23656
|
-
// the eventual children of this component.
|
|
23657
|
-
// Solution: Eventually all children of this component should be using query fragments to avoid this
|
|
23658
|
-
const QuoteCheckout_QuoteFragment = t(`
|
|
23659
|
-
fragment QuoteCheckout_QuoteFragment on Quote {
|
|
23660
|
-
id
|
|
23661
|
-
accountId
|
|
23662
|
-
amountDue
|
|
23663
|
-
amount
|
|
23664
|
-
quoteChanges {
|
|
23665
|
-
id
|
|
23666
|
-
charges {
|
|
23667
|
-
kind
|
|
23668
|
-
coupon {
|
|
23669
|
-
couponCode
|
|
23670
|
-
}
|
|
23671
|
-
}
|
|
23473
|
+
const mutation$d = t(`
|
|
23474
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
23475
|
+
quoteRecalculateTaxes(id: $id) {
|
|
23476
|
+
quote {
|
|
23477
|
+
...Signup_QuoteFragment
|
|
23672
23478
|
}
|
|
23673
|
-
|
|
23674
|
-
...shouldShowCouponEditor_QuoteFragment
|
|
23675
|
-
...PaymentForm_QuoteFragment
|
|
23676
|
-
...getQuoteAmountDue_QuoteFragment
|
|
23479
|
+
errors
|
|
23677
23480
|
}
|
|
23678
|
-
|
|
23679
|
-
|
|
23680
|
-
|
|
23681
|
-
|
|
23682
|
-
|
|
23683
|
-
|
|
23684
|
-
|
|
23685
|
-
|
|
23686
|
-
|
|
23687
|
-
|
|
23481
|
+
}
|
|
23482
|
+
`, [Signup_QuoteFragment]);
|
|
23483
|
+
const quoteRecalculateTaxes$2 = async ({ quoteId, apiHost, token, }) => {
|
|
23484
|
+
var _a;
|
|
23485
|
+
const response = await execute(mutation$d, { apiHost, token }, { id: quoteId });
|
|
23486
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
23487
|
+
};
|
|
23488
|
+
|
|
23489
|
+
const { Title, Text: Text$n } = Typography;
|
|
23490
|
+
function PaymentSuccessDisplay({ amountPaid, className, companyName, returnUrl, style, currencyId, }) {
|
|
23491
|
+
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-items-center bunny-justify-center bunny-h-full ${className}`, style: style, children: [jsx(CheckCircleFilled, { style: { fontSize: '48px', color: 'rgb(52 211 153)' } }), jsxs(Title, { level: 3, className: "bunny-mt-2 bunny-m-0", children: ["Payment of ", formatCurrency(amountPaid, currencyId), " successful"] }), returnUrl && (jsxs(Text$n, { className: "bunny-text-slate-500 bunny-cursor-pointer bunny-underline", onClick: () => (window.location.href = returnUrl), children: ["Back to ", companyName] }))] }));
|
|
23492
|
+
}
|
|
23493
|
+
|
|
23494
|
+
const query$5 = t(`
|
|
23495
|
+
query PriceList($code: String!) {
|
|
23496
|
+
priceList (code: $code) {
|
|
23497
|
+
...Signup_PriceListFragment
|
|
23688
23498
|
}
|
|
23689
|
-
|
|
23499
|
+
}
|
|
23500
|
+
`, [Signup_PriceListFragment]);
|
|
23501
|
+
const getPriceList = async ({ token, code, apiHost, }) => {
|
|
23502
|
+
const response = await execute(query$5, { apiHost, token }, { code });
|
|
23503
|
+
return response === null || response === void 0 ? void 0 : response.priceList;
|
|
23504
|
+
};
|
|
23505
|
+
|
|
23506
|
+
const showErrorNotification$2 = useErrorNotification();
|
|
23690
23507
|
const showSuccessNotification$1 = useSuccessNotification();
|
|
23691
|
-
const
|
|
23692
|
-
|
|
23693
|
-
|
|
23694
|
-
//
|
|
23695
|
-
const quote = readFragment(QuoteCheckout_QuoteFragment, maskedQuote);
|
|
23696
|
-
const upgradingSubscription = readFragment(QuoteCheckout_SubscriptionFragment, maskedUpgradingSubscription);
|
|
23697
|
-
// Context
|
|
23698
|
-
const onPaymentMethodSaved = useOnPaymentMethodSaved();
|
|
23699
|
-
const onPaymentMethodRemoved = useOnPaymentMethodRemoved();
|
|
23508
|
+
const showInfoNotification$2 = useInfoNotification();
|
|
23509
|
+
function Signup({ companyName, priceListCode, returnUrl, couponCode, className, shadow = 'shadow-md', style, defaultFirstName, defaultLastName, defaultEmail, defaultCompanyName, defaultBillingCountry, }) {
|
|
23510
|
+
var _a, _b, _c, _d, _e, _f;
|
|
23511
|
+
// Hooks
|
|
23700
23512
|
const { apiHost } = useContext(BunnyContext);
|
|
23701
|
-
const
|
|
23513
|
+
const tokenFromContexts = useToken();
|
|
23702
23514
|
const isMobile = useIsMobile();
|
|
23703
|
-
const
|
|
23704
|
-
const
|
|
23515
|
+
const { topNavImageUrl } = useBrand();
|
|
23516
|
+
const defaultValues = useMemo(() => ({
|
|
23517
|
+
firstName: defaultFirstName,
|
|
23518
|
+
lastName: defaultLastName,
|
|
23519
|
+
email: defaultEmail,
|
|
23520
|
+
accountName: defaultCompanyName,
|
|
23521
|
+
billingCountry: defaultBillingCountry,
|
|
23522
|
+
}), [defaultFirstName, defaultLastName, defaultEmail, defaultCompanyName, defaultBillingCountry]);
|
|
23705
23523
|
const queryClient = useQueryClient();
|
|
23706
|
-
const [
|
|
23707
|
-
const
|
|
23524
|
+
const [initialQuote, setInitialQuote] = useState(undefined);
|
|
23525
|
+
const [accountId, setAccountId] = useState(undefined);
|
|
23526
|
+
const [portalSessionToken, setPortalSessionToken] = useState(undefined);
|
|
23527
|
+
const token = portalSessionToken || tokenFromContexts;
|
|
23528
|
+
const [purchaseSucceeded, setPurchaseSucceeded] = useState(false);
|
|
23529
|
+
const defaultCouponAppliedRef = useRef(undefined);
|
|
23530
|
+
const [couponEditorCouponCode, setCouponEditorCouponCode] = useState('');
|
|
23531
|
+
// Read fragment
|
|
23532
|
+
const initialQuoteId = (_a = readFragment(Signup_QuoteFragment, initialQuote)) === null || _a === void 0 ? void 0 : _a.id;
|
|
23533
|
+
const hasTaxPlugin = useHasTaxPlugin({
|
|
23708
23534
|
apiHost,
|
|
23709
23535
|
token,
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
|
|
23536
|
+
});
|
|
23537
|
+
const { mutate: recalculateTaxesMutation } = useMutation({
|
|
23538
|
+
mutationFn: (quoteId) => {
|
|
23539
|
+
return quoteRecalculateTaxes$2({ token, apiHost, quoteId });
|
|
23540
|
+
},
|
|
23541
|
+
onError: (error) => {
|
|
23542
|
+
if (!error[0].message.includes('Ensure that you have a taxation plugin')) {
|
|
23543
|
+
showErrorNotification$2(error.message);
|
|
23544
|
+
}
|
|
23545
|
+
},
|
|
23546
|
+
onSuccess: (quote) => {
|
|
23547
|
+
queryClient.setQueryData(['quote', initialQuoteId], quote);
|
|
23714
23548
|
queryClient.invalidateQueries({
|
|
23715
|
-
queryKey:
|
|
23716
|
-
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
23717
|
-
objectName: 'editingQuote',
|
|
23718
|
-
token,
|
|
23719
|
-
}),
|
|
23549
|
+
queryKey: ['quote', initialQuoteId],
|
|
23720
23550
|
});
|
|
23721
|
-
showSuccessNotification$1('Coupon applied');
|
|
23722
|
-
onRecalculateTaxes();
|
|
23723
|
-
setCouponCode('');
|
|
23724
23551
|
},
|
|
23725
|
-
|
|
23726
|
-
|
|
23727
|
-
|
|
23552
|
+
});
|
|
23553
|
+
const { mutate: quoteAccountSignupMutate, isPending: isSigningUp } = useMutation({
|
|
23554
|
+
mutationFn: (formData) => {
|
|
23555
|
+
var _a;
|
|
23556
|
+
return quoteAccountSignup({
|
|
23557
|
+
token,
|
|
23558
|
+
apiHost,
|
|
23559
|
+
priceListCode,
|
|
23560
|
+
accountName: formData.accountName,
|
|
23561
|
+
billingContact: {
|
|
23562
|
+
firstName: formData.firstName,
|
|
23563
|
+
lastName: formData.lastName,
|
|
23564
|
+
email: formData.email,
|
|
23565
|
+
},
|
|
23566
|
+
billingDetails: {
|
|
23567
|
+
billingCountry: formData.billingCountry,
|
|
23568
|
+
// TODO: add these billing details back for Avalara and AFC taxation plugins.
|
|
23569
|
+
// billingState: formData.billingState,
|
|
23570
|
+
// billingCity: formData.billingCity,
|
|
23571
|
+
// billingZip: formData.billingZip,
|
|
23572
|
+
// billingStreet: formData.billingStreet,
|
|
23573
|
+
// taxNumber: formData.taxNumber,
|
|
23574
|
+
},
|
|
23575
|
+
trial: (_a = priceList === null || priceList === void 0 ? void 0 : priceList.trialAllowed) !== null && _a !== void 0 ? _a : false,
|
|
23576
|
+
});
|
|
23577
|
+
},
|
|
23578
|
+
onSuccess: (data) => {
|
|
23579
|
+
var _a, _b;
|
|
23580
|
+
setAccountId((_a = data === null || data === void 0 ? void 0 : data.account) === null || _a === void 0 ? void 0 : _a.id);
|
|
23581
|
+
if (!(data === null || data === void 0 ? void 0 : data.portalSessionToken)) {
|
|
23582
|
+
throw new Error('Portal session token is required');
|
|
23583
|
+
}
|
|
23584
|
+
setPortalSessionToken(data === null || data === void 0 ? void 0 : data.portalSessionToken);
|
|
23585
|
+
// We must invalidate the accountPaymentMethodsKey query in order to clear payment methods from the provided api token,
|
|
23586
|
+
// to instead use paymentMethods from portalSessionToken.
|
|
23728
23587
|
queryClient.invalidateQueries({
|
|
23729
|
-
queryKey: QueryKeyFactory.
|
|
23730
|
-
|
|
23731
|
-
objectName: 'editingQuote',
|
|
23588
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
23589
|
+
accountId,
|
|
23732
23590
|
token,
|
|
23733
23591
|
}),
|
|
23734
23592
|
});
|
|
23735
|
-
|
|
23736
|
-
|
|
23593
|
+
setInitialQuote(data === null || data === void 0 ? void 0 : data.quote);
|
|
23594
|
+
handleRecalculateTaxes((_b = data === null || data === void 0 ? void 0 : data.quote) === null || _b === void 0 ? void 0 : _b.id);
|
|
23595
|
+
},
|
|
23596
|
+
onError: (error) => {
|
|
23597
|
+
const errorMessage = error.response.errors[0].message;
|
|
23598
|
+
if (errorMessage.includes("Address couldn't be validated")) {
|
|
23599
|
+
showErrorNotification$2('Please enter a valid billing address');
|
|
23600
|
+
}
|
|
23601
|
+
else {
|
|
23602
|
+
showErrorNotification$2(errorMessage);
|
|
23603
|
+
}
|
|
23737
23604
|
},
|
|
23738
23605
|
});
|
|
23739
|
-
|
|
23740
|
-
const
|
|
23741
|
-
|
|
23742
|
-
|
|
23606
|
+
// Queries
|
|
23607
|
+
const { data: maskedPriceList, isLoading: isLoadingPriceList } = useQuery({
|
|
23608
|
+
queryKey: ['priceList', priceListCode],
|
|
23609
|
+
queryFn: () => getPriceList({ token, apiHost, code: priceListCode }),
|
|
23610
|
+
});
|
|
23611
|
+
const { data, isLoading: isLoadingQuote } = useQuery({
|
|
23612
|
+
queryKey: ['quote', initialQuoteId],
|
|
23613
|
+
queryFn: () => {
|
|
23614
|
+
if (!initialQuoteId) {
|
|
23743
23615
|
throw new Error('Quote ID is required');
|
|
23744
|
-
|
|
23745
|
-
|
|
23746
|
-
return await checkout({ quoteId: quote.id, token, apiHost });
|
|
23616
|
+
}
|
|
23617
|
+
return getQuote$1({ token, apiHost, id: initialQuoteId });
|
|
23747
23618
|
},
|
|
23748
|
-
|
|
23749
|
-
onError: onFail,
|
|
23750
|
-
});
|
|
23751
|
-
async function handleCheckoutNoPayment() {
|
|
23752
|
-
setIsSaving(true);
|
|
23753
|
-
checkoutMutation.mutate();
|
|
23754
|
-
setIsSaving(false);
|
|
23755
|
-
}
|
|
23756
|
-
if (taxationRequiredAccountFields)
|
|
23757
|
-
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
23758
|
-
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: paymentRequired ? (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsx(Fragment, { children: upgradingSubscription &&
|
|
23759
|
-
shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) && (jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsx(Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
23760
|
-
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
23761
|
-
var _a;
|
|
23762
|
-
const couponCode = (_a = couponCharge === null || couponCharge === void 0 ? void 0 : couponCharge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode;
|
|
23763
|
-
if (couponCode) {
|
|
23764
|
-
removeCoupon(couponCode);
|
|
23765
|
-
}
|
|
23766
|
-
});
|
|
23767
|
-
}, children: "Remove coupon(s)" }))] })) : (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsx(Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsx(Text$o, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
23768
|
-
};
|
|
23769
|
-
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
23770
|
-
const isMobile = useIsMobile();
|
|
23771
|
-
return (jsx("div", { className: `bunny-flex bunny-w-full bunny-flex-col bunny-gap-6 ${isMobile ? 'bunny-shadow-padding-xb' : ''} ${className}`, style: {
|
|
23772
|
-
...(isMobile
|
|
23773
|
-
? setMaxHeight
|
|
23774
|
-
? { maxHeight: '60vh' }
|
|
23775
|
-
: {}
|
|
23776
|
-
: {
|
|
23777
|
-
width: '100%',
|
|
23778
|
-
maxWidth: '400px',
|
|
23779
|
-
}),
|
|
23780
|
-
}, children: children }));
|
|
23781
|
-
};
|
|
23782
|
-
|
|
23783
|
-
const Checkout_QuoteFragment = t(`
|
|
23784
|
-
fragment Checkout_QuoteFragment on Quote {
|
|
23785
|
-
id
|
|
23786
|
-
accountId
|
|
23787
|
-
formattedQuote {
|
|
23788
|
-
html
|
|
23789
|
-
}
|
|
23790
|
-
...QuoteCheckout_QuoteFragment
|
|
23791
|
-
}
|
|
23792
|
-
`, [QuoteCheckout_QuoteFragment]);
|
|
23793
|
-
const Checkout = ({ onCancel, onSuccess, onFail, onRecalculateTaxes, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
23794
|
-
var _a, _b, _c, _d, _e;
|
|
23795
|
-
const { apiHost } = useContext(BunnyContext);
|
|
23796
|
-
const isMobile = useIsMobile();
|
|
23797
|
-
const token = useToken();
|
|
23798
|
-
// Context
|
|
23799
|
-
const onPaymentMethodSaved = useOnPaymentMethodSaved();
|
|
23800
|
-
const onPaymentMethodRemoved = useOnPaymentMethodRemoved();
|
|
23801
|
-
// Read fragments
|
|
23802
|
-
const quote = readFragment(Checkout_QuoteFragment, maskedQuote);
|
|
23803
|
-
const hasTaxPlugin = useHasTaxPlugin({
|
|
23804
|
-
apiHost,
|
|
23805
|
-
token,
|
|
23806
|
-
});
|
|
23807
|
-
// Queries
|
|
23808
|
-
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = useQuery({
|
|
23809
|
-
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
23810
|
-
queryFn: () => getTaxationRequiredAccountFields({ apiHost, token }),
|
|
23811
|
-
enabled: Boolean(quote),
|
|
23812
|
-
staleTime: 0,
|
|
23813
|
-
});
|
|
23814
|
-
const { data: account, isLoading: isLoadingAccount } = useQuery({
|
|
23815
|
-
queryKey: ['account', quote === null || quote === void 0 ? void 0 : quote.accountId],
|
|
23816
|
-
queryFn: () => (quote === null || quote === void 0 ? void 0 : quote.accountId) && getAccount$1({ id: quote.accountId, apiHost, token }),
|
|
23817
|
-
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
23818
|
-
});
|
|
23819
|
-
// Use onRecalculateTaxes callback because parents need to define recalculateTaxes to get and set the right quote data they need
|
|
23820
|
-
async function recalculateTaxes() {
|
|
23821
|
-
if (quote) {
|
|
23822
|
-
if (!quote.id)
|
|
23823
|
-
throw new Error('Quote ID is required');
|
|
23824
|
-
onRecalculateTaxes(quote.id);
|
|
23825
|
-
}
|
|
23826
|
-
return {};
|
|
23827
|
-
}
|
|
23828
|
-
const recalculateTaxesEnabled = Boolean(quote) &&
|
|
23829
|
-
open &&
|
|
23830
|
-
hasTaxPlugin &&
|
|
23831
|
-
!taxationRequiredAccountFields &&
|
|
23832
|
-
!isLoadingTaxationRequiredAccountFields &&
|
|
23833
|
-
!isUpdatingQuote;
|
|
23834
|
-
useQuery({
|
|
23835
|
-
queryKey: QueryKeyFactory.createQuoteTaxCalculateKey({
|
|
23836
|
-
id: (_a = quote === null || quote === void 0 ? void 0 : quote.id) !== null && _a !== void 0 ? _a : undefined,
|
|
23837
|
-
token,
|
|
23838
|
-
}),
|
|
23839
|
-
queryFn: recalculateTaxes,
|
|
23840
|
-
// Recalculate taxes if the quote is open, has a tax plugin, and the taxation required account fields are not required
|
|
23841
|
-
enabled: recalculateTaxesEnabled,
|
|
23842
|
-
staleTime: 0,
|
|
23843
|
-
});
|
|
23844
|
-
if (!open || isLoadingTaxationRequiredAccountFields || isLoadingAccount)
|
|
23845
|
-
return null;
|
|
23846
|
-
return (jsx("div", { className: `bunny-flex bunny-flex-col bunny-fixed bunny-top-0 bunny-left-0 bunny-right-0 bunny-bottom-0 bunny-bg-slate-50
|
|
23847
|
-
bunny-overflow-auto bunny-height-full`, style: {
|
|
23848
|
-
zIndex: 1001,
|
|
23849
|
-
}, children: jsxs("div", { className: `bunny-flex bunny-flex-col bunny-grow bunny-pt-4 ${isMobile ? 'bunny-pb-4' : 'bunny-pb-8'} bunny-content-container`, children: [jsx("div", { className: "bunny-flex bunny-justify-end bunny-w-full bunny-pr-4", children: jsx(CloseOutlined, { className: "bunny-text-base bunny-shadow-padding-xb", onClick: onCancel }) }), jsxs("div", { className: `bunny-flex bunny-justify-end bunny-pt-4 bunny-gap-4 ${isMobile ? 'bunny-flex-col' : 'bunny-shadow-padding-xb'}`, children: [((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_b = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _b === void 0 ? void 0 : _b.html)) && (jsx(InvoiceQuoteView, { html: invoice ? invoice.html : (_d = (_c = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _c === void 0 ? void 0 : _c.html) !== null && _d !== void 0 ? _d : '' })), !isMobile && ((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_e = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _e === void 0 ? void 0 : _e.html)) && (jsx(Divider, { className: "bunny-h-full", type: "vertical" })), invoice ? (jsx("div", { className: "bunny-w-full bunny-pt-12", children: jsx(PaymentForm, { onPaymentSuccess: onSuccess, invoice: invoice, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }) })) : quote ? (jsx(QuoteCheckout, { account: account, onFail: error => {
|
|
23850
|
-
onFail(error);
|
|
23851
|
-
}, onSuccess: onSuccess, quote: quote, taxationRequiredAccountFields: taxationRequiredAccountFields, token: token, onRecalculateTaxes: async () => {
|
|
23852
|
-
if (recalculateTaxesEnabled) {
|
|
23853
|
-
await recalculateTaxes();
|
|
23854
|
-
}
|
|
23855
|
-
} })) : (jsx(PaymentForm, { onPaymentSuccess: onSuccess, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }))] }), jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
23856
|
-
};
|
|
23857
|
-
|
|
23858
|
-
function canEditChargeQuantity(charge) {
|
|
23859
|
-
if (!charge)
|
|
23860
|
-
return false;
|
|
23861
|
-
if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
|
|
23862
|
-
return false;
|
|
23863
|
-
if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
|
|
23864
|
-
return false;
|
|
23865
|
-
return true;
|
|
23866
|
-
}
|
|
23867
|
-
|
|
23868
|
-
const { Text: Text$n } = Typography;
|
|
23869
|
-
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
23870
|
-
var _a;
|
|
23871
|
-
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
|
|
23872
|
-
const isMobile = useIsMobile();
|
|
23873
|
-
useEffect(() => {
|
|
23874
|
-
setTimeout(() => {
|
|
23875
|
-
setIsTooltipOpen(true);
|
|
23876
|
-
}, 1000);
|
|
23877
|
-
setTimeout(() => {
|
|
23878
|
-
setIsTooltipOpen(false);
|
|
23879
|
-
}, 6000);
|
|
23880
|
-
}, []);
|
|
23881
|
-
return (jsxs(Text$n, { className: `bunny-flex bunny-items-center bunny-gap-2 ${isMobile ? 'bunny-justify-between' : ''}`, children: [jsx(QuantityLabel, { activeCharge: priceListCharge }), jsx(Tooltip, { onOpenChange: setIsTooltipOpen, open: isTooltipOpen, title: "Change quantity here", styles: {
|
|
23882
|
-
body: {
|
|
23883
|
-
paddingTop: '0.75rem',
|
|
23884
|
-
paddingBottom: '0.75rem',
|
|
23885
|
-
},
|
|
23886
|
-
}, children: jsx(Input, { id: `${(_a = priceListCharge.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().replace(/ /g, '-')}-quantity-input`, className: isMobile ? 'text-right' : '', disabled: disabled, onChange: e => {
|
|
23887
|
-
onQuantityChanged(Number(e.target.value));
|
|
23888
|
-
}, min: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMin, max: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMax, style: { minWidth: '120px' }, type: "number", value: quantity, required: true }) })] }));
|
|
23889
|
-
};
|
|
23890
|
-
const QuantityLabel = ({ activeCharge }) => {
|
|
23891
|
-
const chargeName = activeCharge.name;
|
|
23892
|
-
return (jsx(Text$n, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
23893
|
-
};
|
|
23894
|
-
|
|
23895
|
-
const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
23896
|
-
fragment PlanPickerCheckoutBar_QuoteFragment on Quote {
|
|
23897
|
-
...Checkout_QuoteFragment
|
|
23898
|
-
quoteChanges {
|
|
23899
|
-
priceList {
|
|
23900
|
-
id
|
|
23901
|
-
}
|
|
23902
|
-
charges {
|
|
23903
|
-
priceListCharge {
|
|
23904
|
-
id
|
|
23905
|
-
}
|
|
23906
|
-
}
|
|
23907
|
-
}
|
|
23908
|
-
}
|
|
23909
|
-
`, [Checkout_QuoteFragment]);
|
|
23910
|
-
const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onCheckoutSuccess, }) => {
|
|
23911
|
-
// Context
|
|
23912
|
-
const { shadow } = useSubscriptionProps();
|
|
23913
|
-
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, onRecalculateTaxes, isFeatureAddonsLoading, isUpdatingQuote, } = useContext(QuoteContext);
|
|
23914
|
-
// Read fragments
|
|
23915
|
-
const quote = readFragment(PlanPickerCheckoutBar_QuoteFragment, maskedQuote);
|
|
23916
|
-
// Local state
|
|
23917
|
-
const [payModalVisible, setPayModalVisible] = useState(false);
|
|
23918
|
-
// Hooks
|
|
23919
|
-
const token = useToken();
|
|
23920
|
-
const showSuccessNotification = useSuccessNotification();
|
|
23921
|
-
const queryClient = useQueryClient();
|
|
23922
|
-
const isMobile = useIsMobile();
|
|
23923
|
-
const handleCheckoutSuccess = () => {
|
|
23924
|
-
queryClient.refetchQueries({
|
|
23925
|
-
queryKey: QueryKeyFactory.createTableKey({
|
|
23926
|
-
pluralType: 'subscriptions',
|
|
23927
|
-
token,
|
|
23928
|
-
}),
|
|
23929
|
-
});
|
|
23930
|
-
queryClient.invalidateQueries({
|
|
23931
|
-
queryKey: QueryKeyFactory.createTableKey({
|
|
23932
|
-
pluralType: 'upgradeSubscriptions',
|
|
23933
|
-
token,
|
|
23934
|
-
}),
|
|
23935
|
-
});
|
|
23936
|
-
queryClient.invalidateQueries({
|
|
23937
|
-
queryKey: QueryKeyFactory.createTableKey({
|
|
23938
|
-
pluralType: 'hasActiveSubscriptions',
|
|
23939
|
-
token,
|
|
23940
|
-
}),
|
|
23941
|
-
});
|
|
23942
|
-
queryClient.invalidateQueries({
|
|
23943
|
-
queryKey: QueryKeyFactory.transactionsKey({ token }),
|
|
23944
|
-
});
|
|
23945
|
-
setPayModalVisible(false);
|
|
23946
|
-
showSuccessNotification('Your subscription has been created', 'Checkout successful');
|
|
23947
|
-
onCheckoutSuccess();
|
|
23948
|
-
};
|
|
23949
|
-
return (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-4' : 'bunny-flex-row'} bunny-my-4 bunny-p-4 bunny-justify-between bunny-bg-white bunny-rounded-md ${shadow ? `shadow-${shadow}` : ''}`, children: [jsx("div", { className: `${isMobile ? 'bunny-flex bunny-flex-col' : 'bunny-flex'} bunny-gap-4`, children: selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.charges.map((charge, index) => {
|
|
23950
|
-
var _a, _b, _c, _d;
|
|
23951
|
-
if (!canEditChargeQuantity({
|
|
23952
|
-
chargeType: (_a = charge.chargeType) !== null && _a !== void 0 ? _a : null,
|
|
23953
|
-
pricingModel: (_b = charge.pricingModel) !== null && _b !== void 0 ? _b : null,
|
|
23954
|
-
}))
|
|
23955
|
-
return null;
|
|
23956
|
-
if (!((_c = charge.feature) === null || _c === void 0 ? void 0 : _c.id))
|
|
23957
|
-
throw new Error('Charge feature is undefined');
|
|
23958
|
-
const isFeatureAddon = charge.featureAddon;
|
|
23959
|
-
const quantity = getFeatureQuantity((_d = charge.feature) === null || _d === void 0 ? void 0 : _d.id, charge.id);
|
|
23960
|
-
const maybeIsChargeLoading = isFeatureAddon && isFeatureAddonsLoading;
|
|
23961
|
-
if (!quantity)
|
|
23962
|
-
return null;
|
|
23963
|
-
// if charge is a feature addon, and a corresponding quote charge is not found in quote, return null
|
|
23964
|
-
if (isFeatureAddon && !featureAddonInQuote(selectedPriceList, charge, quote)) {
|
|
23965
|
-
return null;
|
|
23966
|
-
}
|
|
23967
|
-
const isDisabled = !quote || maybeIsChargeLoading || !selectedPriceList || !charge.selfServiceQuantity;
|
|
23968
|
-
return (jsx(CheckoutBarInput, { disabled: isDisabled, priceListCharge: charge, quantity: quantity, onQuantityChanged: quantity => {
|
|
23969
|
-
onChangeQuantity(charge.id, quantity);
|
|
23970
|
-
} }, index));
|
|
23971
|
-
}) }), jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true), selectedPriceList: selectedPriceList }), jsx(Checkout, { onCancel: () => setPayModalVisible(false), onFail: error => handlePortalErrors === null || handlePortalErrors === void 0 ? void 0 : handlePortalErrors(error), onSuccess: handleCheckoutSuccess, onRecalculateTaxes: onRecalculateTaxes, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: isUpdatingQuote })] }));
|
|
23972
|
-
};
|
|
23973
|
-
|
|
23974
|
-
const useQuoteUpdateFeatureAddon_QuoteFragment = t(`
|
|
23975
|
-
fragment useQuoteUpdateFeatureAddon_QuoteFragment on Quote {
|
|
23976
|
-
id
|
|
23977
|
-
startDate
|
|
23978
|
-
}
|
|
23979
|
-
`);
|
|
23980
|
-
|
|
23981
|
-
const FeatureAddonRow_QuoteFragment = t(`
|
|
23982
|
-
fragment FeatureAddonRow_QuoteFragment on Quote {
|
|
23983
|
-
...useQuoteUpdateFeatureAddon_QuoteFragment
|
|
23984
|
-
}
|
|
23985
|
-
`, [useQuoteUpdateFeatureAddon_QuoteFragment]);
|
|
23986
|
-
|
|
23987
|
-
const useToggleAddonPlan_QuoteFragment = t(`
|
|
23988
|
-
fragment useToggleAddonPlan_QuoteFragment on Quote {
|
|
23989
|
-
quoteChanges {
|
|
23990
|
-
priceList {
|
|
23991
|
-
id
|
|
23992
|
-
}
|
|
23993
|
-
id
|
|
23994
|
-
}
|
|
23995
|
-
id
|
|
23996
|
-
}
|
|
23997
|
-
`);
|
|
23998
|
-
|
|
23999
|
-
const AddonPlanRow_QuoteFragment = t(`
|
|
24000
|
-
fragment AddonPlanRow_QuoteFragment on Quote {
|
|
24001
|
-
...useToggleAddonPlan_QuoteFragment
|
|
24002
|
-
}
|
|
24003
|
-
`, [useToggleAddonPlan_QuoteFragment]);
|
|
24004
|
-
|
|
24005
|
-
/**
|
|
24006
|
-
* Central quote fragment for QuoteProvider context.
|
|
24007
|
-
*
|
|
24008
|
-
* This fragment aggregates all child component fragments to ensure the QuoteProvider
|
|
24009
|
-
* fetches all required quote data upfront. When a component needs specific quote fields,
|
|
24010
|
-
* add its fragment here to maintain type safety and avoid over-fetching.
|
|
24011
|
-
*
|
|
24012
|
-
* Pattern: Fragment Composition
|
|
24013
|
-
* - Components define their data needs via fragments
|
|
24014
|
-
* - Provider composes these fragments into a single query
|
|
24015
|
-
* - Type safety ensures all required fields are fetched
|
|
24016
|
-
*/
|
|
24017
|
-
const QuoteContext_QuoteFragment = t(`
|
|
24018
|
-
fragment QuoteContext_QuoteFragment on Quote {
|
|
24019
|
-
id
|
|
24020
|
-
currencyId
|
|
24021
|
-
amountDue
|
|
24022
|
-
startDate
|
|
24023
|
-
quoteChanges {
|
|
24024
|
-
id
|
|
24025
|
-
kind
|
|
24026
|
-
priceList {
|
|
24027
|
-
id
|
|
24028
|
-
}
|
|
24029
|
-
charges {
|
|
24030
|
-
priceListCharge {
|
|
24031
|
-
id
|
|
24032
|
-
chargeType
|
|
24033
|
-
pricingModel
|
|
24034
|
-
quantityMin
|
|
24035
|
-
quantityMax
|
|
24036
|
-
selfServiceQuantity
|
|
24037
|
-
}
|
|
24038
|
-
feature {
|
|
24039
|
-
id
|
|
24040
|
-
}
|
|
24041
|
-
quantity
|
|
24042
|
-
id
|
|
24043
|
-
}
|
|
24044
|
-
}
|
|
24045
|
-
...PlanPickerCheckoutBar_QuoteFragment
|
|
24046
|
-
...CheckoutBarSummarySection_QuoteFragment
|
|
24047
|
-
...AddonPlanRow_QuoteFragment
|
|
24048
|
-
...FeatureAddonRow_QuoteFragment
|
|
24049
|
-
...PaymentForms_QuoteFragment
|
|
24050
|
-
}
|
|
24051
|
-
`, [
|
|
24052
|
-
PlanPickerCheckoutBar_QuoteFragment,
|
|
24053
|
-
CheckoutBarSummarySection_QuoteFragment,
|
|
24054
|
-
AddonPlanRow_QuoteFragment,
|
|
24055
|
-
FeatureAddonRow_QuoteFragment,
|
|
24056
|
-
PaymentForms_QuoteFragment,
|
|
24057
|
-
]);
|
|
24058
|
-
|
|
24059
|
-
const FormattedQuoteField_QuoteFragment = t(`
|
|
24060
|
-
fragment FormattedQuoteField_QuoteFragment on Quote {
|
|
24061
|
-
formattedQuote {
|
|
24062
|
-
html
|
|
24063
|
-
}
|
|
24064
|
-
}
|
|
24065
|
-
`);
|
|
24066
|
-
const query$5 = t(`
|
|
24067
|
-
query quote($id: ID, $removeFormattedQuoteField: Boolean!) {
|
|
24068
|
-
quote(id: $id) {
|
|
24069
|
-
...QuoteContext_QuoteFragment
|
|
24070
|
-
...FormattedQuoteField_QuoteFragment @include(if: $removeFormattedQuoteField)
|
|
24071
|
-
}
|
|
24072
|
-
}
|
|
24073
|
-
`, [QuoteContext_QuoteFragment, FormattedQuoteField_QuoteFragment]);
|
|
24074
|
-
const getQuote$1 = async ({ id, token, apiHost, removeFormattedQuoteField = false, }) => {
|
|
24075
|
-
const response = await execute(query$5, { apiHost, token }, { id, removeFormattedQuoteField });
|
|
24076
|
-
return response === null || response === void 0 ? void 0 : response.quote;
|
|
24077
|
-
};
|
|
24078
|
-
|
|
24079
|
-
const MUTATION$1 = () => `
|
|
24080
|
-
mutation AccountSignup (
|
|
24081
|
-
$pluginId: String!,
|
|
24082
|
-
$paymentMethodId: String,
|
|
24083
|
-
$priceListCode: String!,
|
|
24084
|
-
$accountId: ID!,
|
|
24085
|
-
$quoteId: ID!,
|
|
24086
|
-
) {
|
|
24087
|
-
accountSignup(
|
|
24088
|
-
pluginId: $pluginId,
|
|
24089
|
-
paymentMethodId: $paymentMethodId,
|
|
24090
|
-
priceListCode: $priceListCode,
|
|
24091
|
-
accountId: $accountId,
|
|
24092
|
-
quoteId: $quoteId,
|
|
24093
|
-
) {
|
|
24094
|
-
errors
|
|
24095
|
-
quote {
|
|
24096
|
-
accountId
|
|
24097
|
-
amount
|
|
24098
|
-
amountDue
|
|
24099
|
-
applicationDate
|
|
24100
|
-
applied
|
|
24101
|
-
backdatedPeriods
|
|
24102
|
-
backdatedQuote
|
|
24103
|
-
billingDay
|
|
24104
|
-
contactId
|
|
24105
|
-
createdAt
|
|
24106
|
-
credits
|
|
24107
|
-
currencyId
|
|
24108
|
-
dealId
|
|
24109
|
-
discount
|
|
24110
|
-
discountValue
|
|
24111
|
-
endDate
|
|
24112
|
-
evergreen
|
|
24113
|
-
expiresAt
|
|
24114
|
-
id
|
|
24115
|
-
invoiceImmediately
|
|
24116
|
-
invoiceImmediatelyAvailable
|
|
24117
|
-
invoiceUntil
|
|
24118
|
-
isPendingApprovalRequest
|
|
24119
|
-
kind
|
|
24120
|
-
message
|
|
24121
|
-
name
|
|
24122
|
-
netPaymentDays
|
|
24123
|
-
notes
|
|
24124
|
-
number
|
|
24125
|
-
ownerId
|
|
24126
|
-
payableId
|
|
24127
|
-
periodAmount
|
|
24128
|
-
poNumber
|
|
24129
|
-
requiresApproval
|
|
24130
|
-
smallUnitAmountDue
|
|
24131
|
-
splitInvoice
|
|
24132
|
-
startDate
|
|
24133
|
-
state
|
|
24134
|
-
subtotal
|
|
24135
|
-
taxAmount
|
|
24136
|
-
taxCode
|
|
24137
|
-
updatedAt
|
|
24138
|
-
uuid
|
|
24139
|
-
}
|
|
24140
|
-
}
|
|
24141
|
-
}`;
|
|
24142
|
-
const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken, paymentMethodId, pluginId, priceListCode, }) => {
|
|
24143
|
-
var _a;
|
|
24144
|
-
const vars = {
|
|
24145
|
-
accountId,
|
|
24146
|
-
quoteId,
|
|
24147
|
-
paymentToken,
|
|
24148
|
-
pluginId,
|
|
24149
|
-
paymentMethodId,
|
|
24150
|
-
priceListCode,
|
|
24151
|
-
};
|
|
24152
|
-
const response = await gqlRequest({
|
|
24153
|
-
query: MUTATION$1(),
|
|
24154
|
-
token,
|
|
24155
|
-
vars,
|
|
24156
|
-
apiHost,
|
|
24157
|
-
});
|
|
24158
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.accountSignup) === null || _a === void 0 ? void 0 : _a.errors;
|
|
24159
|
-
if (errors)
|
|
24160
|
-
throw errors;
|
|
24161
|
-
return response === null || response === void 0 ? void 0 : response.accountSignup;
|
|
24162
|
-
};
|
|
24163
|
-
|
|
24164
|
-
const MUTATION = () => `
|
|
24165
|
-
mutation QuoteAccountSignup (
|
|
24166
|
-
$accountName: String!,
|
|
24167
|
-
$billingContact: ContactAttributes!,
|
|
24168
|
-
$priceListCode: String!,
|
|
24169
|
-
$billingDetails: BillingDetailsAttributes
|
|
24170
|
-
) {
|
|
24171
|
-
quoteAccountSignup(
|
|
24172
|
-
priceListCode: $priceListCode,
|
|
24173
|
-
accountName: $accountName,
|
|
24174
|
-
billingContact: $billingContact,
|
|
24175
|
-
billingDetails: $billingDetails
|
|
24176
|
-
) {
|
|
24177
|
-
account {
|
|
24178
|
-
id
|
|
24179
|
-
}
|
|
24180
|
-
quote {
|
|
24181
|
-
accountId
|
|
24182
|
-
amount
|
|
24183
|
-
amountDue
|
|
24184
|
-
applicationDate
|
|
24185
|
-
applied
|
|
24186
|
-
backdatedPeriods
|
|
24187
|
-
backdatedQuote
|
|
24188
|
-
billingDay
|
|
24189
|
-
contactId
|
|
24190
|
-
createdAt
|
|
24191
|
-
credits
|
|
24192
|
-
currencyId
|
|
24193
|
-
dealId
|
|
24194
|
-
discount
|
|
24195
|
-
discountValue
|
|
24196
|
-
endDate
|
|
24197
|
-
evergreen
|
|
24198
|
-
expiresAt
|
|
24199
|
-
id
|
|
24200
|
-
invoiceImmediately
|
|
24201
|
-
invoiceImmediatelyAvailable
|
|
24202
|
-
invoiceUntil
|
|
24203
|
-
isPendingApprovalRequest
|
|
24204
|
-
kind
|
|
24205
|
-
message
|
|
24206
|
-
name
|
|
24207
|
-
netPaymentDays
|
|
24208
|
-
notes
|
|
24209
|
-
number
|
|
24210
|
-
ownerId
|
|
24211
|
-
payableId
|
|
24212
|
-
periodAmount
|
|
24213
|
-
poNumber
|
|
24214
|
-
requiresApproval
|
|
24215
|
-
smallUnitAmountDue
|
|
24216
|
-
splitInvoice
|
|
24217
|
-
startDate
|
|
24218
|
-
state
|
|
24219
|
-
subtotal
|
|
24220
|
-
taxAmount
|
|
24221
|
-
taxCode
|
|
24222
|
-
updatedAt
|
|
24223
|
-
uuid
|
|
24224
|
-
}
|
|
24225
|
-
tenant {
|
|
24226
|
-
code
|
|
24227
|
-
}
|
|
24228
|
-
portalSessionToken
|
|
24229
|
-
errors
|
|
24230
|
-
}
|
|
24231
|
-
}`;
|
|
24232
|
-
const quoteAccountSignup = async ({ token, apiHost, priceListCode, accountName, billingContact, billingDetails, }) => {
|
|
24233
|
-
var _a;
|
|
24234
|
-
const vars = {
|
|
24235
|
-
priceListCode,
|
|
24236
|
-
accountName,
|
|
24237
|
-
billingContact,
|
|
24238
|
-
billingDetails,
|
|
24239
|
-
};
|
|
24240
|
-
const response = await gqlRequest({
|
|
24241
|
-
query: MUTATION(),
|
|
24242
|
-
token,
|
|
24243
|
-
vars,
|
|
24244
|
-
apiHost,
|
|
24245
|
-
});
|
|
24246
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAccountSignup) === null || _a === void 0 ? void 0 : _a.errors;
|
|
24247
|
-
if (errors)
|
|
24248
|
-
throw errors;
|
|
24249
|
-
return response === null || response === void 0 ? void 0 : response.quoteAccountSignup;
|
|
24250
|
-
};
|
|
24251
|
-
|
|
24252
|
-
const QUOTE_RECALCULATE_TAXES = `
|
|
24253
|
-
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
24254
|
-
quoteRecalculateTaxes(id: $id) {
|
|
24255
|
-
quote {
|
|
24256
|
-
accountId
|
|
24257
|
-
amount
|
|
24258
|
-
amountDue
|
|
24259
|
-
smallUnitAmountDue
|
|
24260
|
-
currencyId
|
|
24261
|
-
formattedQuote {
|
|
24262
|
-
html
|
|
24263
|
-
}
|
|
24264
|
-
id
|
|
24265
|
-
payableId
|
|
24266
|
-
periodAmount
|
|
24267
|
-
subtotal
|
|
24268
|
-
taxAmount
|
|
24269
|
-
amountsByPeriod {
|
|
24270
|
-
amount
|
|
24271
|
-
startDate
|
|
24272
|
-
}
|
|
24273
|
-
kind
|
|
24274
|
-
quoteChanges {
|
|
24275
|
-
currencyId
|
|
24276
|
-
id
|
|
24277
|
-
kind
|
|
24278
|
-
charges {
|
|
24279
|
-
subtotal
|
|
24280
|
-
amountsByPeriod {
|
|
24281
|
-
amount
|
|
24282
|
-
startDate
|
|
24283
|
-
}
|
|
24284
|
-
amount
|
|
24285
|
-
billingPeriod
|
|
24286
|
-
currencyId
|
|
24287
|
-
feature {
|
|
24288
|
-
unitName
|
|
24289
|
-
}
|
|
24290
|
-
id
|
|
24291
|
-
name
|
|
24292
|
-
priceListCharge {
|
|
24293
|
-
id
|
|
24294
|
-
}
|
|
24295
|
-
priceList {
|
|
24296
|
-
id
|
|
24297
|
-
}
|
|
24298
|
-
coupon {
|
|
24299
|
-
couponCode
|
|
24300
|
-
}
|
|
24301
|
-
quantity
|
|
24302
|
-
kind
|
|
24303
|
-
}
|
|
24304
|
-
priceList {
|
|
24305
|
-
id
|
|
24306
|
-
plan {
|
|
24307
|
-
name
|
|
24308
|
-
}
|
|
24309
|
-
product {
|
|
24310
|
-
name
|
|
24311
|
-
}
|
|
24312
|
-
}
|
|
24313
|
-
}
|
|
24314
|
-
}
|
|
24315
|
-
errors
|
|
24316
|
-
}
|
|
24317
|
-
}
|
|
24318
|
-
`;
|
|
24319
|
-
const quoteRecalculateTaxes$2 = async ({ quoteId, apiHost, token, }) => {
|
|
24320
|
-
var _a, _b;
|
|
24321
|
-
const vars = { id: quoteId };
|
|
24322
|
-
const response = await gqlRequest({
|
|
24323
|
-
query: QUOTE_RECALCULATE_TAXES,
|
|
24324
|
-
token,
|
|
24325
|
-
vars,
|
|
24326
|
-
apiHost,
|
|
24327
|
-
});
|
|
24328
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.errors;
|
|
24329
|
-
if (errors)
|
|
24330
|
-
throw errors;
|
|
24331
|
-
return (_b = response.quoteRecalculateTaxes) === null || _b === void 0 ? void 0 : _b.quote;
|
|
24332
|
-
};
|
|
24333
|
-
|
|
24334
|
-
const { Text: Text$m } = Typography;
|
|
24335
|
-
const CheckoutSummary_PriceListFragment = t(`
|
|
24336
|
-
fragment CheckoutSummary_PriceListFragment on PriceList {
|
|
24337
|
-
product {
|
|
24338
|
-
name
|
|
24339
|
-
}
|
|
24340
|
-
name
|
|
24341
|
-
}
|
|
24342
|
-
`);
|
|
24343
|
-
function CheckoutSummary({ quote, className, onAddCoupon, onRemoveCoupon, isRemovingCoupon, priceList: maskedPriceList, isAddingCoupon, couponCode, setCouponCode, activeCouponsExist, }) {
|
|
24344
|
-
var _a;
|
|
24345
|
-
const priceList = readFragment(CheckoutSummary_PriceListFragment, maskedPriceList);
|
|
24346
|
-
return (jsxs("div", { className: `${className} bunny-space-y-4`, children: [jsxs(Text$m, { children: [jsxs("div", { className: "bunny-text-lg bunny-font-medium bunny-mb-4", children: ["Checkout summary - ", (_a = priceList === null || priceList === void 0 ? void 0 : priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList === null || priceList === void 0 ? void 0 : priceList.name] }), jsx("div", { className: "bunny-space-y-4", children: quote === null || quote === void 0 ? void 0 : quote.quoteChanges.map(quoteChange => quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges.map(charge => {
|
|
24347
|
-
var _a;
|
|
24348
|
-
const multiplier = charge.kind === 'COUPON' ? -1 : 1;
|
|
24349
|
-
return (jsxs("div", { className: "bunny-grid bunny-grid-cols-3 bunny-gap-4 bunny-items-center", children: [jsx("div", { className: "bunny-col-span-1", children: charge.name }), jsx("div", { className: "bunny-col-span-1 bunny-text-center", children: ((_a = charge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode) ? (jsx("button", { onClick: () => {
|
|
24350
|
-
var _a, _b;
|
|
24351
|
-
if (isRemovingCoupon) {
|
|
24352
|
-
return;
|
|
24353
|
-
}
|
|
24354
|
-
if (!((_a = charge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode)) {
|
|
24355
|
-
throw new Error('Coupon code not found');
|
|
24356
|
-
}
|
|
24357
|
-
onRemoveCoupon((_b = charge.coupon) === null || _b === void 0 ? void 0 : _b.couponCode);
|
|
24358
|
-
}, className: "bunny-text-orange-500 hover:bunny-text-orange-400 bunny-cursor-pointer bunny-bg-transparent bunny-border-none", children: "Remove" })) : (jsx("div", { children: charge.quantity })) }), jsx("div", { className: "bunny-col-span-1 bunny-text-right", children: formatCurrency(multiplier * (charge.subtotal || 0), charge.currencyId) })] }, charge.id));
|
|
24359
|
-
})) }), jsx(CheckoutSummaryDivider, {}), jsxs("div", { className: "bunny-space-y-4", children: [jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Subtotal" }), jsx("div", { children: formatCurrency(quote.subtotal, quote.currencyId) })] }), jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Taxes" }), jsx("div", { children: formatCurrency(quote.taxAmount, quote.currencyId) })] })] }), jsx(CheckoutSummaryDivider, {}), jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsx("div", { children: "Total" }), jsx("div", { children: formatCurrency(quote.amountDue, quote.currencyId) })] })] }), activeCouponsExist && (jsx(CouponEditor, { className: "bunny-w-full", onAddCoupon: onAddCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode }))] }));
|
|
24360
|
-
}
|
|
24361
|
-
const CheckoutSummaryDivider = () => {
|
|
24362
|
-
return (jsx("div", { className: "bunny-my-2", children: jsx(Divider, { className: "m-0" }) }));
|
|
24363
|
-
};
|
|
24364
|
-
|
|
24365
|
-
const SelfServiceBuyWarning_PriceListFragment = t(`
|
|
24366
|
-
fragment SelfServiceBuyWarning_PriceListFragment on PriceList {
|
|
24367
|
-
plan {
|
|
24368
|
-
selfServiceBuy
|
|
24369
|
-
}
|
|
24370
|
-
}
|
|
24371
|
-
`);
|
|
24372
|
-
function SelfServiceBuyWarning({ priceList: maskedPriceList, onShowSelfServiceBuyWarning, }) {
|
|
24373
|
-
const priceList = readFragment(SelfServiceBuyWarning_PriceListFragment, maskedPriceList);
|
|
24374
|
-
const hasShownRef = useRef(false);
|
|
24375
|
-
// Only show the warning when component is first mounted
|
|
24376
|
-
useEffect(() => {
|
|
24377
|
-
var _a;
|
|
24378
|
-
if (!priceList || hasShownRef.current)
|
|
24379
|
-
return;
|
|
24380
|
-
if (((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.selfServiceBuy) === false) {
|
|
24381
|
-
hasShownRef.current = true;
|
|
24382
|
-
onShowSelfServiceBuyWarning();
|
|
24383
|
-
}
|
|
24384
|
-
}, [priceList, onShowSelfServiceBuyWarning]);
|
|
24385
|
-
return null;
|
|
24386
|
-
}
|
|
24387
|
-
|
|
24388
|
-
const { Text: Text$l } = Typography;
|
|
24389
|
-
const PriceListDisplay_PriceListFragment = t(`
|
|
24390
|
-
fragment PriceListDisplay_PriceListFragment on PriceList {
|
|
24391
|
-
product {
|
|
24392
|
-
name
|
|
24393
|
-
}
|
|
24394
|
-
name
|
|
24395
|
-
basePrice
|
|
24396
|
-
currencyId
|
|
24397
|
-
}
|
|
24398
|
-
`);
|
|
24399
|
-
function PriceListDisplay({ priceList: maskedPriceList }) {
|
|
24400
|
-
var _a;
|
|
24401
|
-
const priceList = readFragment(PriceListDisplay_PriceListFragment, maskedPriceList);
|
|
24402
|
-
if (!priceList)
|
|
24403
|
-
return null;
|
|
24404
|
-
return (jsx("div", { className: "bunny-flex bunny-flex-col bunny-space-y-8", children: jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxs(Text$l, { className: "bunny-text-slate-500 bunny-font-bold bunny-text-lg", children: [(_a = priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList.name] }), jsxs(Text$l, { className: "bunny-font-bold bunny-text-xl", children: [formatCurrency(priceList.basePrice, priceList.currencyId), " / month"] })] }) }));
|
|
24405
|
-
}
|
|
24406
|
-
|
|
24407
|
-
const Signup_PriceListFragment = t(`
|
|
24408
|
-
fragment Signup_PriceListFragment on PriceList {
|
|
24409
|
-
...CheckoutSummary_PriceListFragment
|
|
24410
|
-
...PriceListDisplay_PriceListFragment
|
|
24411
|
-
...SelfServiceBuyWarning_PriceListFragment
|
|
24412
|
-
plan {
|
|
24413
|
-
selfServiceBuy
|
|
24414
|
-
}
|
|
24415
|
-
}
|
|
24416
|
-
`, [
|
|
24417
|
-
CheckoutSummary_PriceListFragment,
|
|
24418
|
-
PriceListDisplay_PriceListFragment,
|
|
24419
|
-
SelfServiceBuyWarning_PriceListFragment,
|
|
24420
|
-
]);
|
|
24421
|
-
|
|
24422
|
-
const { Title, Text: Text$k } = Typography;
|
|
24423
|
-
function PaymentSuccessDisplay({ amountPaid, className, companyName, returnUrl, style, currencyId, }) {
|
|
24424
|
-
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-items-center bunny-justify-center bunny-h-full ${className}`, style: style, children: [jsx(CheckCircleFilled, { style: { fontSize: '48px', color: 'rgb(52 211 153)' } }), jsxs(Title, { level: 3, className: "bunny-mt-2 bunny-m-0", children: ["Payment of ", formatCurrency(amountPaid, currencyId), " successful"] }), returnUrl && (jsxs(Text$k, { className: "bunny-text-slate-500 bunny-cursor-pointer bunny-underline", onClick: () => (window.location.href = returnUrl), children: ["Back to ", companyName] }))] }));
|
|
24425
|
-
}
|
|
24426
|
-
|
|
24427
|
-
const mutation$d = t(`
|
|
24428
|
-
query PriceList($code: String!) {
|
|
24429
|
-
priceList (code: $code) {
|
|
24430
|
-
...Signup_PriceListFragment
|
|
24431
|
-
}
|
|
24432
|
-
}
|
|
24433
|
-
`, [Signup_PriceListFragment]);
|
|
24434
|
-
const getPriceList = async ({ token, code, apiHost, }) => {
|
|
24435
|
-
const response = await execute(mutation$d, { apiHost, token }, { code });
|
|
24436
|
-
return response === null || response === void 0 ? void 0 : response.priceList;
|
|
24437
|
-
};
|
|
24438
|
-
|
|
24439
|
-
const showErrorNotification$1 = useErrorNotification();
|
|
24440
|
-
const showSuccessNotification = useSuccessNotification();
|
|
24441
|
-
const showInfoNotification$2 = useInfoNotification();
|
|
24442
|
-
function Signup({ companyName, priceListCode, returnUrl, couponCode, className, shadow = 'shadow-md', style, defaultFirstName, defaultLastName, defaultEmail, defaultCompanyName, defaultBillingCountry, }) {
|
|
24443
|
-
var _a, _b, _c, _d, _e;
|
|
24444
|
-
// Hooks
|
|
24445
|
-
const { apiHost } = useContext(BunnyContext);
|
|
24446
|
-
const tokenFromContexts = useToken();
|
|
24447
|
-
const isMobile = useIsMobile();
|
|
24448
|
-
const { topNavImageUrl } = useBrand();
|
|
24449
|
-
const defaultValues = useMemo(() => ({
|
|
24450
|
-
firstName: defaultFirstName,
|
|
24451
|
-
lastName: defaultLastName,
|
|
24452
|
-
email: defaultEmail,
|
|
24453
|
-
accountName: defaultCompanyName,
|
|
24454
|
-
billingCountry: defaultBillingCountry,
|
|
24455
|
-
}), [defaultFirstName, defaultLastName, defaultEmail, defaultCompanyName, defaultBillingCountry]);
|
|
24456
|
-
const queryClient = useQueryClient();
|
|
24457
|
-
const [initialQuote, setInitialQuote] = useState(undefined);
|
|
24458
|
-
const [accountId, setAccountId] = useState(undefined);
|
|
24459
|
-
const [portalSessionToken, setPortalSessionToken] = useState(undefined);
|
|
24460
|
-
const token = portalSessionToken || tokenFromContexts;
|
|
24461
|
-
const [purchaseSucceeded, setPurchaseSucceeded] = useState(false);
|
|
24462
|
-
const defaultCouponAppliedRef = useRef(undefined);
|
|
24463
|
-
const [couponEditorCouponCode, setCouponEditorCouponCode] = useState('');
|
|
24464
|
-
const hasTaxPlugin = useHasTaxPlugin({
|
|
24465
|
-
apiHost,
|
|
24466
|
-
token,
|
|
24467
|
-
});
|
|
24468
|
-
const { mutate: recalculateTaxesMutation } = useMutation({
|
|
24469
|
-
mutationFn: (quoteId) => {
|
|
24470
|
-
return quoteRecalculateTaxes$2({ token, apiHost, quoteId });
|
|
24471
|
-
},
|
|
24472
|
-
onError: (error) => {
|
|
24473
|
-
if (!error[0].message.includes('Ensure that you have a taxation plugin')) {
|
|
24474
|
-
showErrorNotification$1(error.message);
|
|
24475
|
-
}
|
|
24476
|
-
},
|
|
24477
|
-
onSuccess: (quote) => {
|
|
24478
|
-
queryClient.setQueryData(['quote', initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id], quote);
|
|
24479
|
-
queryClient.invalidateQueries({
|
|
24480
|
-
queryKey: ['quote', initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id],
|
|
24481
|
-
});
|
|
24482
|
-
},
|
|
24483
|
-
});
|
|
24484
|
-
const { mutate: quoteAccountSignupMutate, isPending: isSigningUp } = useMutation({
|
|
24485
|
-
mutationFn: (formData) => {
|
|
24486
|
-
return quoteAccountSignup({
|
|
24487
|
-
token,
|
|
24488
|
-
apiHost,
|
|
24489
|
-
priceListCode,
|
|
24490
|
-
accountName: formData.accountName,
|
|
24491
|
-
billingContact: {
|
|
24492
|
-
firstName: formData.firstName,
|
|
24493
|
-
lastName: formData.lastName,
|
|
24494
|
-
email: formData.email,
|
|
24495
|
-
},
|
|
24496
|
-
billingDetails: {
|
|
24497
|
-
billingCountry: formData.billingCountry,
|
|
24498
|
-
// TODO: add these billing details back for Avalara and AFC taxation plugins.
|
|
24499
|
-
// billingState: formData.billingState,
|
|
24500
|
-
// billingCity: formData.billingCity,
|
|
24501
|
-
// billingZip: formData.billingZip,
|
|
24502
|
-
// billingStreet: formData.billingStreet,
|
|
24503
|
-
// taxNumber: formData.taxNumber,
|
|
24504
|
-
},
|
|
24505
|
-
});
|
|
24506
|
-
},
|
|
24507
|
-
onSuccess: (data) => {
|
|
24508
|
-
setAccountId(data.account.id);
|
|
24509
|
-
setPortalSessionToken(data.portalSessionToken);
|
|
24510
|
-
// We must invalidate the accountPaymentMethodsKey query in order to clear payment methods from the provided api token,
|
|
24511
|
-
// to instead use paymentMethods from portalSessionToken.
|
|
24512
|
-
queryClient.invalidateQueries({
|
|
24513
|
-
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
24514
|
-
accountId,
|
|
24515
|
-
token,
|
|
24516
|
-
}),
|
|
24517
|
-
});
|
|
24518
|
-
setInitialQuote(data.quote);
|
|
24519
|
-
handleRecalculateTaxes(data.quote.id);
|
|
24520
|
-
},
|
|
24521
|
-
onError: (error) => {
|
|
24522
|
-
const errorMessage = error.response.errors[0].message;
|
|
24523
|
-
if (errorMessage.includes("Address couldn't be validated")) {
|
|
24524
|
-
showErrorNotification$1('Please enter a valid billing address');
|
|
24525
|
-
}
|
|
24526
|
-
else {
|
|
24527
|
-
showErrorNotification$1(errorMessage);
|
|
24528
|
-
}
|
|
24529
|
-
},
|
|
24530
|
-
});
|
|
24531
|
-
// Queries
|
|
24532
|
-
const { data: maskedPriceList, isLoading: isLoadingPriceList } = useQuery({
|
|
24533
|
-
queryKey: ['priceList', priceListCode],
|
|
24534
|
-
queryFn: () => getPriceList({ token, apiHost, code: priceListCode }),
|
|
24535
|
-
});
|
|
24536
|
-
const { data, isLoading: isLoadingQuote } = useQuery({
|
|
24537
|
-
queryKey: ['quote', initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id],
|
|
24538
|
-
queryFn: () => {
|
|
24539
|
-
if (!(initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id)) {
|
|
24540
|
-
throw new Error('Quote ID is required');
|
|
24541
|
-
}
|
|
24542
|
-
return getQuote$1({ token, apiHost, id: initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id });
|
|
24543
|
-
},
|
|
24544
|
-
enabled: !!(initialQuote === null || initialQuote === void 0 ? void 0 : initialQuote.id),
|
|
23619
|
+
enabled: !!initialQuoteId,
|
|
24545
23620
|
});
|
|
24546
23621
|
const priceList = readFragment(Signup_PriceListFragment, maskedPriceList);
|
|
24547
|
-
const quote = readFragment(
|
|
24548
|
-
const quoteChangeId = (
|
|
23622
|
+
const quote = readFragment(Signup_QuoteFragment, data || initialQuote);
|
|
23623
|
+
const quoteChangeId = (_e = (_d = (_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b[((_c = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _c === void 0 ? void 0 : _c.length) - 1]) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : undefined;
|
|
24549
23624
|
// Derived state
|
|
24550
|
-
const selfServiceBuyEnabled = (
|
|
23625
|
+
const selfServiceBuyEnabled = (_f = priceList === null || priceList === void 0 ? void 0 : priceList.plan) === null || _f === void 0 ? void 0 : _f.selfServiceBuy;
|
|
24551
23626
|
const { addCoupon, removeCoupon, isAddingCoupon, isRemovingCoupon, activeCouponsExist } = useUpdateCoupons({
|
|
24552
23627
|
apiHost,
|
|
24553
23628
|
token,
|
|
@@ -24556,7 +23631,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
24556
23631
|
queryClient.invalidateQueries({
|
|
24557
23632
|
queryKey: ['quote', quote === null || quote === void 0 ? void 0 : quote.id],
|
|
24558
23633
|
});
|
|
24559
|
-
showSuccessNotification('Coupon applied');
|
|
23634
|
+
showSuccessNotification$1('Coupon applied');
|
|
24560
23635
|
handleRecalculateTaxes(quote === null || quote === void 0 ? void 0 : quote.id);
|
|
24561
23636
|
setCouponEditorCouponCode('');
|
|
24562
23637
|
},
|
|
@@ -24564,7 +23639,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
24564
23639
|
queryClient.invalidateQueries({
|
|
24565
23640
|
queryKey: ['quote', quote === null || quote === void 0 ? void 0 : quote.id],
|
|
24566
23641
|
});
|
|
24567
|
-
showSuccessNotification('Coupon removed');
|
|
23642
|
+
showSuccessNotification$1('Coupon removed');
|
|
24568
23643
|
handleRecalculateTaxes(quote === null || quote === void 0 ? void 0 : quote.id);
|
|
24569
23644
|
},
|
|
24570
23645
|
});
|
|
@@ -24586,17 +23661,19 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
24586
23661
|
setPurchaseSucceeded(true);
|
|
24587
23662
|
}
|
|
24588
23663
|
async function accountSignupFunction(pluginId, paymentMethodId) {
|
|
24589
|
-
var _a;
|
|
24590
23664
|
if (!portalSessionToken) {
|
|
24591
23665
|
throw new Error('Portal session token is required');
|
|
24592
23666
|
}
|
|
24593
23667
|
if (!accountId) {
|
|
24594
23668
|
throw new Error('Account ID is required');
|
|
24595
23669
|
}
|
|
23670
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
23671
|
+
throw new Error('Quote ID is required');
|
|
23672
|
+
}
|
|
24596
23673
|
return await accountSignup({
|
|
24597
23674
|
token: portalSessionToken,
|
|
24598
23675
|
apiHost,
|
|
24599
|
-
quoteId:
|
|
23676
|
+
quoteId: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
24600
23677
|
paymentMethodId,
|
|
24601
23678
|
pluginId,
|
|
24602
23679
|
priceListCode: priceListCode,
|
|
@@ -24609,7 +23686,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
24609
23686
|
return;
|
|
24610
23687
|
}
|
|
24611
23688
|
if (!quoteId) {
|
|
24612
|
-
showErrorNotification$
|
|
23689
|
+
showErrorNotification$2('No quote ID found to recalculate taxes');
|
|
24613
23690
|
return;
|
|
24614
23691
|
}
|
|
24615
23692
|
recalculateTaxesMutation(quoteId);
|
|
@@ -24620,7 +23697,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
24620
23697
|
if (purchaseSucceeded) {
|
|
24621
23698
|
return (jsx(Fragment, { children: (quote === null || quote === void 0 ? void 0 : quote.currencyId) !== undefined ? (jsx("div", { className: "bunny-w-screen bunny-absolute bunny-top-0 bunny-left-0 bunny-flex bunny-items-start bunny-pt-[25vh]", children: jsx(PaymentSuccessDisplay, { amountPaid: (quote === null || quote === void 0 ? void 0 : quote.amountDue) || 0, className: "bunny-w-full", companyName: companyName, returnUrl: returnUrl, currencyId: quote === null || quote === void 0 ? void 0 : quote.currencyId }) })) : (jsx("div", { children: "No currency ID found from Quote" })) }));
|
|
24622
23699
|
}
|
|
24623
|
-
return (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col' : 'bunny-flex-row'} bunny-h-screen bunny-w-screen bunny-absolute bunny-top-0 bunny-left-0 ${shadow} ${className}`, style: style, children: [jsx(SelfServiceBuyWarning, { priceList: priceList, onShowSelfServiceBuyWarning: handleShowSelfServiceBuyWarning }), jsx("div", { className: `bunny-flex bunny-items-center bunny-flex-col ${isMobile ? 'bunny-w-full bunny-h-1/2' : 'bunny-w-1/2 bunny-h-full'} bunny-justify-center`, children: jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-start bunny-justify-between bunny-w-3/5 bunny-h-full bunny-gap-4 bunny-my-24", children: [jsx("div", { children: topNavImageUrl.length > 0 && (jsx("img", { alt: "Logo", src: topNavImageUrl, style: { width: 'auto', height: '28px' } })) }),
|
|
23700
|
+
return (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col' : 'bunny-flex-row'} bunny-h-screen bunny-w-screen bunny-absolute bunny-top-0 bunny-left-0 ${shadow} ${className}`, style: style, children: [jsx(SelfServiceBuyWarning, { priceList: priceList, onShowSelfServiceBuyWarning: handleShowSelfServiceBuyWarning }), jsx("div", { className: `bunny-flex bunny-items-center bunny-flex-col ${isMobile ? 'bunny-w-full bunny-h-1/2' : 'bunny-w-1/2 bunny-h-full'} bunny-justify-center`, children: jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-start bunny-justify-between bunny-w-3/5 bunny-h-full bunny-gap-4 bunny-my-24", children: [jsx("div", { children: topNavImageUrl.length > 0 && (jsx("img", { alt: "Logo", src: topNavImageUrl, style: { width: 'auto', height: '28px' } })) }), quote ? (jsx(CheckoutSummary, { quote: quote, className: "bunny-h-full bunny-w-full", onAddCoupon: addCoupon, onRemoveCoupon: removeCoupon, isRemovingCoupon: isRemovingCoupon, priceList: priceList, isAddingCoupon: isAddingCoupon, couponCode: couponEditorCouponCode, setCouponCode: setCouponEditorCouponCode, activeCouponsExist: activeCouponsExist })) : (jsx("div", { className: "bunny-h-full", children: isLoadingPriceList ? (jsx(Skeleton, { active: true })) : (jsx(PriceListDisplay, { priceList: priceList })) })), jsx(Footer, {})] }) }), jsx("div", { className: `bunny-flex bunny-flex-col ${isMobile ? 'bunny-w-full bunny-h-1/2 bunny-overflow-auto' : 'bunny-w-1/2 bunny-h-full'} bunny-items-center`, style: {
|
|
24624
23701
|
boxShadow: '-5px 0 20px 0 rgba(0, 0, 0, 0.05)',
|
|
24625
23702
|
}, children: isLoadingPriceList ? (jsx(Skeleton, { active: true, className: `bunny-flex bunny-flex-col bunny-w-3/5 bunny-mt-24` })) : (jsx("div", { className: `bunny-flex bunny-flex-col bunny-w-3/5 bunny-mt-24`, children: jsx(PaymentForms, { quote: quote, handlePaymentSuccess: handlePaymentSuccess, handleSubmit: handleSubmit, proceedingToPayment: isSigningUp || isLoadingQuote, accountId: accountId, overrideToken: portalSessionToken, customCheckoutFunction: accountSignupFunction, defaultValues: defaultValues }) })) })] }));
|
|
24626
23703
|
}
|
|
@@ -24629,8 +23706,283 @@ const [ChangeUpgradingSubscriptionProvider, useChangeUpgradingSubscription] = cr
|
|
|
24629
23706
|
|
|
24630
23707
|
const [SubscriptionCancelProvider, useSubscriptionCancel] = createValueContext();
|
|
24631
23708
|
|
|
23709
|
+
const [SubscriptionPropsProvider, useSubscriptionProps] = createValueContext();
|
|
23710
|
+
|
|
23711
|
+
const [UpgradingSubscriptionProvider, useUpgradingSubscription] = createValueContext();
|
|
23712
|
+
|
|
24632
23713
|
const [UpgradingSubscriptionIdProvider, useUpgradingSubscriptionId] = createStateContext(initialValue => useState(initialValue));
|
|
24633
23714
|
|
|
23715
|
+
const QuoteFields_QuoteFragment = t(`
|
|
23716
|
+
fragment QuoteFields_QuoteFragment on Quote @_unmask {
|
|
23717
|
+
accountId
|
|
23718
|
+
amount
|
|
23719
|
+
amountDue
|
|
23720
|
+
smallUnitAmountDue
|
|
23721
|
+
currencyId
|
|
23722
|
+
id
|
|
23723
|
+
payableId
|
|
23724
|
+
periodAmount
|
|
23725
|
+
subtotal
|
|
23726
|
+
taxAmount
|
|
23727
|
+
startDate
|
|
23728
|
+
formattedQuote {
|
|
23729
|
+
html
|
|
23730
|
+
}
|
|
23731
|
+
amountsByPeriod {
|
|
23732
|
+
amount
|
|
23733
|
+
startDate
|
|
23734
|
+
}
|
|
23735
|
+
kind
|
|
23736
|
+
quoteChanges {
|
|
23737
|
+
currencyId
|
|
23738
|
+
id
|
|
23739
|
+
kind
|
|
23740
|
+
charges {
|
|
23741
|
+
subtotal
|
|
23742
|
+
amountsByPeriod {
|
|
23743
|
+
amount
|
|
23744
|
+
startDate
|
|
23745
|
+
}
|
|
23746
|
+
amount
|
|
23747
|
+
billingPeriod
|
|
23748
|
+
currencyId
|
|
23749
|
+
feature {
|
|
23750
|
+
unitName
|
|
23751
|
+
}
|
|
23752
|
+
id
|
|
23753
|
+
name
|
|
23754
|
+
priceListCharge {
|
|
23755
|
+
id
|
|
23756
|
+
}
|
|
23757
|
+
priceList {
|
|
23758
|
+
id
|
|
23759
|
+
}
|
|
23760
|
+
coupon {
|
|
23761
|
+
couponCode
|
|
23762
|
+
}
|
|
23763
|
+
quantity
|
|
23764
|
+
kind
|
|
23765
|
+
}
|
|
23766
|
+
priceList {
|
|
23767
|
+
id
|
|
23768
|
+
plan {
|
|
23769
|
+
name
|
|
23770
|
+
}
|
|
23771
|
+
product {
|
|
23772
|
+
name
|
|
23773
|
+
}
|
|
23774
|
+
}
|
|
23775
|
+
}
|
|
23776
|
+
}
|
|
23777
|
+
`);
|
|
23778
|
+
|
|
23779
|
+
const MUTATION$1 = `
|
|
23780
|
+
mutation accountUpdate(
|
|
23781
|
+
$id: ID!,
|
|
23782
|
+
$attributes: AccountAttributes!) {
|
|
23783
|
+
accountUpdate(
|
|
23784
|
+
id: $id,
|
|
23785
|
+
attributes: $attributes
|
|
23786
|
+
) {
|
|
23787
|
+
account {
|
|
23788
|
+
id
|
|
23789
|
+
billingCountry
|
|
23790
|
+
billingState
|
|
23791
|
+
billingStreet
|
|
23792
|
+
billingCity
|
|
23793
|
+
billingZip
|
|
23794
|
+
name
|
|
23795
|
+
}
|
|
23796
|
+
errors
|
|
23797
|
+
}
|
|
23798
|
+
}
|
|
23799
|
+
`;
|
|
23800
|
+
const accountUpdate$1 = async ({ accountId, attributes, token, apiHost, }) => {
|
|
23801
|
+
var _a;
|
|
23802
|
+
const vars = { id: accountId, attributes };
|
|
23803
|
+
const response = await gqlRequest({
|
|
23804
|
+
query: MUTATION$1,
|
|
23805
|
+
token,
|
|
23806
|
+
vars,
|
|
23807
|
+
apiHost,
|
|
23808
|
+
});
|
|
23809
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.accountUpdate) === null || _a === void 0 ? void 0 : _a.errors;
|
|
23810
|
+
if (errors)
|
|
23811
|
+
throw errors;
|
|
23812
|
+
return response.accountUpdate;
|
|
23813
|
+
};
|
|
23814
|
+
|
|
23815
|
+
const COUNTRIES_REQUIRING_STATE = ['US', 'CA'];
|
|
23816
|
+
const TaxationForm = ({ account, accountId }) => {
|
|
23817
|
+
// Hooks
|
|
23818
|
+
const queryClient = useQueryClient();
|
|
23819
|
+
const { apiHost } = useContext(BunnyContext);
|
|
23820
|
+
const token = useToken();
|
|
23821
|
+
const [form] = Form.useForm();
|
|
23822
|
+
// Mutations
|
|
23823
|
+
const { mutate: updateAccount, isPending: isUpdatingAccount } = useMutation({
|
|
23824
|
+
mutationFn: async (changedFormData) => {
|
|
23825
|
+
const account = await accountUpdate$1({
|
|
23826
|
+
accountId,
|
|
23827
|
+
attributes: changedFormData,
|
|
23828
|
+
token,
|
|
23829
|
+
apiHost,
|
|
23830
|
+
});
|
|
23831
|
+
return account;
|
|
23832
|
+
},
|
|
23833
|
+
onSuccess: () => {
|
|
23834
|
+
queryClient.invalidateQueries({
|
|
23835
|
+
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
23836
|
+
});
|
|
23837
|
+
},
|
|
23838
|
+
});
|
|
23839
|
+
return (jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-4", form: form, initialValues: account, layout: "vertical", onFinish: updateAccount, children: [jsx(Form.Item, { label: "Billing street", name: "billingStreet", children: jsx(Input, { placeholder: "Street" }) }), jsx(Form.Item, { label: "Billing city", name: "billingCity", children: jsx(Input, { placeholder: "City" }) }), jsx(FormBillingState, {}), jsx(Form.Item, { label: "Billing country", name: "billingCountry", rules: [{ required: true }], children: jsx(Select, { options: COUNTRY_LIST, placeholder: "Select a country", showSearch: true, filterOption: (input, option) => {
|
|
23840
|
+
var _a, _b;
|
|
23841
|
+
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
23842
|
+
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
23843
|
+
} }) }), jsx(Form.Item, { label: "Billing zip", name: "billingZip", children: jsx(Input, { placeholder: "Zip" }) }), jsx(Form.Item, { children: jsx(Button, { className: "bunny-w-full", disabled: isUpdatingAccount, htmlType: "submit", type: "primary", children: "Submit" }) })] }));
|
|
23844
|
+
};
|
|
23845
|
+
const FormBillingState = () => {
|
|
23846
|
+
const billingCountry = Form.useWatch('billingCountry');
|
|
23847
|
+
const billingStateRequired = COUNTRIES_REQUIRING_STATE.includes(billingCountry);
|
|
23848
|
+
return (jsx(Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsx(Input, { placeholder: "State" }) }));
|
|
23849
|
+
};
|
|
23850
|
+
|
|
23851
|
+
const [OnPaymentMethodSavedProvider, useOnPaymentMethodSaved] = createValueContext();
|
|
23852
|
+
// This provider is used in all components that may save a payment method
|
|
23853
|
+
|
|
23854
|
+
const [OnPaymentMethodRemovedProvider, useOnPaymentMethodRemoved] = createValueContext();
|
|
23855
|
+
// This provider is used in all components that may remove a payment method
|
|
23856
|
+
|
|
23857
|
+
const { Text: Text$m } = Typography;
|
|
23858
|
+
// HACK: I have imported QuoteFields_QuoteFragment here as a hack to ensure I have all of the quote data needed for
|
|
23859
|
+
// the eventual children of this component.
|
|
23860
|
+
// Solution: Eventually all children of this component should be using query fragments to avoid this
|
|
23861
|
+
const QuoteCheckout_QuoteFragment = t(`
|
|
23862
|
+
fragment QuoteCheckout_QuoteFragment on Quote {
|
|
23863
|
+
id
|
|
23864
|
+
accountId
|
|
23865
|
+
amountDue
|
|
23866
|
+
amount
|
|
23867
|
+
quoteChanges {
|
|
23868
|
+
id
|
|
23869
|
+
charges {
|
|
23870
|
+
kind
|
|
23871
|
+
coupon {
|
|
23872
|
+
couponCode
|
|
23873
|
+
}
|
|
23874
|
+
}
|
|
23875
|
+
}
|
|
23876
|
+
...QuoteFields_QuoteFragment
|
|
23877
|
+
...shouldShowCouponEditor_QuoteFragment
|
|
23878
|
+
...PaymentForm_QuoteFragment
|
|
23879
|
+
...getQuoteAmountDue_QuoteFragment
|
|
23880
|
+
}
|
|
23881
|
+
`, [
|
|
23882
|
+
QuoteFields_QuoteFragment,
|
|
23883
|
+
shouldShowCouponEditor_QuoteFragment,
|
|
23884
|
+
PaymentForm_QuoteFragment,
|
|
23885
|
+
getQuoteAmountDue_QuoteFragment,
|
|
23886
|
+
]);
|
|
23887
|
+
const QuoteCheckout_SubscriptionFragment = t(`
|
|
23888
|
+
fragment QuoteCheckout_SubscriptionFragment on Subscription {
|
|
23889
|
+
id
|
|
23890
|
+
...shouldShowCouponEditor_SubscriptionFragment
|
|
23891
|
+
}
|
|
23892
|
+
`, [shouldShowCouponEditor_SubscriptionFragment]);
|
|
23893
|
+
const showSuccessNotification = useSuccessNotification();
|
|
23894
|
+
const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxationRequiredAccountFields, onRecalculateTaxes, }) => {
|
|
23895
|
+
var _a, _b, _c, _d, _e;
|
|
23896
|
+
const maskedUpgradingSubscription = useUpgradingSubscription();
|
|
23897
|
+
// Read fragments
|
|
23898
|
+
const quote = readFragment(QuoteCheckout_QuoteFragment, maskedQuote);
|
|
23899
|
+
const upgradingSubscription = readFragment(QuoteCheckout_SubscriptionFragment, maskedUpgradingSubscription);
|
|
23900
|
+
// Context
|
|
23901
|
+
const onPaymentMethodSaved = useOnPaymentMethodSaved();
|
|
23902
|
+
const onPaymentMethodRemoved = useOnPaymentMethodRemoved();
|
|
23903
|
+
const { apiHost } = useContext(BunnyContext);
|
|
23904
|
+
const token = useToken();
|
|
23905
|
+
const isMobile = useIsMobile();
|
|
23906
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
23907
|
+
const paymentRequired = getQuoteAmountDue(quote) > 0;
|
|
23908
|
+
const queryClient = useQueryClient();
|
|
23909
|
+
const [couponCode, setCouponCode] = useState('');
|
|
23910
|
+
const { addCoupon, removeCoupon, isAddingCoupon, isRemovingCoupon, activeCouponsExist } = useUpdateCoupons({
|
|
23911
|
+
apiHost,
|
|
23912
|
+
token,
|
|
23913
|
+
quoteChangeId: (_d = (_c = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a[((_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.length) - 1]) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : undefined,
|
|
23914
|
+
onCouponAdded: () => {
|
|
23915
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
23916
|
+
throw new Error('Quote ID is required');
|
|
23917
|
+
queryClient.invalidateQueries({
|
|
23918
|
+
queryKey: QueryKeyFactory.createObjectKey({
|
|
23919
|
+
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
23920
|
+
objectName: 'editingQuote',
|
|
23921
|
+
token,
|
|
23922
|
+
}),
|
|
23923
|
+
});
|
|
23924
|
+
showSuccessNotification('Coupon applied');
|
|
23925
|
+
onRecalculateTaxes();
|
|
23926
|
+
setCouponCode('');
|
|
23927
|
+
},
|
|
23928
|
+
onCouponRemoved: () => {
|
|
23929
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
23930
|
+
throw new Error('Quote ID is required');
|
|
23931
|
+
queryClient.invalidateQueries({
|
|
23932
|
+
queryKey: QueryKeyFactory.createObjectKey({
|
|
23933
|
+
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
23934
|
+
objectName: 'editingQuote',
|
|
23935
|
+
token,
|
|
23936
|
+
}),
|
|
23937
|
+
});
|
|
23938
|
+
showSuccessNotification('Coupon removed');
|
|
23939
|
+
onRecalculateTaxes();
|
|
23940
|
+
},
|
|
23941
|
+
});
|
|
23942
|
+
const couponsOnQuote = (_e = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _e === void 0 ? void 0 : _e.flatMap(quoteChange => { var _a; return (_a = quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges) === null || _a === void 0 ? void 0 : _a.filter(charge => charge.kind === 'COUPON'); });
|
|
23943
|
+
const checkoutMutation = useMutation({
|
|
23944
|
+
mutationFn: async () => {
|
|
23945
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
23946
|
+
throw new Error('Quote ID is required');
|
|
23947
|
+
if (paymentRequired)
|
|
23948
|
+
throw new Error('Payment is required');
|
|
23949
|
+
return await checkout({ quoteId: quote.id, token, apiHost });
|
|
23950
|
+
},
|
|
23951
|
+
onSuccess,
|
|
23952
|
+
onError: onFail,
|
|
23953
|
+
});
|
|
23954
|
+
async function handleCheckoutNoPayment() {
|
|
23955
|
+
setIsSaving(true);
|
|
23956
|
+
checkoutMutation.mutate();
|
|
23957
|
+
setIsSaving(false);
|
|
23958
|
+
}
|
|
23959
|
+
if (taxationRequiredAccountFields)
|
|
23960
|
+
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
23961
|
+
return (jsx(PaymentFormWrapper, { setMaxHeight: false, children: paymentRequired ? (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsx(Fragment, { children: upgradingSubscription &&
|
|
23962
|
+
shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) && (jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsx(Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
23963
|
+
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
23964
|
+
var _a;
|
|
23965
|
+
const couponCode = (_a = couponCharge === null || couponCharge === void 0 ? void 0 : couponCharge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode;
|
|
23966
|
+
if (couponCode) {
|
|
23967
|
+
removeCoupon(couponCode);
|
|
23968
|
+
}
|
|
23969
|
+
});
|
|
23970
|
+
}, children: "Remove coupon(s)" }))] })) : (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsx(Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsx(Text$m, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
23971
|
+
};
|
|
23972
|
+
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
23973
|
+
const isMobile = useIsMobile();
|
|
23974
|
+
return (jsx("div", { className: `bunny-flex bunny-w-full bunny-flex-col bunny-gap-6 ${isMobile ? 'bunny-shadow-padding-xb' : ''} ${className}`, style: {
|
|
23975
|
+
...(isMobile
|
|
23976
|
+
? setMaxHeight
|
|
23977
|
+
? { maxHeight: '60vh' }
|
|
23978
|
+
: {}
|
|
23979
|
+
: {
|
|
23980
|
+
width: '100%',
|
|
23981
|
+
maxWidth: '400px',
|
|
23982
|
+
}),
|
|
23983
|
+
}, children: children }));
|
|
23984
|
+
};
|
|
23985
|
+
|
|
24634
23986
|
const findParentSubscription_SubscriptionFragment = t(`
|
|
24635
23987
|
fragment findParentSubscription_SubscriptionFragment on Subscription {
|
|
24636
23988
|
id
|
|
@@ -24704,15 +24056,6 @@ const Card = ({ children, className, style, }) => {
|
|
|
24704
24056
|
}, children: children }));
|
|
24705
24057
|
};
|
|
24706
24058
|
|
|
24707
|
-
const TAG_COLORS = {
|
|
24708
|
-
ACTIVE: 'green',
|
|
24709
|
-
TRIAL: 'blue',
|
|
24710
|
-
CANCELED: 'red',
|
|
24711
|
-
EXPIRED: 'gray',
|
|
24712
|
-
TRIAL_EXPIRED: 'red',
|
|
24713
|
-
PENDING: 'yellow',
|
|
24714
|
-
};
|
|
24715
|
-
|
|
24716
24059
|
const isSubscriptionNotActive = (subscriptionState) => {
|
|
24717
24060
|
return ((subscriptionState === null || subscriptionState === void 0 ? void 0 : subscriptionState.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
24718
24061
|
(subscriptionState === null || subscriptionState === void 0 ? void 0 : subscriptionState.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
@@ -25086,7 +24429,7 @@ function SubscriptionStatusText({ subscription: maskedSubscription, }) {
|
|
|
25086
24429
|
return `Ends on ${formatDate(endDate || trialEndDate)}`;
|
|
25087
24430
|
}
|
|
25088
24431
|
|
|
25089
|
-
const { Text: Text$
|
|
24432
|
+
const { Text: Text$l } = Typography;
|
|
25090
24433
|
const SubscriptionStatusAndActions_SubscriptionFragment = t(`
|
|
25091
24434
|
fragment SubscriptionStatusAndActions_SubscriptionFragment on Subscription {
|
|
25092
24435
|
id
|
|
@@ -25124,11 +24467,11 @@ function SubscriptionStatusAndActions({ subscription: maskedSubscription, }) {
|
|
|
25124
24467
|
const cardActionsVisible = !isMobile;
|
|
25125
24468
|
const showStatusSkeleton = arePriceListChangeOptionsLoading && cardActionsVisible;
|
|
25126
24469
|
const showActionsSkeleton = arePriceListChangeOptionsLoading && !priceListChangeOptions;
|
|
25127
|
-
return (jsxs(Fragment, { children: [showStatusSkeleton ? (jsx(Skeleton.Input, { active: true, size: "small", style: { width: 180 } })) : (jsx(Text$
|
|
24470
|
+
return (jsxs(Fragment, { children: [showStatusSkeleton ? (jsx(Skeleton.Input, { active: true, size: "small", style: { width: 180 } })) : (jsx(Text$l, { className: "bunny-grow", children: jsx(SubscriptionStatusText, { subscription: subscription }) })), cardActionsVisible &&
|
|
25128
24471
|
(showActionsSkeleton ? (jsx(Skeleton.Button, { active: true, size: "default", style: { width: 100 } })) : (jsx(SubscriptionCardActions, { priceListChangeOptions: priceListChangeOptions, subscription: subscription, isPaymentMethodLoading: isPaymentMethodLoading })))] }));
|
|
25129
24472
|
}
|
|
25130
24473
|
|
|
25131
|
-
const { Text: Text$
|
|
24474
|
+
const { Text: Text$k } = Typography;
|
|
25132
24475
|
const SubscriptionCardHeader_SubscriptionFragment = t(`
|
|
25133
24476
|
fragment SubscriptionCardHeader_SubscriptionFragment on Subscription {
|
|
25134
24477
|
id
|
|
@@ -25166,10 +24509,10 @@ const SubscriptionCardHeader = ({ subscription: maskedSubscription, }) => {
|
|
|
25166
24509
|
const isTrial = isSubscriptionTrial(subscription.state);
|
|
25167
24510
|
return (jsxs("div", { className: "bunny-flex bunny-items-center bunny-justify-between", style: {
|
|
25168
24511
|
backgroundColor: darkMode ? 'var(--row-background-dark)' : '',
|
|
25169
|
-
}, children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [((_a = subscription === null || subscription === void 0 ? void 0 : subscription.product) === null || _a === void 0 ? void 0 : _a.name) && (jsx(Text$
|
|
24512
|
+
}, children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [((_a = subscription === null || subscription === void 0 ? void 0 : subscription.product) === null || _a === void 0 ? void 0 : _a.name) && (jsx(Text$k, { style: {
|
|
25170
24513
|
color: brandColor,
|
|
25171
24514
|
...subscriptionProductNameStyle,
|
|
25172
|
-
}, children: subscription.product.name })), jsxs("div", { className: "bunny-flex bunny-grow bunny-items-center bunny-gap-2", children: [((_b = subscription === null || subscription === void 0 ? void 0 : subscription.plan) === null || _b === void 0 ? void 0 : _b.name) && (jsx(Text$
|
|
24515
|
+
}, children: subscription.product.name })), jsxs("div", { className: "bunny-flex bunny-grow bunny-items-center bunny-gap-2", children: [((_b = subscription === null || subscription === void 0 ? void 0 : subscription.plan) === null || _b === void 0 ? void 0 : _b.name) && (jsx(Text$k, { className: "bunny-text-sm", children: subscription.plan.name })), jsxs(CustomizedTag, { color: TAG_COLORS[(_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()], children: [lodashExports.capitalize(subscription.state.toLowerCase().replace(/_/g, ' ')), isTrial ? ` (${trialDaysLeft !== null && trialDaysLeft !== void 0 ? trialDaysLeft : 'N/A'} days left)` : ''] }), ((_d = subscription.priceList) === null || _d === void 0 ? void 0 : _d.deprecated) && (jsx(CustomizedTag, { color: LEGACY_SUBSCRIPTION_COLOR, children: "Legacy" }))] })] }), jsx("div", { className: "bunny-flex bunny-items-center bunny-gap-6", children: jsx(SubscriptionStatusAndActions, { subscription: subscription }) })] }));
|
|
25173
24516
|
};
|
|
25174
24517
|
|
|
25175
24518
|
const filterSubscriptionCharges_SubscriptionChargeFragment = t(`
|
|
@@ -25222,11 +24565,37 @@ function sortSubscriptionCharges(charges) {
|
|
|
25222
24565
|
return orderedCharges;
|
|
25223
24566
|
}
|
|
25224
24567
|
|
|
25225
|
-
const { Text: Text$
|
|
24568
|
+
const { Text: Text$j } = Typography;
|
|
25226
24569
|
const SubscriptionCardColumnHeaders = ({ columns, }) => {
|
|
25227
|
-
return (jsx(Fragment, { children: columns.map((subscriptionColumn, index) => (jsx(Text$
|
|
24570
|
+
return (jsx(Fragment, { children: columns.map((subscriptionColumn, index) => (jsx(Text$j, { className: `bunny-text-slate-400 ${subscriptionColumn.className}`, children: subscriptionColumn.title }, index))) }));
|
|
25228
24571
|
};
|
|
25229
24572
|
|
|
24573
|
+
var ChargeType;
|
|
24574
|
+
(function (ChargeType) {
|
|
24575
|
+
ChargeType["USAGE"] = "USAGE";
|
|
24576
|
+
ChargeType["ONE_TIME"] = "ONE_TIME";
|
|
24577
|
+
ChargeType["RECURRING"] = "RECURRING";
|
|
24578
|
+
})(ChargeType || (ChargeType = {}));
|
|
24579
|
+
var ChargeType$1 = ChargeType;
|
|
24580
|
+
|
|
24581
|
+
var QuoteChangeKind;
|
|
24582
|
+
(function (QuoteChangeKind) {
|
|
24583
|
+
QuoteChangeKind["ADJUSTMENT"] = "ADJUSTMENT";
|
|
24584
|
+
QuoteChangeKind["COUPON"] = "COUPON";
|
|
24585
|
+
QuoteChangeKind["CREDIT"] = "CREDIT";
|
|
24586
|
+
QuoteChangeKind["DISCOUNT"] = "DISCOUNT";
|
|
24587
|
+
QuoteChangeKind["FREE_PERIOD_DISCOUNT"] = "FREE_PERIOD_DISCOUNT";
|
|
24588
|
+
QuoteChangeKind["PRICE_UPDATE"] = "PRICE_UPDATE";
|
|
24589
|
+
QuoteChangeKind["QUANTITY_UPDATE"] = "QUANTITY_UPDATE";
|
|
24590
|
+
QuoteChangeKind["REINSTATE"] = "REINSTATE";
|
|
24591
|
+
QuoteChangeKind["RENEW"] = "RENEW";
|
|
24592
|
+
QuoteChangeKind["SUBSCRIBE"] = "SUBSCRIBE";
|
|
24593
|
+
QuoteChangeKind["UNSUBSCRIBE"] = "UNSUBSCRIBE";
|
|
24594
|
+
QuoteChangeKind["UPDATE"] = "UPDATE";
|
|
24595
|
+
QuoteChangeKind["ACTIVATE"] = "ACTIVATE";
|
|
24596
|
+
})(QuoteChangeKind || (QuoteChangeKind = {}));
|
|
24597
|
+
var QuoteChangeKind$1 = QuoteChangeKind;
|
|
24598
|
+
|
|
25230
24599
|
var utc$2 = {exports: {}};
|
|
25231
24600
|
|
|
25232
24601
|
var utc$1 = utc$2.exports;
|
|
@@ -25514,7 +24883,7 @@ const TieredDisplayDropdown = ({ pricingModel, charge: maskedCharge, currencyId,
|
|
|
25514
24883
|
const nextRecord = priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers[index + 1];
|
|
25515
24884
|
const starts = record.starts;
|
|
25516
24885
|
const ends = (nextRecord === null || nextRecord === void 0 ? void 0 : nextRecord.starts) ? nextRecord.starts - 1 : '+';
|
|
25517
|
-
return (jsxs(Fragment, { children: [formatNumber(starts, 0), typeof ends === 'number' ? formatNumber(ends, 0) : '+'] }));
|
|
24886
|
+
return (jsxs(Fragment, { children: [formatNumber(starts, 0), typeof ends === 'number' ? ' - ' : '', typeof ends === 'number' ? formatNumber(ends, 0) : '+'] }));
|
|
25518
24887
|
},
|
|
25519
24888
|
},
|
|
25520
24889
|
{
|
|
@@ -25612,9 +24981,9 @@ const SubscriptionChargeUnitPrice = ({ charge: maskedCharge, currencyId, }) => {
|
|
|
25612
24981
|
return (jsx(Fragment, { children: hasPriceTiers(charge) ? (jsx(TieredDisplayDropdown, { pricingModel: charge.pricingModel, charge: charge, currencyId: currencyId, priceDecimals: (_c = charge.priceDecimals) !== null && _c !== void 0 ? _c : 0, truncatedText: `${charge.kind === 'PRICE_UPDATE' ? 'new ' : ''}${getApplicablePriceTier(charge, currencyId, (_d = charge.priceDecimals) !== null && _d !== void 0 ? _d : 0)}` })) : isChargeDiscount ? (`-${price}`) : (price) }));
|
|
25613
24982
|
};
|
|
25614
24983
|
|
|
25615
|
-
const { Text: Text$
|
|
24984
|
+
const { Text: Text$i } = Typography;
|
|
25616
24985
|
const SubscriptionsListCell = ({ children, className, gridColumn, right, style, }) => {
|
|
25617
|
-
return (jsx(Text$
|
|
24986
|
+
return (jsx(Text$i, { className: `bunny-flex bunny-items-center bunny-text-sm bunny-whitespace-nowrap ${className}`, style: {
|
|
25618
24987
|
gridColumn,
|
|
25619
24988
|
textAlign: right ? "right" : "left",
|
|
25620
24989
|
justifyContent: right ? "flex-end" : "flex-start",
|
|
@@ -25786,9 +25155,9 @@ function AddonSubscriptionsCards({ subscriptions: maskedSubscriptions, subscript
|
|
|
25786
25155
|
}) }));
|
|
25787
25156
|
}
|
|
25788
25157
|
|
|
25789
|
-
const { Text: Text$
|
|
25158
|
+
const { Text: Text$h } = Typography;
|
|
25790
25159
|
const SubscriptionCardCellMobile = ({ children, className, style, }) => {
|
|
25791
|
-
return (jsx(Text$
|
|
25160
|
+
return (jsx(Text$h, { className: className, style: style, children: children }));
|
|
25792
25161
|
};
|
|
25793
25162
|
|
|
25794
25163
|
const SubscriptionCardMobile_SubscriptionFragment = t(`
|
|
@@ -25894,6 +25263,38 @@ const SubscriptionsList = ({ showInactive, subscriptions: maskedSubscriptions, }
|
|
|
25894
25263
|
}) }));
|
|
25895
25264
|
};
|
|
25896
25265
|
|
|
25266
|
+
const canSubscriptionUpgradeFromTrial_SubscriptionFragment = t(`
|
|
25267
|
+
fragment canSubscriptionUpgradeFromTrial_SubscriptionFragment on Subscription {
|
|
25268
|
+
state
|
|
25269
|
+
plan {
|
|
25270
|
+
selfServiceBuy
|
|
25271
|
+
}
|
|
25272
|
+
}
|
|
25273
|
+
`);
|
|
25274
|
+
const canSubscriptionUpgradeFromTrial = (maskedSubscription) => {
|
|
25275
|
+
var _a, _b;
|
|
25276
|
+
const subscription = readFragment(canSubscriptionUpgradeFromTrial_SubscriptionFragment, maskedSubscription);
|
|
25277
|
+
return ((((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
25278
|
+
((_b = subscription.plan) === null || _b === void 0 ? void 0 : _b.selfServiceBuy)) ||
|
|
25279
|
+
false);
|
|
25280
|
+
};
|
|
25281
|
+
|
|
25282
|
+
const canSubscriptionUpgradeFromTrialExpired_SubscriptionFragment = t(`
|
|
25283
|
+
fragment canSubscriptionUpgradeFromTrialExpired_SubscriptionFragment on Subscription {
|
|
25284
|
+
state
|
|
25285
|
+
plan {
|
|
25286
|
+
selfServiceBuy
|
|
25287
|
+
}
|
|
25288
|
+
}
|
|
25289
|
+
`);
|
|
25290
|
+
const canSubscriptionUpgradeFromTrialExpired = (maskedSubscription) => {
|
|
25291
|
+
var _a, _b;
|
|
25292
|
+
const subscription = readFragment(canSubscriptionUpgradeFromTrialExpired_SubscriptionFragment, maskedSubscription);
|
|
25293
|
+
return ((((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
25294
|
+
((_b = subscription.plan) === null || _b === void 0 ? void 0 : _b.selfServiceBuy)) ||
|
|
25295
|
+
false);
|
|
25296
|
+
};
|
|
25297
|
+
|
|
25897
25298
|
const PriceListCardButton_PriceListFragment = t(`
|
|
25898
25299
|
fragment PriceListCardButton_PriceListFragment on PriceList {
|
|
25899
25300
|
id
|
|
@@ -25944,16 +25345,50 @@ const PriceListCardButton = ({ disableSelectCurrentPlan, isPriceListCurrentSubsc
|
|
|
25944
25345
|
return (jsx("div", { className: "bunny-flex bunny-flex-col bunny-grow bunny-w-full bunny-gap-3", children: jsx(Button, { className: "bunny-w-full", disabled: disableSelectCurrentPlan, type: isSelected ? 'primary' : 'default', children: createButtonText() }) }));
|
|
25945
25346
|
};
|
|
25946
25347
|
|
|
25348
|
+
const periodMonthsConverter = (period) => {
|
|
25349
|
+
if (period === 0)
|
|
25350
|
+
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
25351
|
+
else if (period === 1)
|
|
25352
|
+
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
25353
|
+
else if (period === 3)
|
|
25354
|
+
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
25355
|
+
else if (period === 6)
|
|
25356
|
+
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
25357
|
+
else if (period === 12)
|
|
25358
|
+
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
25359
|
+
else
|
|
25360
|
+
return null;
|
|
25361
|
+
};
|
|
25362
|
+
const billingPeriodConverter = (period) => {
|
|
25363
|
+
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
25364
|
+
return 0;
|
|
25365
|
+
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
25366
|
+
return 1;
|
|
25367
|
+
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
25368
|
+
return 3;
|
|
25369
|
+
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
25370
|
+
return 6;
|
|
25371
|
+
else
|
|
25372
|
+
return 12;
|
|
25373
|
+
};
|
|
25374
|
+
|
|
25375
|
+
const QuoteContext = createContext({});
|
|
25376
|
+
|
|
25947
25377
|
const BillingPeriodSelector = ({ availableBillingPeriods, onChangeBillingPeriod, products, selectedBillingPeriod, selectedProduct, onChangeProduct, }) => {
|
|
25948
25378
|
const { secondaryColor, brandColor } = useBrand();
|
|
25949
25379
|
const isMobile = useIsMobile();
|
|
25380
|
+
const { isInPreviewMode } = useSubscriptionProps();
|
|
25950
25381
|
if (!availableBillingPeriods || (availableBillingPeriods === null || availableBillingPeriods === void 0 ? void 0 : availableBillingPeriods.length) < 2)
|
|
25951
25382
|
return null;
|
|
25952
25383
|
return (jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-8", children: [(products === null || products === void 0 ? void 0 : products.length) && products.length > 1 && (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsx("div", { className: "bunny-font-medium bunny-text-xs", style: {
|
|
25953
25384
|
color: secondaryColor,
|
|
25954
25385
|
}, children: "Select product" }), jsx(ProductRadioStyled, { brandColor: brandColor, children: jsx(Radio.Group, { onChange: e => {
|
|
25386
|
+
if (isInPreviewMode)
|
|
25387
|
+
return;
|
|
25955
25388
|
onChangeProduct(products === null || products === void 0 ? void 0 : products.find(product => product.id === e.target.value));
|
|
25956
25389
|
}, value: selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id, buttonStyle: "solid", children: jsx(Space, { className: "bunny-gap-2", children: products === null || products === void 0 ? void 0 : products.map(product => (jsx(Radio.Button, { value: product.id, children: product.name }, product.id))) }) }) })] })), jsx("div", { className: "bunny-flex bunny-flex-col bunny-w-full bunny-gap-2", children: jsx(StyledRadioGroup, { className: "bunny-w-full", "$isMobile": isMobile, children: jsx(Radio.Group, { onChange: e => {
|
|
25390
|
+
if (isInPreviewMode)
|
|
25391
|
+
return;
|
|
25957
25392
|
onChangeBillingPeriod(e.target.value);
|
|
25958
25393
|
}, value: selectedBillingPeriod, size: "small", buttonStyle: "solid", children: availableBillingPeriods === null || availableBillingPeriods === void 0 ? void 0 : availableBillingPeriods.map((periodMonth, index) => {
|
|
25959
25394
|
return (jsx(Radio.Button, { value: periodMonthsConverter(periodMonth), children: periodMonthsConverter(periodMonth) }, index));
|
|
@@ -25988,14 +25423,140 @@ const StyledRadioGroup = styled.div `
|
|
|
25988
25423
|
> span {
|
|
25989
25424
|
font-size: 11px !important;
|
|
25990
25425
|
}
|
|
25991
|
-
}
|
|
25992
|
-
.ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked) {
|
|
25993
|
-
background: transparent !important;
|
|
25994
|
-
}
|
|
25995
|
-
.ant-radio-button-wrapper::before {
|
|
25996
|
-
display: none !important;
|
|
25997
|
-
}
|
|
25998
|
-
`;
|
|
25426
|
+
}
|
|
25427
|
+
.ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked) {
|
|
25428
|
+
background: transparent !important;
|
|
25429
|
+
}
|
|
25430
|
+
.ant-radio-button-wrapper::before {
|
|
25431
|
+
display: none !important;
|
|
25432
|
+
}
|
|
25433
|
+
`;
|
|
25434
|
+
|
|
25435
|
+
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
25436
|
+
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
25437
|
+
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
25438
|
+
}
|
|
25439
|
+
|
|
25440
|
+
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
25441
|
+
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
25442
|
+
priceLists {
|
|
25443
|
+
id
|
|
25444
|
+
isVisible
|
|
25445
|
+
periodMonths
|
|
25446
|
+
}
|
|
25447
|
+
}
|
|
25448
|
+
`);
|
|
25449
|
+
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
25450
|
+
// Read fragments
|
|
25451
|
+
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
25452
|
+
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
25453
|
+
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
25454
|
+
var _a;
|
|
25455
|
+
return !((_a = currentSubscription === null || currentSubscription === void 0 ? void 0 : currentSubscription.addonSubscriptions) === null || _a === void 0 ? void 0 : _a.some(addonSubscription => addonSubscription.priceList.id === addonPriceList.id));
|
|
25456
|
+
});
|
|
25457
|
+
return unpurchasedAddonPriceLists.length > 0;
|
|
25458
|
+
}
|
|
25459
|
+
|
|
25460
|
+
function hasUnpurchasedFeatureAddons(priceList, currentSubscription) {
|
|
25461
|
+
const featureAddons = priceList.charges.filter(charge => charge.featureAddon);
|
|
25462
|
+
const purchasedFeatureAddons = currentSubscription === null || currentSubscription === void 0 ? void 0 : currentSubscription.charges.filter(charge => { var _a; return (_a = charge.priceListCharge) === null || _a === void 0 ? void 0 : _a.featureAddon; });
|
|
25463
|
+
const unpurchasedFeatureAddons = featureAddons.filter(charge => !(purchasedFeatureAddons === null || purchasedFeatureAddons === void 0 ? void 0 : purchasedFeatureAddons.some(purchasedCharge => { var _a; return ((_a = purchasedCharge.priceListCharge) === null || _a === void 0 ? void 0 : _a.id) === charge.id; })));
|
|
25464
|
+
return unpurchasedFeatureAddons.length > 0;
|
|
25465
|
+
}
|
|
25466
|
+
function findQuoteChangeForFeatureAddon(quote) {
|
|
25467
|
+
return quote === null || quote === void 0 ? void 0 : quote.quoteChanges.find(qc => qc.kind === QuoteChangeKind$1.UPDATE ||
|
|
25468
|
+
qc.kind === QuoteChangeKind$1.SUBSCRIBE ||
|
|
25469
|
+
qc.kind === QuoteChangeKind$1.ACTIVATE);
|
|
25470
|
+
}
|
|
25471
|
+
function featureAddonInQuote(selectedPriceList, priceListCharge, quote) {
|
|
25472
|
+
var _a, _b, _c;
|
|
25473
|
+
const quoteChange = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.find(qc => { var _a; return ((_a = qc === null || qc === void 0 ? void 0 : qc.priceList) === null || _a === void 0 ? void 0 : _a.id) === selectedPriceList.id; });
|
|
25474
|
+
if (!quoteChange)
|
|
25475
|
+
return false;
|
|
25476
|
+
return (_c = (_b = quoteChange.charges) === null || _b === void 0 ? void 0 : _b.some(c => { var _a; return ((_a = c.priceListCharge) === null || _a === void 0 ? void 0 : _a.id) === priceListCharge.id; })) !== null && _c !== void 0 ? _c : false;
|
|
25477
|
+
}
|
|
25478
|
+
// ID Cucumber will use to find the feature addon switch
|
|
25479
|
+
function featureAddonSwitchTestId(addonName) {
|
|
25480
|
+
const name = addonName.toLowerCase().replace(/ /g, '-');
|
|
25481
|
+
return `feature-addon-switch-${name}`;
|
|
25482
|
+
}
|
|
25483
|
+
|
|
25484
|
+
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
25485
|
+
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
25486
|
+
const createPlanDescription = (planDescription) => {
|
|
25487
|
+
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
25488
|
+
};
|
|
25489
|
+
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
25490
|
+
if (!priceList) {
|
|
25491
|
+
return;
|
|
25492
|
+
}
|
|
25493
|
+
// If a period option is selected, return the charge that matches the selected period option
|
|
25494
|
+
let activeBillingPLCharge;
|
|
25495
|
+
// Default to first price list charge
|
|
25496
|
+
let lowestPLCharge;
|
|
25497
|
+
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
25498
|
+
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
25499
|
+
activeBillingPLCharge = priceList.charges[0];
|
|
25500
|
+
}
|
|
25501
|
+
for (let j = 0; j < priceList.charges.length; j++) {
|
|
25502
|
+
const charge = priceList.charges[j];
|
|
25503
|
+
if (charge.chargeType === ChargeType$1.USAGE || charge.featureAddon === true)
|
|
25504
|
+
continue;
|
|
25505
|
+
if (activeBillingPLCharge) {
|
|
25506
|
+
// If we already found a charge with the same billing period check if this charge is lower
|
|
25507
|
+
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
25508
|
+
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
25509
|
+
activeBillingPLCharge = charge;
|
|
25510
|
+
}
|
|
25511
|
+
}
|
|
25512
|
+
// If a period option is selected, only return the charge if it matches the selected period option
|
|
25513
|
+
else if (selectedPriceList &&
|
|
25514
|
+
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
25515
|
+
activeBillingPLCharge = charge;
|
|
25516
|
+
}
|
|
25517
|
+
// Otherwise, return the lowest price list charge
|
|
25518
|
+
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
25519
|
+
lowestPLCharge = charge;
|
|
25520
|
+
}
|
|
25521
|
+
}
|
|
25522
|
+
return {
|
|
25523
|
+
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
25524
|
+
};
|
|
25525
|
+
};
|
|
25526
|
+
const showErrorNotification$1 = useErrorNotification();
|
|
25527
|
+
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
25528
|
+
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
25529
|
+
if (!priceListAddonPlans) {
|
|
25530
|
+
showErrorNotification$1('Price list addon plans are undefined');
|
|
25531
|
+
return false;
|
|
25532
|
+
}
|
|
25533
|
+
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
25534
|
+
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
25535
|
+
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription); // TODO: set type properly later
|
|
25536
|
+
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription); // TODO: set type properly later
|
|
25537
|
+
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
25538
|
+
// When should priceList be disabled?
|
|
25539
|
+
// if upgradingSubscription?.priceList.id === priceList.id
|
|
25540
|
+
// AND the upgradingSubscription is not in trial
|
|
25541
|
+
// AND cannot purchase feature addons
|
|
25542
|
+
// AND cannot purchase add-on plans
|
|
25543
|
+
// AND selfServiceBuy is false
|
|
25544
|
+
// if upgradingSubscription?.priceList.id != priceList.id
|
|
25545
|
+
// AND upgradingSubscription is expired trial
|
|
25546
|
+
// AND priceList is not deprecated
|
|
25547
|
+
if (isUpgradingSubscriptionPriceList) {
|
|
25548
|
+
return (!existingSubscriptionInTrial &&
|
|
25549
|
+
!existingSubscriptionInTrialExpired &&
|
|
25550
|
+
!canPurchaseFeatureAddons &&
|
|
25551
|
+
!canPurchasePlanAddons);
|
|
25552
|
+
}
|
|
25553
|
+
else if (priceList === null || priceList === void 0 ? void 0 : priceList.deprecated) {
|
|
25554
|
+
return true;
|
|
25555
|
+
}
|
|
25556
|
+
else {
|
|
25557
|
+
return false;
|
|
25558
|
+
}
|
|
25559
|
+
};
|
|
25999
25560
|
|
|
26000
25561
|
const NextPriceListButton = ({ availablePriceLists, priceListStart, setPriceListStart, numberOfPlansToDisplay, }) => {
|
|
26001
25562
|
return (jsxs("div", { className: "bunny-absolute bunny-flex bunny-gap-1", style: { top: '12px', right: '8px' }, children: [priceListStart > 0 && (jsx("div", { className: "bunny-flex bunny-items-center bunny-justify-center bunny-rounded-full bunny-shadow bunny-p-1 bunny-cursor-pointer", onClick: () => {
|
|
@@ -26056,12 +25617,12 @@ function priceDescriptionString({ unitName, showPriceAsMonthly, periodMonths, pr
|
|
|
26056
25617
|
return `Per ${unitName && !priceListHasFlatFeeCharges ? `${unitName.toLowerCase()} / ` : ''}${showPriceAsMonthly ? 'month' : periodLabel}`;
|
|
26057
25618
|
}
|
|
26058
25619
|
|
|
26059
|
-
const { Text: Text$
|
|
25620
|
+
const { Text: Text$g } = Typography;
|
|
26060
25621
|
const PriceTierPrice = ({ currencyId, priceDecimals, tier, }) => {
|
|
26061
|
-
return (jsx(Text$
|
|
25622
|
+
return (jsx(Text$g, { className: "bunny-text-white", children: formatCurrency(tier.price, currencyId, priceDecimals) }));
|
|
26062
25623
|
};
|
|
26063
25624
|
|
|
26064
|
-
const { Text: Text$
|
|
25625
|
+
const { Text: Text$f } = Typography;
|
|
26065
25626
|
const PriceTierRow_PriceTierFragment = t(`
|
|
26066
25627
|
fragment PriceTierRow_PriceTierFragment on PriceListChargeTier {
|
|
26067
25628
|
starts
|
|
@@ -26076,10 +25637,10 @@ const PriceTierRow = ({ tier: maskedTier, nextTier: maskedNextTier, }) => {
|
|
|
26076
25637
|
}
|
|
26077
25638
|
return `${tier === null || tier === void 0 ? void 0 : tier.starts}+`;
|
|
26078
25639
|
})();
|
|
26079
|
-
return jsx(Text$
|
|
25640
|
+
return jsx(Text$f, { className: "bunny-text-white", children: text });
|
|
26080
25641
|
};
|
|
26081
25642
|
|
|
26082
|
-
const { Text: Text$
|
|
25643
|
+
const { Text: Text$e } = Typography;
|
|
26083
25644
|
const ChargePriceTiers_PriceListChargeFragment = t(`
|
|
26084
25645
|
fragment ChargePriceTiers_PriceListChargeFragment on PriceListCharge {
|
|
26085
25646
|
id
|
|
@@ -26096,7 +25657,7 @@ const ChargePriceTiers_PriceListChargeFragment = t(`
|
|
|
26096
25657
|
const ChargePriceTiers = ({ charge: maskedCharge, currencyId, }) => {
|
|
26097
25658
|
var _a;
|
|
26098
25659
|
const charge = readFragment(ChargePriceTiers_PriceListChargeFragment, maskedCharge);
|
|
26099
|
-
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-1 bunny-w-full", children: [jsx(Text$
|
|
25660
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-1 bunny-w-full", children: [jsx(Text$e, { className: "bunny-text-white bunny-font-bold", children: charge.name }), jsxs(Text$e, { className: "bunny-flex bunny-flex-row bunny-text-gray-400 bunny-text-xs/3", children: [getPricingModelTitle(charge.pricingModel), " pricing -", ' ', getPricingModelDescription(charge.pricingModel)] }), jsx("div", { style: {
|
|
26100
25661
|
maxWidth: '150px',
|
|
26101
25662
|
minWidth: '50%',
|
|
26102
25663
|
gap: '0.1rem',
|
|
@@ -26247,7 +25808,7 @@ const hasMultipleRecurringCharges = (maskedPriceList) => {
|
|
|
26247
25808
|
return (((_b = (_a = priceList.charges) === null || _a === void 0 ? void 0 : _a.filter(charge => charge.chargeType !== t.scalar('ChargeType', 'USAGE') && charge.featureAddon !== true).length) !== null && _b !== void 0 ? _b : 0) > 1);
|
|
26248
25809
|
};
|
|
26249
25810
|
|
|
26250
|
-
const { Text: Text$
|
|
25811
|
+
const { Text: Text$d } = Typography;
|
|
26251
25812
|
const MarkupWrapper = defaultStyled.div `
|
|
26252
25813
|
padding: 0 !important;
|
|
26253
25814
|
margin: 0 !important;
|
|
@@ -26282,7 +25843,7 @@ const PriceListCardPriceDescription = ({ feature, priceList: maskedPriceList, })
|
|
|
26282
25843
|
const billingPeriodText = periodMonthsConverted
|
|
26283
25844
|
? BillingPeriodConverter$1[periodMonthsConverted]
|
|
26284
25845
|
: 'undefined';
|
|
26285
|
-
return (jsxs(Text$
|
|
25846
|
+
return (jsxs(Text$d, { className: "bunny-text-start bunny-text-gray-400 bunny-text-sm", children: [jsx("div", { children: ((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.pricingDescription) && !isEmptyHtml(priceList.plan.pricingDescription) ? (jsx(MarkupWrapper, { children: jsx(Markup, { content: priceList.plan.pricingDescription }) })) : (priceDescriptionString({
|
|
26286
25847
|
unitName: hasMultipleRecurringCharges(priceList) ? undefined : feature === null || feature === void 0 ? void 0 : feature.unitName,
|
|
26287
25848
|
showPriceAsMonthly: priceList.showPriceAsMonthly,
|
|
26288
25849
|
periodMonths: priceList.periodMonths,
|
|
@@ -26290,9 +25851,9 @@ const PriceListCardPriceDescription = ({ feature, priceList: maskedPriceList, })
|
|
|
26290
25851
|
})) }), priceList.periodMonths && priceList.periodMonths > 1 && (jsxs("div", { children: ["Billed ", billingPeriodText] }))] }));
|
|
26291
25852
|
};
|
|
26292
25853
|
|
|
26293
|
-
const { Text: Text$
|
|
25854
|
+
const { Text: Text$c } = Typography;
|
|
26294
25855
|
const PriceListCardDescription = ({ description }) => {
|
|
26295
|
-
return (jsx(Text$
|
|
25856
|
+
return (jsx(Text$c, { className: "bunny-text-gray-400 bunny-text-sm", children: jsx(Markup, { content: description }) }));
|
|
26296
25857
|
};
|
|
26297
25858
|
|
|
26298
25859
|
const GetPrice_PriceListFragment = t(`
|
|
@@ -26318,218 +25879,609 @@ const PriceListPriceText_PriceListFragment = t(`
|
|
|
26318
25879
|
id
|
|
26319
25880
|
pricingStyle
|
|
26320
25881
|
}
|
|
26321
|
-
currencyId
|
|
26322
|
-
...GetPrice_PriceListFragment
|
|
25882
|
+
currencyId
|
|
25883
|
+
...GetPrice_PriceListFragment
|
|
25884
|
+
}
|
|
25885
|
+
`, [GetPrice_PriceListFragment]);
|
|
25886
|
+
function priceListPriceText({ priceList: maskedPriceList, }) {
|
|
25887
|
+
var _a, _b, _c;
|
|
25888
|
+
// Read fragments
|
|
25889
|
+
const priceList = readFragment(PriceListPriceText_PriceListFragment, maskedPriceList);
|
|
25890
|
+
const calculatePriceDecimals = () => {
|
|
25891
|
+
var _a, _b;
|
|
25892
|
+
if (((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.pricingStyle) === t.scalar('PlanPricingStyles', 'PRICED')) {
|
|
25893
|
+
const decimalPart = (_b = getPrice(priceList)) === null || _b === void 0 ? void 0 : _b.toString().split('.')[1];
|
|
25894
|
+
if (!decimalPart)
|
|
25895
|
+
return 0;
|
|
25896
|
+
// If decimal part consists only of zeros, return 0
|
|
25897
|
+
if (parseInt(decimalPart) === 0) {
|
|
25898
|
+
return 0;
|
|
25899
|
+
}
|
|
25900
|
+
return undefined;
|
|
25901
|
+
}
|
|
25902
|
+
return 0;
|
|
25903
|
+
};
|
|
25904
|
+
const priceDecimals = calculatePriceDecimals();
|
|
25905
|
+
const price = !((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.pricingStyle) ||
|
|
25906
|
+
((_b = priceList.plan) === null || _b === void 0 ? void 0 : _b.pricingStyle) === t.scalar('PlanPricingStyles', 'PRICED')
|
|
25907
|
+
? formatCurrency(getPrice(priceList), priceList.currencyId, priceDecimals)
|
|
25908
|
+
: ((_c = priceList.plan) === null || _c === void 0 ? void 0 : _c.pricingStyle) === t.scalar('PlanPricingStyles', 'CONTACT_US')
|
|
25909
|
+
? 'Custom'
|
|
25910
|
+
: 'Free';
|
|
25911
|
+
return price;
|
|
25912
|
+
}
|
|
25913
|
+
|
|
25914
|
+
const { Text: Text$b } = Typography;
|
|
25915
|
+
const PriceListCardPrice_PriceListFragment = t(`
|
|
25916
|
+
fragment PriceListCardPrice_PriceListFragment on PriceList {
|
|
25917
|
+
...PriceListPriceText_PriceListFragment
|
|
25918
|
+
}
|
|
25919
|
+
`, [PriceListPriceText_PriceListFragment]);
|
|
25920
|
+
const PriceListCardPrice = ({ className, priceList: maskedPriceList, }) => {
|
|
25921
|
+
// Read fragments
|
|
25922
|
+
const priceList = readFragment(PriceListCardPrice_PriceListFragment, maskedPriceList);
|
|
25923
|
+
return (jsx(Text$b, { className: className ? className : 'bunny-font-medium bunny-text-3xl bunny-text-gray-900', children: priceListPriceText({ priceList }) }));
|
|
25924
|
+
};
|
|
25925
|
+
|
|
25926
|
+
const { Text: Text$a } = Typography;
|
|
25927
|
+
const PriceListCardTitle = ({ planName, isPriceListCurrentSubscription, trialRemainingDays, }) => {
|
|
25928
|
+
const { brandColor } = useBrand();
|
|
25929
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-4", children: [Boolean(trialRemainingDays) && (jsx("div", { className: "bunny-font-medium bunny-text-secondary", style: { height: '1rem' }, children: isPriceListCurrentSubscription
|
|
25930
|
+
? `Trial ends in ${trialRemainingDays} day${trialRemainingDays === 1 ? '' : 's'}`
|
|
25931
|
+
: ' ' })), jsx(Text$a, { className: "bunny-font-medium bunny-text-xl bunny-text-left", style: { color: brandColor }, children: planName })] }));
|
|
25932
|
+
};
|
|
25933
|
+
|
|
25934
|
+
const PLAN_GRID_PADDING = 4;
|
|
25935
|
+
const PlanPickerGridCell = ({ children, noBorder, }) => {
|
|
25936
|
+
const isMobile = useIsMobile();
|
|
25937
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col", style: isMobile
|
|
25938
|
+
? {}
|
|
25939
|
+
: {
|
|
25940
|
+
...(noBorder ? {} : { borderLeft: `1px solid ${SLATE_200}` }),
|
|
25941
|
+
}, children: [jsx("div", { className: "bunny-grow", children: children }), jsx("div", { className: "bunny-mt-4" })] }));
|
|
25942
|
+
};
|
|
25943
|
+
|
|
25944
|
+
const PriceListCardDesktop_PriceListFragment = t(`
|
|
25945
|
+
fragment PriceListCardDesktop_PriceListFragment on PriceList {
|
|
25946
|
+
id
|
|
25947
|
+
deprecated
|
|
25948
|
+
plan {
|
|
25949
|
+
id
|
|
25950
|
+
pricingStyle
|
|
25951
|
+
contactUsUrl
|
|
25952
|
+
name
|
|
25953
|
+
}
|
|
25954
|
+
charges {
|
|
25955
|
+
id
|
|
25956
|
+
featureAddon
|
|
25957
|
+
priceListChargeTiers {
|
|
25958
|
+
starts
|
|
25959
|
+
price
|
|
25960
|
+
}
|
|
25961
|
+
...PricingTooltip_PriceListChargeFragment
|
|
25962
|
+
}
|
|
25963
|
+
currencyId
|
|
25964
|
+
...PriceListCardButton_PriceListFragment
|
|
25965
|
+
...PriceListHasPriceTiers_PriceListFragment
|
|
25966
|
+
...PricingTooltip_PriceListFragment
|
|
25967
|
+
...PriceListCardPrice_PriceListFragment
|
|
25968
|
+
...PriceListCardPriceDescription_PriceListFragment
|
|
25969
|
+
}
|
|
25970
|
+
`, [
|
|
25971
|
+
PriceListCardButton_PriceListFragment,
|
|
25972
|
+
PricingTooltip_PriceListChargeFragment,
|
|
25973
|
+
PriceListHasPriceTiers_PriceListFragment,
|
|
25974
|
+
PricingTooltip_PriceListFragment,
|
|
25975
|
+
PriceListCardPrice_PriceListFragment,
|
|
25976
|
+
PriceListCardPriceDescription_PriceListFragment,
|
|
25977
|
+
]);
|
|
25978
|
+
const PriceListCardDesktop = ({ hideButton, description, disableSelectCurrentPlan, feature, isPriceListCurrentSubscription, isSelected, priceList: maskedPriceList, subscriptionPlan, trialRemainingDays, noBorder, onClickPriceListCard, }) => {
|
|
25979
|
+
var _a, _b, _c, _d;
|
|
25980
|
+
// Context
|
|
25981
|
+
const { isInPreviewMode } = useSubscriptionProps();
|
|
25982
|
+
// Read fragments
|
|
25983
|
+
const priceList = readFragment(PriceListCardDesktop_PriceListFragment, maskedPriceList);
|
|
25984
|
+
return (jsx(PlanPickerGridCell, { noBorder: noBorder, children: jsxs("div", { className: `bunny-flex bunny-flex-col bunny-items-start bunny-justify-between bunny-w-full bunny-rounded-md bunny-gap-4 bunny-pt-4 bunny-px-4 ${disableSelectCurrentPlan ? '' : 'cursor-pointer'} bunny-box-border`, onClick: () => {
|
|
25985
|
+
var _a, _b, _c;
|
|
25986
|
+
if (isInPreviewMode)
|
|
25987
|
+
return;
|
|
25988
|
+
if (!disableSelectCurrentPlan) {
|
|
25989
|
+
if (((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.pricingStyle) === t.scalar('PlanPricingStyles', 'CONTACT_US')) {
|
|
25990
|
+
window.open((_c = (_b = priceList.plan) === null || _b === void 0 ? void 0 : _b.contactUsUrl) !== null && _c !== void 0 ? _c : undefined, '_blank');
|
|
25991
|
+
}
|
|
25992
|
+
else {
|
|
25993
|
+
onClickPriceListCard === null || onClickPriceListCard === void 0 ? void 0 : onClickPriceListCard(priceList);
|
|
25994
|
+
}
|
|
25995
|
+
}
|
|
25996
|
+
}, style: {
|
|
25997
|
+
height: '100%',
|
|
25998
|
+
}, children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-8 bunny-h-full bunny-justify-between", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-start bunny-gap-2", children: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx(PriceListCardTitle, { isPriceListCurrentSubscription: isPriceListCurrentSubscription, planName: (_b = (_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'undefined', trialRemainingDays: trialRemainingDays }), priceList.deprecated && jsx(CustomizedTag, { color: 'orange', children: "Legacy" })] }), jsx(PriceListCardDescription, { description: description })] }), jsxs("div", { style: {
|
|
25999
|
+
display: 'grid',
|
|
26000
|
+
gridTemplateRows: 'auto minmax(40px, auto)',
|
|
26001
|
+
alignItems: 'start',
|
|
26002
|
+
}, children: [jsx(PriceListCardPrice, { priceList: priceList }), jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx(PriceListCardPriceDescription, { feature: feature, priceList: priceList }), priceListHasPriceTiers(priceList) && (jsx(PricingTooltip, { priceListCharges: (_d = (_c = priceList.charges) === null || _c === void 0 ? void 0 : _c.filter(charge => charge.featureAddon !== true)) !== null && _d !== void 0 ? _d : [], currencyId: priceList.currencyId, priceList: priceList }))] })] })] }), !hideButton && (jsx(PriceListCardButton, { disableSelectCurrentPlan: disableSelectCurrentPlan, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, subscriptionPlan: subscriptionPlan }))] }) }));
|
|
26003
|
+
};
|
|
26004
|
+
|
|
26005
|
+
const CheckIcon = ({ backgroundColor, size, }) => {
|
|
26006
|
+
return (jsx("div", { className: "bunny-flex bunny-items-center bunny-justify-center bunny-rounded-full bunny-shrink-0", style: { width: size, height: size, backgroundColor }, children: jsx("svg", { width: "8", height: "6", viewBox: "0 0 8 6", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M1.5 2.99992L3.16667 4.66659L6.5 1.33325", stroke: "white", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }) }));
|
|
26007
|
+
};
|
|
26008
|
+
|
|
26009
|
+
const PriceListCardMobile_PriceListFragment = t(`
|
|
26010
|
+
fragment PriceListCardMobile_PriceListFragment on PriceList {
|
|
26011
|
+
plan {
|
|
26012
|
+
name
|
|
26013
|
+
}
|
|
26014
|
+
...PriceListCardPriceDescription_PriceListFragment
|
|
26015
|
+
...PriceListCardButton_PriceListFragment
|
|
26016
|
+
...PriceListCardPrice_PriceListFragment
|
|
26017
|
+
...PriceListCardButton_PriceListFragment
|
|
26018
|
+
}
|
|
26019
|
+
`, [
|
|
26020
|
+
PriceListCardPriceDescription_PriceListFragment,
|
|
26021
|
+
PriceListCardButton_PriceListFragment,
|
|
26022
|
+
PriceListCardPrice_PriceListFragment,
|
|
26023
|
+
PriceListCardButton_PriceListFragment,
|
|
26024
|
+
]);
|
|
26025
|
+
const PriceListCardMobile = ({ description, feature, isPriceListCurrentSubscription, isSelected, priceList: maskedPriceList, subscriptionPlan, trialRemainingDays, disableOnClickPriceListCard, onClickPriceListCard, }) => {
|
|
26026
|
+
var _a, _b;
|
|
26027
|
+
// Context
|
|
26028
|
+
const { brandColor } = useBrand();
|
|
26029
|
+
const { isInPreviewMode } = useSubscriptionProps();
|
|
26030
|
+
// Read fragments
|
|
26031
|
+
const priceList = readFragment(PriceListCardMobile_PriceListFragment, maskedPriceList);
|
|
26032
|
+
return (jsxs("div", { className: `bunny-relative bunny-flex bunny-flex-col bunny-border-2 bunny-border-solid bunny-rounded-lg bunny-p-4`, onClick: () => {
|
|
26033
|
+
if (isInPreviewMode)
|
|
26034
|
+
return;
|
|
26035
|
+
if (!disableOnClickPriceListCard)
|
|
26036
|
+
onClickPriceListCard === null || onClickPriceListCard === void 0 ? void 0 : onClickPriceListCard(priceList);
|
|
26037
|
+
}, style: {
|
|
26038
|
+
minWidth: '220px',
|
|
26039
|
+
borderColor: isSelected ? brandColor : SLATE_200,
|
|
26040
|
+
}, children: [isSelected && (jsx("div", { className: "bunny-absolute", style: {
|
|
26041
|
+
top: '10px',
|
|
26042
|
+
right: '10px',
|
|
26043
|
+
}, children: jsx(CheckIcon, { backgroundColor: brandColor, size: "20px" }) })), jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-center bunny-grow bunny-gap-2", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-center bunny-gap-2", children: [jsx(PriceListCardTitle, { isPriceListCurrentSubscription: isPriceListCurrentSubscription, planName: (_b = (_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'undefined', trialRemainingDays: trialRemainingDays }), jsx(PriceListCardDescription, { description: description })] }), jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-center bunny-gap-2", children: [jsx(PriceListCardPrice, { priceList: priceList }), jsx(PriceListCardPriceDescription, { feature: feature, priceList: priceList })] }), jsx(PriceListCardButton, { disableSelectCurrentPlan: disableOnClickPriceListCard, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, subscriptionPlan: subscriptionPlan })] })] }));
|
|
26044
|
+
};
|
|
26045
|
+
|
|
26046
|
+
const PriceListCard_PriceListFragment = t(`
|
|
26047
|
+
fragment PriceListCard_PriceListFragment on PriceList {
|
|
26048
|
+
id
|
|
26049
|
+
plan {
|
|
26050
|
+
description
|
|
26051
|
+
id
|
|
26052
|
+
}
|
|
26053
|
+
...PriceListCardDesktop_PriceListFragment
|
|
26054
|
+
...PriceListCardMobile_PriceListFragment
|
|
26055
|
+
}
|
|
26056
|
+
`, [PriceListCardDesktop_PriceListFragment, PriceListCardMobile_PriceListFragment]);
|
|
26057
|
+
const PriceListCard = ({ hideButton, isSelected, priceList: maskedPriceList, subscriptions, trialRemainingDays, noBorder, onClickPriceListCard, disableCurrentPlan, }) => {
|
|
26058
|
+
var _a, _b, _c, _d;
|
|
26059
|
+
const isMobile = useIsMobile();
|
|
26060
|
+
const upgradingSubscription = useUpgradingSubscription();
|
|
26061
|
+
// Read fragments
|
|
26062
|
+
const priceList = readFragment(PriceListCard_PriceListFragment, maskedPriceList);
|
|
26063
|
+
// Derived state
|
|
26064
|
+
const description = createPlanDescription((_b = (_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : '');
|
|
26065
|
+
// Get the active price list charge for this plan
|
|
26066
|
+
const activeCharge = (_c = getActivePlanPriceData(priceList, priceList)) === null || _c === void 0 ? void 0 : _c.activeCharge;
|
|
26067
|
+
// Is the price list the current price list for the upgradingSubscription
|
|
26068
|
+
const isPriceListCurrentSubscription = ((_d = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) === null || _d === void 0 ? void 0 : _d.id) === priceList.id;
|
|
26069
|
+
const disableSelectCurrentPlan = disableCurrentPlan !== null && disableCurrentPlan !== void 0 ? disableCurrentPlan : isPriceListDisabled({
|
|
26070
|
+
priceList: priceList,
|
|
26071
|
+
upgradingSubscription: upgradingSubscription, // TODO: set type properly later
|
|
26072
|
+
});
|
|
26073
|
+
const subscriptionPlan = subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.find(subscription => {
|
|
26074
|
+
var _a, _b;
|
|
26075
|
+
return subscription.plan.id === ((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.id) &&
|
|
26076
|
+
subscription.state !== t.scalar('SubscriptionState', 'CANCELED') &&
|
|
26077
|
+
subscription.state !== t.scalar('SubscriptionState', 'EXPIRED') &&
|
|
26078
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
26079
|
+
});
|
|
26080
|
+
if (!activeCharge) {
|
|
26081
|
+
return null;
|
|
26082
|
+
}
|
|
26083
|
+
const { feature } = activeCharge;
|
|
26084
|
+
return isMobile ? (jsx(PriceListCardMobile, { description: description, feature: feature, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, trialRemainingDays: trialRemainingDays, subscriptionPlan: subscriptionPlan,
|
|
26085
|
+
// TODO: naming mismatch disableOnClickPriceListCard vs disableSelectCurrentPlan, maybe also functionality mismatch? (ignore for now, mobile won't ever show this currently)
|
|
26086
|
+
disableOnClickPriceListCard: disableSelectCurrentPlan, onClickPriceListCard: onClickPriceListCard })) : (jsx(PriceListCardDesktop, { hideButton: hideButton, description: description, disableSelectCurrentPlan: disableSelectCurrentPlan, feature: feature, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, trialRemainingDays: trialRemainingDays, subscriptionPlan: subscriptionPlan, noBorder: noBorder, onClickPriceListCard: onClickPriceListCard }));
|
|
26087
|
+
};
|
|
26088
|
+
|
|
26089
|
+
const useSetQuoteQueryData$1 = () => {
|
|
26090
|
+
const token = useToken();
|
|
26091
|
+
const queryClient = useQueryClient();
|
|
26092
|
+
const setQuoteQueryData = (quoteId, quote) => {
|
|
26093
|
+
queryClient.setQueryData(QueryKeyFactory.createObjectKey({
|
|
26094
|
+
id: quoteId,
|
|
26095
|
+
objectName: 'editingQuote',
|
|
26096
|
+
token,
|
|
26097
|
+
}), quote);
|
|
26098
|
+
};
|
|
26099
|
+
return { setQuoteQueryData };
|
|
26100
|
+
};
|
|
26101
|
+
|
|
26102
|
+
const CheckoutButton = ({ disabled, onClickCheckout, loading, tooltipText, }) => {
|
|
26103
|
+
const isMobile = useIsMobile();
|
|
26104
|
+
const TooltipWrapper = ({ children }) => {
|
|
26105
|
+
if (tooltipText) {
|
|
26106
|
+
return jsx(Tooltip, { title: tooltipText, children: children });
|
|
26107
|
+
}
|
|
26108
|
+
return jsx("div", { children: children });
|
|
26109
|
+
};
|
|
26110
|
+
return (jsx(TooltipWrapper, { children: jsx(Button, { className: isMobile ? 'w-full' : '', disabled: disabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
26111
|
+
};
|
|
26112
|
+
|
|
26113
|
+
const CheckoutPrice_QuoteFragment = t(`
|
|
26114
|
+
fragment CheckoutPrice_QuoteFragment on Quote {
|
|
26115
|
+
periodAmount
|
|
26116
|
+
amountDue
|
|
26117
|
+
quoteChanges {
|
|
26118
|
+
charges {
|
|
26119
|
+
kind
|
|
26120
|
+
chargeType
|
|
26121
|
+
}
|
|
26122
|
+
}
|
|
26323
26123
|
}
|
|
26324
|
-
|
|
26325
|
-
|
|
26326
|
-
|
|
26124
|
+
`);
|
|
26125
|
+
// if there are any charges on the subscribe quote change
|
|
26126
|
+
const CheckoutPrice = ({ quote: maskedQuote, selectedPriceList, }) => {
|
|
26127
|
+
var _a, _b;
|
|
26327
26128
|
// Read fragments
|
|
26328
|
-
const
|
|
26329
|
-
|
|
26330
|
-
|
|
26331
|
-
|
|
26332
|
-
|
|
26333
|
-
|
|
26334
|
-
|
|
26335
|
-
|
|
26336
|
-
|
|
26337
|
-
|
|
26338
|
-
|
|
26339
|
-
|
|
26340
|
-
}
|
|
26341
|
-
return 0;
|
|
26342
|
-
};
|
|
26343
|
-
const priceDecimals = calculatePriceDecimals();
|
|
26344
|
-
const price = !((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.pricingStyle) ||
|
|
26345
|
-
((_b = priceList.plan) === null || _b === void 0 ? void 0 : _b.pricingStyle) === t.scalar('PlanPricingStyles', 'PRICED')
|
|
26346
|
-
? formatCurrency(getPrice(priceList), priceList.currencyId, priceDecimals)
|
|
26347
|
-
: ((_c = priceList.plan) === null || _c === void 0 ? void 0 : _c.pricingStyle) === t.scalar('PlanPricingStyles', 'CONTACT_US')
|
|
26348
|
-
? 'Custom'
|
|
26349
|
-
: 'Free';
|
|
26350
|
-
return price;
|
|
26351
|
-
}
|
|
26129
|
+
const quote = readFragment(CheckoutPrice_QuoteFragment, maskedQuote);
|
|
26130
|
+
// Hooks
|
|
26131
|
+
const isMobile = useIsMobile();
|
|
26132
|
+
const displayAmount = (_a = quote === null || quote === void 0 ? void 0 : quote.amountDue) !== null && _a !== void 0 ? _a : quote === null || quote === void 0 ? void 0 : quote.periodAmount; // amountDue might not be available, so we use periodAmount as a fallback
|
|
26133
|
+
const hasDisplayAmount = selectedPriceList && displayAmount !== undefined;
|
|
26134
|
+
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
26135
|
+
const periodLabel = convertedPeriodMonths ? PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
26136
|
+
const subscribingToUsageCharges = (_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.some(qc => qc.charges.some(c => c.kind === 'SUBSCRIBE' && c.chargeType === 'USAGE'));
|
|
26137
|
+
return (jsxs("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: [subscribingToUsageCharges ? 'Usage based pricing' : '', subscribingToUsageCharges && hasDisplayAmount ? ' + ' : '', hasDisplayAmount
|
|
26138
|
+
? `${formatCurrency(displayAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, undefined)} / ${periodLabel}`
|
|
26139
|
+
: ''] }));
|
|
26140
|
+
};
|
|
26352
26141
|
|
|
26353
26142
|
const { Text: Text$9 } = Typography;
|
|
26354
|
-
const
|
|
26355
|
-
fragment
|
|
26356
|
-
|
|
26143
|
+
const CheckoutBarSummarySection_QuoteFragment = t(`
|
|
26144
|
+
fragment CheckoutBarSummarySection_QuoteFragment on Quote {
|
|
26145
|
+
quoteChanges {
|
|
26146
|
+
charges {
|
|
26147
|
+
id
|
|
26148
|
+
}
|
|
26149
|
+
}
|
|
26150
|
+
...CheckoutPrice_QuoteFragment
|
|
26357
26151
|
}
|
|
26358
|
-
`, [
|
|
26359
|
-
const
|
|
26360
|
-
|
|
26361
|
-
|
|
26362
|
-
|
|
26152
|
+
`, [CheckoutPrice_QuoteFragment]);
|
|
26153
|
+
const CheckoutBarSummarySection = ({ selectedPriceList, onClickCheckout, }) => {
|
|
26154
|
+
var _a;
|
|
26155
|
+
// Context
|
|
26156
|
+
const { quote: maskedQuote, isQuotePending, isUpdatingQuote } = useContext(QuoteContext);
|
|
26157
|
+
const quote = readFragment(CheckoutBarSummarySection_QuoteFragment, maskedQuote);
|
|
26158
|
+
const { isInPreviewMode } = useSubscriptionProps();
|
|
26159
|
+
// Hooks
|
|
26160
|
+
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
26161
|
+
const isMobile = useIsMobile();
|
|
26162
|
+
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
26163
|
+
const quoteHasCharges = Boolean((_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.some(qc => qc.charges.length > 0));
|
|
26164
|
+
const checkoutButtonDisabled = Boolean(!selectedPriceList || !quoteHasCharges || !hasPaymentPlugins || isInPreviewMode);
|
|
26165
|
+
return (jsxs(Text$9, { className: `bunny-flex bunny-items-center bunny-gap-4 ${isMobile ? 'bunny-flex-col' : ''}`, children: [quote && (jsxs("div", { className: `bunny-flex ${isMobile ? 'items-center justify-between w-full' : 'flex-col'}`, children: [jsx("div", { className: "bunny-text-slate-500 bunny-font-medium bunny-text-right", style: { fontSize: '11px' }, children: "TOTAL" }), jsx(CheckoutPrice, { quote: quote, selectedPriceList: selectedPriceList })] })), jsx(CheckoutButton, { disabled: checkoutButtonDisabled, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
26166
|
+
? 'Checkout is disabled in preview mode'
|
|
26167
|
+
: !hasPaymentPlugins
|
|
26168
|
+
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
26169
|
+
: undefined })] }));
|
|
26363
26170
|
};
|
|
26364
26171
|
|
|
26365
|
-
const
|
|
26366
|
-
|
|
26367
|
-
|
|
26368
|
-
|
|
26369
|
-
|
|
26370
|
-
|
|
26172
|
+
const accountQuery = (id) => `
|
|
26173
|
+
query account {
|
|
26174
|
+
account(id: ${id}) {
|
|
26175
|
+
billingCountry
|
|
26176
|
+
billingState
|
|
26177
|
+
billingStreet
|
|
26178
|
+
billingCity
|
|
26179
|
+
billingZip
|
|
26180
|
+
}
|
|
26181
|
+
}`;
|
|
26182
|
+
const getAccount$1 = async ({ id, apiHost, token, }) => {
|
|
26183
|
+
const response = await gqlRequest({
|
|
26184
|
+
query: accountQuery(id),
|
|
26185
|
+
token,
|
|
26186
|
+
apiHost,
|
|
26187
|
+
});
|
|
26188
|
+
return response === null || response === void 0 ? void 0 : response.account;
|
|
26371
26189
|
};
|
|
26372
26190
|
|
|
26373
|
-
const
|
|
26374
|
-
|
|
26375
|
-
|
|
26376
|
-
|
|
26377
|
-
|
|
26378
|
-
|
|
26379
|
-
|
|
26380
|
-
|
|
26191
|
+
const MUTATION = `{
|
|
26192
|
+
currentUser {
|
|
26193
|
+
taxationRequiredAccountFields
|
|
26194
|
+
}
|
|
26195
|
+
}`;
|
|
26196
|
+
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
26197
|
+
var _a, _b;
|
|
26198
|
+
const response = await gqlRequest({
|
|
26199
|
+
query: MUTATION,
|
|
26200
|
+
token,
|
|
26201
|
+
apiHost: apiHost,
|
|
26202
|
+
});
|
|
26203
|
+
return ((_b = (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.taxationRequiredAccountFields) === null || _b === void 0 ? void 0 : _b.length) > 0
|
|
26204
|
+
? response.currentUser.taxationRequiredAccountFields
|
|
26205
|
+
: null;
|
|
26381
26206
|
};
|
|
26382
26207
|
|
|
26383
|
-
const
|
|
26384
|
-
fragment
|
|
26208
|
+
const Checkout_QuoteFragment = t(`
|
|
26209
|
+
fragment Checkout_QuoteFragment on Quote {
|
|
26385
26210
|
id
|
|
26386
|
-
|
|
26387
|
-
|
|
26388
|
-
|
|
26389
|
-
pricingStyle
|
|
26390
|
-
contactUsUrl
|
|
26391
|
-
name
|
|
26392
|
-
}
|
|
26393
|
-
charges {
|
|
26394
|
-
id
|
|
26395
|
-
featureAddon
|
|
26396
|
-
priceListChargeTiers {
|
|
26397
|
-
starts
|
|
26398
|
-
price
|
|
26399
|
-
}
|
|
26400
|
-
...PricingTooltip_PriceListChargeFragment
|
|
26211
|
+
accountId
|
|
26212
|
+
formattedQuote {
|
|
26213
|
+
html
|
|
26401
26214
|
}
|
|
26402
|
-
|
|
26403
|
-
...PriceListCardButton_PriceListFragment
|
|
26404
|
-
...PriceListHasPriceTiers_PriceListFragment
|
|
26405
|
-
...PricingTooltip_PriceListFragment
|
|
26406
|
-
...PriceListCardPrice_PriceListFragment
|
|
26407
|
-
...PriceListCardPriceDescription_PriceListFragment
|
|
26215
|
+
...QuoteCheckout_QuoteFragment
|
|
26408
26216
|
}
|
|
26409
|
-
`, [
|
|
26410
|
-
|
|
26411
|
-
|
|
26412
|
-
|
|
26413
|
-
|
|
26414
|
-
|
|
26415
|
-
|
|
26416
|
-
|
|
26417
|
-
const
|
|
26418
|
-
var _a, _b, _c, _d;
|
|
26217
|
+
`, [QuoteCheckout_QuoteFragment]);
|
|
26218
|
+
const Checkout = ({ onCancel, onSuccess, onFail, onRecalculateTaxes, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
26219
|
+
var _a, _b, _c, _d, _e;
|
|
26220
|
+
const { apiHost } = useContext(BunnyContext);
|
|
26221
|
+
const isMobile = useIsMobile();
|
|
26222
|
+
const token = useToken();
|
|
26223
|
+
// Context
|
|
26224
|
+
const onPaymentMethodSaved = useOnPaymentMethodSaved();
|
|
26225
|
+
const onPaymentMethodRemoved = useOnPaymentMethodRemoved();
|
|
26419
26226
|
// Read fragments
|
|
26420
|
-
const
|
|
26421
|
-
|
|
26422
|
-
|
|
26423
|
-
|
|
26424
|
-
|
|
26425
|
-
|
|
26426
|
-
|
|
26427
|
-
|
|
26428
|
-
|
|
26429
|
-
|
|
26430
|
-
|
|
26431
|
-
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
|
|
26435
|
-
|
|
26436
|
-
|
|
26437
|
-
|
|
26227
|
+
const quote = readFragment(Checkout_QuoteFragment, maskedQuote);
|
|
26228
|
+
const hasTaxPlugin = useHasTaxPlugin({
|
|
26229
|
+
apiHost,
|
|
26230
|
+
token,
|
|
26231
|
+
});
|
|
26232
|
+
// Queries
|
|
26233
|
+
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = useQuery({
|
|
26234
|
+
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
26235
|
+
queryFn: () => getTaxationRequiredAccountFields({ apiHost, token }),
|
|
26236
|
+
enabled: Boolean(quote),
|
|
26237
|
+
staleTime: 0,
|
|
26238
|
+
});
|
|
26239
|
+
const { data: account, isLoading: isLoadingAccount } = useQuery({
|
|
26240
|
+
queryKey: ['account', quote === null || quote === void 0 ? void 0 : quote.accountId],
|
|
26241
|
+
queryFn: () => (quote === null || quote === void 0 ? void 0 : quote.accountId) && getAccount$1({ id: quote.accountId, apiHost, token }),
|
|
26242
|
+
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
26243
|
+
});
|
|
26244
|
+
// Use onRecalculateTaxes callback because parents need to define recalculateTaxes to get and set the right quote data they need
|
|
26245
|
+
async function recalculateTaxes() {
|
|
26246
|
+
if (quote) {
|
|
26247
|
+
if (!quote.id)
|
|
26248
|
+
throw new Error('Quote ID is required');
|
|
26249
|
+
onRecalculateTaxes(quote.id);
|
|
26250
|
+
}
|
|
26251
|
+
return {};
|
|
26252
|
+
}
|
|
26253
|
+
const recalculateTaxesEnabled = Boolean(quote) &&
|
|
26254
|
+
open &&
|
|
26255
|
+
hasTaxPlugin &&
|
|
26256
|
+
!taxationRequiredAccountFields &&
|
|
26257
|
+
!isLoadingTaxationRequiredAccountFields &&
|
|
26258
|
+
!isUpdatingQuote;
|
|
26259
|
+
useQuery({
|
|
26260
|
+
queryKey: QueryKeyFactory.createQuoteTaxCalculateKey({
|
|
26261
|
+
id: (_a = quote === null || quote === void 0 ? void 0 : quote.id) !== null && _a !== void 0 ? _a : undefined,
|
|
26262
|
+
token,
|
|
26263
|
+
}),
|
|
26264
|
+
queryFn: recalculateTaxes,
|
|
26265
|
+
// Recalculate taxes if the quote is open, has a tax plugin, and the taxation required account fields are not required
|
|
26266
|
+
enabled: recalculateTaxesEnabled,
|
|
26267
|
+
staleTime: 0,
|
|
26268
|
+
});
|
|
26269
|
+
if (!open || isLoadingTaxationRequiredAccountFields || isLoadingAccount)
|
|
26270
|
+
return null;
|
|
26271
|
+
return (jsx("div", { className: `bunny-flex bunny-flex-col bunny-fixed bunny-top-0 bunny-left-0 bunny-right-0 bunny-bottom-0 bunny-bg-slate-50
|
|
26272
|
+
bunny-overflow-auto bunny-height-full`, style: {
|
|
26273
|
+
zIndex: 1001,
|
|
26274
|
+
}, children: jsxs("div", { className: `bunny-flex bunny-flex-col bunny-grow bunny-pt-4 ${isMobile ? 'bunny-pb-4' : 'bunny-pb-8'} bunny-content-container`, children: [jsx("div", { className: "bunny-flex bunny-justify-end bunny-w-full bunny-pr-4", children: jsx(CloseOutlined, { className: "bunny-text-base bunny-shadow-padding-xb", onClick: onCancel }) }), jsxs("div", { className: `bunny-flex bunny-justify-end bunny-pt-4 bunny-gap-4 ${isMobile ? 'bunny-flex-col' : 'bunny-shadow-padding-xb'}`, children: [((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_b = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _b === void 0 ? void 0 : _b.html)) && (jsx(InvoiceQuoteView, { html: invoice ? invoice.html : (_d = (_c = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _c === void 0 ? void 0 : _c.html) !== null && _d !== void 0 ? _d : '' })), !isMobile && ((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_e = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _e === void 0 ? void 0 : _e.html)) && (jsx(Divider, { className: "bunny-h-full", type: "vertical" })), invoice ? (jsx("div", { className: "bunny-w-full bunny-pt-12", children: jsx(PaymentForm, { onPaymentSuccess: onSuccess, invoice: invoice, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }) })) : quote ? (jsx(QuoteCheckout, { account: account, onFail: error => {
|
|
26275
|
+
onFail(error);
|
|
26276
|
+
}, onSuccess: onSuccess, quote: quote, taxationRequiredAccountFields: taxationRequiredAccountFields, token: token, onRecalculateTaxes: async () => {
|
|
26277
|
+
if (recalculateTaxesEnabled) {
|
|
26278
|
+
await recalculateTaxes();
|
|
26279
|
+
}
|
|
26280
|
+
} })) : (jsx(PaymentForm, { onPaymentSuccess: onSuccess, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id) }))] }), jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
26438
26281
|
};
|
|
26439
26282
|
|
|
26440
|
-
|
|
26441
|
-
|
|
26283
|
+
function canEditChargeQuantity(charge) {
|
|
26284
|
+
if (!charge)
|
|
26285
|
+
return false;
|
|
26286
|
+
if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
|
|
26287
|
+
return false;
|
|
26288
|
+
if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
|
|
26289
|
+
return false;
|
|
26290
|
+
return true;
|
|
26291
|
+
}
|
|
26292
|
+
|
|
26293
|
+
const { Text: Text$8 } = Typography;
|
|
26294
|
+
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
26295
|
+
var _a;
|
|
26296
|
+
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
|
|
26297
|
+
const isMobile = useIsMobile();
|
|
26298
|
+
useEffect(() => {
|
|
26299
|
+
setTimeout(() => {
|
|
26300
|
+
setIsTooltipOpen(true);
|
|
26301
|
+
}, 1000);
|
|
26302
|
+
setTimeout(() => {
|
|
26303
|
+
setIsTooltipOpen(false);
|
|
26304
|
+
}, 6000);
|
|
26305
|
+
}, []);
|
|
26306
|
+
return (jsxs(Text$8, { className: `bunny-flex bunny-items-center bunny-gap-2 ${isMobile ? 'bunny-justify-between' : ''}`, children: [jsx(QuantityLabel, { activeCharge: priceListCharge }), jsx(Tooltip, { onOpenChange: setIsTooltipOpen, open: isTooltipOpen, title: "Change quantity here", styles: {
|
|
26307
|
+
body: {
|
|
26308
|
+
paddingTop: '0.75rem',
|
|
26309
|
+
paddingBottom: '0.75rem',
|
|
26310
|
+
},
|
|
26311
|
+
}, children: jsx(Input, { id: `${(_a = priceListCharge.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().replace(/ /g, '-')}-quantity-input`, className: isMobile ? 'text-right' : '', disabled: disabled, onChange: e => {
|
|
26312
|
+
onQuantityChanged(Number(e.target.value));
|
|
26313
|
+
}, min: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMin, max: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMax, style: { minWidth: '120px' }, type: "number", value: quantity, required: true }) })] }));
|
|
26314
|
+
};
|
|
26315
|
+
const QuantityLabel = ({ activeCharge }) => {
|
|
26316
|
+
const chargeName = activeCharge.name;
|
|
26317
|
+
return (jsx(Text$8, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
26442
26318
|
};
|
|
26443
26319
|
|
|
26444
|
-
const
|
|
26445
|
-
fragment
|
|
26446
|
-
|
|
26447
|
-
|
|
26320
|
+
const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
26321
|
+
fragment PlanPickerCheckoutBar_QuoteFragment on Quote {
|
|
26322
|
+
...Checkout_QuoteFragment
|
|
26323
|
+
quoteChanges {
|
|
26324
|
+
priceList {
|
|
26325
|
+
id
|
|
26326
|
+
}
|
|
26327
|
+
charges {
|
|
26328
|
+
priceListCharge {
|
|
26329
|
+
id
|
|
26330
|
+
}
|
|
26331
|
+
}
|
|
26448
26332
|
}
|
|
26449
|
-
...PriceListCardPriceDescription_PriceListFragment
|
|
26450
|
-
...PriceListCardButton_PriceListFragment
|
|
26451
|
-
...PriceListCardPrice_PriceListFragment
|
|
26452
|
-
...PriceListCardButton_PriceListFragment
|
|
26453
26333
|
}
|
|
26454
|
-
`, [
|
|
26455
|
-
|
|
26456
|
-
PriceListCardButton_PriceListFragment,
|
|
26457
|
-
PriceListCardPrice_PriceListFragment,
|
|
26458
|
-
PriceListCardButton_PriceListFragment,
|
|
26459
|
-
]);
|
|
26460
|
-
const PriceListCardMobile = ({ description, feature, isPriceListCurrentSubscription, isSelected, priceList: maskedPriceList, subscriptionPlan, trialRemainingDays, disableOnClickPriceListCard, onClickPriceListCard, }) => {
|
|
26461
|
-
var _a, _b;
|
|
26334
|
+
`, [Checkout_QuoteFragment]);
|
|
26335
|
+
const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onCheckoutSuccess, }) => {
|
|
26462
26336
|
// Context
|
|
26463
|
-
const {
|
|
26337
|
+
const { shadow, isInPreviewMode } = useSubscriptionProps();
|
|
26338
|
+
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, onRecalculateTaxes, isFeatureAddonsLoading, isUpdatingQuote, } = useContext(QuoteContext);
|
|
26464
26339
|
// Read fragments
|
|
26465
|
-
const
|
|
26466
|
-
|
|
26467
|
-
|
|
26468
|
-
|
|
26469
|
-
|
|
26470
|
-
|
|
26471
|
-
|
|
26472
|
-
|
|
26473
|
-
|
|
26474
|
-
|
|
26475
|
-
|
|
26340
|
+
const quote = readFragment(PlanPickerCheckoutBar_QuoteFragment, maskedQuote);
|
|
26341
|
+
// Local state
|
|
26342
|
+
const [payModalVisible, setPayModalVisible] = useState(false);
|
|
26343
|
+
// Hooks
|
|
26344
|
+
const token = useToken();
|
|
26345
|
+
const showSuccessNotification = useSuccessNotification();
|
|
26346
|
+
const queryClient = useQueryClient();
|
|
26347
|
+
const isMobile = useIsMobile();
|
|
26348
|
+
const handleCheckoutSuccess = () => {
|
|
26349
|
+
queryClient.refetchQueries({
|
|
26350
|
+
queryKey: QueryKeyFactory.createTableKey({
|
|
26351
|
+
pluralType: 'subscriptions',
|
|
26352
|
+
token,
|
|
26353
|
+
}),
|
|
26354
|
+
});
|
|
26355
|
+
queryClient.invalidateQueries({
|
|
26356
|
+
queryKey: QueryKeyFactory.createTableKey({
|
|
26357
|
+
pluralType: 'upgradeSubscriptions',
|
|
26358
|
+
token,
|
|
26359
|
+
}),
|
|
26360
|
+
});
|
|
26361
|
+
queryClient.invalidateQueries({
|
|
26362
|
+
queryKey: QueryKeyFactory.createTableKey({
|
|
26363
|
+
pluralType: 'hasActiveSubscriptions',
|
|
26364
|
+
token,
|
|
26365
|
+
}),
|
|
26366
|
+
});
|
|
26367
|
+
queryClient.invalidateQueries({
|
|
26368
|
+
queryKey: QueryKeyFactory.transactionsKey({ token }),
|
|
26369
|
+
});
|
|
26370
|
+
setPayModalVisible(false);
|
|
26371
|
+
showSuccessNotification('Your subscription has been created', 'Checkout successful');
|
|
26372
|
+
onCheckoutSuccess();
|
|
26373
|
+
};
|
|
26374
|
+
return (jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-4' : 'bunny-flex-row'} bunny-my-4 bunny-p-4 bunny-justify-between bunny-bg-white bunny-rounded-md ${shadow ? `shadow-${shadow}` : ''}`, children: [jsx("div", { className: `${isMobile ? 'bunny-flex bunny-flex-col' : 'bunny-flex'} bunny-gap-4`, children: selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.charges.map((charge, index) => {
|
|
26375
|
+
var _a, _b, _c, _d;
|
|
26376
|
+
if (!canEditChargeQuantity({
|
|
26377
|
+
chargeType: (_a = charge.chargeType) !== null && _a !== void 0 ? _a : null,
|
|
26378
|
+
pricingModel: (_b = charge.pricingModel) !== null && _b !== void 0 ? _b : null,
|
|
26379
|
+
}))
|
|
26380
|
+
return null;
|
|
26381
|
+
if (!((_c = charge.feature) === null || _c === void 0 ? void 0 : _c.id))
|
|
26382
|
+
throw new Error('Charge feature is undefined');
|
|
26383
|
+
const isFeatureAddon = charge.featureAddon;
|
|
26384
|
+
const quantity = getFeatureQuantity((_d = charge.feature) === null || _d === void 0 ? void 0 : _d.id, charge.id);
|
|
26385
|
+
const maybeIsChargeLoading = isFeatureAddon && isFeatureAddonsLoading;
|
|
26386
|
+
if (!quantity)
|
|
26387
|
+
return null;
|
|
26388
|
+
// if charge is a feature addon, and a corresponding quote charge is not found in quote, return null
|
|
26389
|
+
if (isFeatureAddon && !featureAddonInQuote(selectedPriceList, charge, quote)) {
|
|
26390
|
+
return null;
|
|
26391
|
+
}
|
|
26392
|
+
const isDisabled = !quote || maybeIsChargeLoading || !selectedPriceList || !charge.selfServiceQuantity;
|
|
26393
|
+
return (jsx(CheckoutBarInput, { disabled: isDisabled, priceListCharge: charge, quantity: quantity, onQuantityChanged: quantity => {
|
|
26394
|
+
if (isInPreviewMode)
|
|
26395
|
+
return;
|
|
26396
|
+
onChangeQuantity(charge.id, quantity);
|
|
26397
|
+
} }, index));
|
|
26398
|
+
}) }), jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true), selectedPriceList: selectedPriceList }), jsx(Checkout, { onCancel: () => setPayModalVisible(false), onFail: error => handlePortalErrors === null || handlePortalErrors === void 0 ? void 0 : handlePortalErrors(error), onSuccess: handleCheckoutSuccess, onRecalculateTaxes: onRecalculateTaxes, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: isUpdatingQuote })] }));
|
|
26476
26399
|
};
|
|
26477
26400
|
|
|
26478
|
-
const
|
|
26479
|
-
fragment
|
|
26401
|
+
const useQuoteUpdateFeatureAddon_QuoteFragment = t(`
|
|
26402
|
+
fragment useQuoteUpdateFeatureAddon_QuoteFragment on Quote {
|
|
26480
26403
|
id
|
|
26481
|
-
|
|
26482
|
-
|
|
26404
|
+
startDate
|
|
26405
|
+
}
|
|
26406
|
+
`);
|
|
26407
|
+
|
|
26408
|
+
const FeatureAddonRow_QuoteFragment = t(`
|
|
26409
|
+
fragment FeatureAddonRow_QuoteFragment on Quote {
|
|
26410
|
+
...useQuoteUpdateFeatureAddon_QuoteFragment
|
|
26411
|
+
}
|
|
26412
|
+
`, [useQuoteUpdateFeatureAddon_QuoteFragment]);
|
|
26413
|
+
|
|
26414
|
+
const useToggleAddonPlan_QuoteFragment = t(`
|
|
26415
|
+
fragment useToggleAddonPlan_QuoteFragment on Quote {
|
|
26416
|
+
quoteChanges {
|
|
26417
|
+
priceList {
|
|
26418
|
+
id
|
|
26419
|
+
}
|
|
26483
26420
|
id
|
|
26484
26421
|
}
|
|
26485
|
-
|
|
26486
|
-
...PriceListCardMobile_PriceListFragment
|
|
26422
|
+
id
|
|
26487
26423
|
}
|
|
26488
|
-
|
|
26489
|
-
|
|
26490
|
-
|
|
26491
|
-
|
|
26492
|
-
|
|
26493
|
-
// Read fragments
|
|
26494
|
-
const priceList = readFragment(PriceListCard_PriceListFragment, maskedPriceList);
|
|
26495
|
-
// Derived state
|
|
26496
|
-
const description = createPlanDescription((_b = (_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.description) !== null && _b !== void 0 ? _b : '');
|
|
26497
|
-
// Get the active price list charge for this plan
|
|
26498
|
-
const activeCharge = (_c = getActivePlanPriceData(priceList, priceList)) === null || _c === void 0 ? void 0 : _c.activeCharge;
|
|
26499
|
-
// Is the price list the current price list for the upgradingSubscription
|
|
26500
|
-
const isPriceListCurrentSubscription = ((_d = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) === null || _d === void 0 ? void 0 : _d.id) === priceList.id;
|
|
26501
|
-
const disableSelectCurrentPlan = disableCurrentPlan !== null && disableCurrentPlan !== void 0 ? disableCurrentPlan : isPriceListDisabled({
|
|
26502
|
-
priceList: priceList,
|
|
26503
|
-
upgradingSubscription: upgradingSubscription, // TODO: set type properly later
|
|
26504
|
-
});
|
|
26505
|
-
const subscriptionPlan = subscriptions === null || subscriptions === void 0 ? void 0 : subscriptions.find(subscription => {
|
|
26506
|
-
var _a, _b;
|
|
26507
|
-
return subscription.plan.id === ((_a = priceList.plan) === null || _a === void 0 ? void 0 : _a.id) &&
|
|
26508
|
-
subscription.state !== t.scalar('SubscriptionState', 'CANCELED') &&
|
|
26509
|
-
subscription.state !== t.scalar('SubscriptionState', 'EXPIRED') &&
|
|
26510
|
-
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
26511
|
-
});
|
|
26512
|
-
if (!activeCharge) {
|
|
26513
|
-
return null;
|
|
26424
|
+
`);
|
|
26425
|
+
|
|
26426
|
+
const AddonPlanRow_QuoteFragment = t(`
|
|
26427
|
+
fragment AddonPlanRow_QuoteFragment on Quote {
|
|
26428
|
+
...useToggleAddonPlan_QuoteFragment
|
|
26514
26429
|
}
|
|
26515
|
-
|
|
26516
|
-
return isMobile ? (jsx(PriceListCardMobile, { description: description, feature: feature, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, trialRemainingDays: trialRemainingDays, subscriptionPlan: subscriptionPlan,
|
|
26517
|
-
// TODO: naming mismatch disableOnClickPriceListCard vs disableSelectCurrentPlan, maybe also functionality mismatch? (ignore for now, mobile won't ever show this currently)
|
|
26518
|
-
disableOnClickPriceListCard: disableSelectCurrentPlan, onClickPriceListCard: onClickPriceListCard })) : (jsx(PriceListCardDesktop, { hideButton: hideButton, description: description, disableSelectCurrentPlan: disableSelectCurrentPlan, feature: feature, isPriceListCurrentSubscription: isPriceListCurrentSubscription, isSelected: isSelected, priceList: priceList, trialRemainingDays: trialRemainingDays, subscriptionPlan: subscriptionPlan, noBorder: noBorder, onClickPriceListCard: onClickPriceListCard }));
|
|
26519
|
-
};
|
|
26430
|
+
`, [useToggleAddonPlan_QuoteFragment]);
|
|
26520
26431
|
|
|
26521
|
-
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26525
|
-
|
|
26526
|
-
|
|
26527
|
-
|
|
26528
|
-
|
|
26529
|
-
|
|
26530
|
-
|
|
26531
|
-
|
|
26532
|
-
|
|
26432
|
+
/**
|
|
26433
|
+
* Central quote fragment for QuoteProvider context.
|
|
26434
|
+
*
|
|
26435
|
+
* This fragment aggregates all child component fragments to ensure the QuoteProvider
|
|
26436
|
+
* fetches all required quote data upfront. When a component needs specific quote fields,
|
|
26437
|
+
* add its fragment here to maintain type safety and avoid over-fetching.
|
|
26438
|
+
*
|
|
26439
|
+
* Pattern: Fragment Composition
|
|
26440
|
+
* - Components define their data needs via fragments
|
|
26441
|
+
* - Provider composes these fragments into a single query
|
|
26442
|
+
* - Type safety ensures all required fields are fetched
|
|
26443
|
+
*/
|
|
26444
|
+
const QuoteContext_QuoteFragment = t(`
|
|
26445
|
+
fragment QuoteContext_QuoteFragment on Quote {
|
|
26446
|
+
id
|
|
26447
|
+
currencyId
|
|
26448
|
+
amountDue
|
|
26449
|
+
startDate
|
|
26450
|
+
quoteChanges {
|
|
26451
|
+
id
|
|
26452
|
+
kind
|
|
26453
|
+
priceList {
|
|
26454
|
+
id
|
|
26455
|
+
}
|
|
26456
|
+
charges {
|
|
26457
|
+
priceListCharge {
|
|
26458
|
+
id
|
|
26459
|
+
chargeType
|
|
26460
|
+
pricingModel
|
|
26461
|
+
quantityMin
|
|
26462
|
+
quantityMax
|
|
26463
|
+
selfServiceQuantity
|
|
26464
|
+
}
|
|
26465
|
+
feature {
|
|
26466
|
+
id
|
|
26467
|
+
}
|
|
26468
|
+
quantity
|
|
26469
|
+
id
|
|
26470
|
+
}
|
|
26471
|
+
}
|
|
26472
|
+
...PlanPickerCheckoutBar_QuoteFragment
|
|
26473
|
+
...CheckoutBarSummarySection_QuoteFragment
|
|
26474
|
+
...AddonPlanRow_QuoteFragment
|
|
26475
|
+
...FeatureAddonRow_QuoteFragment
|
|
26476
|
+
...PaymentForms_QuoteFragment
|
|
26477
|
+
}
|
|
26478
|
+
`, [
|
|
26479
|
+
PlanPickerCheckoutBar_QuoteFragment,
|
|
26480
|
+
CheckoutBarSummarySection_QuoteFragment,
|
|
26481
|
+
AddonPlanRow_QuoteFragment,
|
|
26482
|
+
FeatureAddonRow_QuoteFragment,
|
|
26483
|
+
PaymentForms_QuoteFragment,
|
|
26484
|
+
]);
|
|
26533
26485
|
|
|
26534
26486
|
const mutation$c = t(`
|
|
26535
26487
|
mutation QuoteChargeDelete($quoteChargeId: ID!) {
|
|
@@ -27126,7 +27078,11 @@ function AddonPlanRow({ addonPriceList: maskedAddonPriceList, selectedPriceList,
|
|
|
27126
27078
|
// Derived state
|
|
27127
27079
|
const switchDisabled = isInPreviewMode || isPurchased;
|
|
27128
27080
|
const hasCustomPrice = ((_b = addonPriceList.plan) === null || _b === void 0 ? void 0 : _b.pricingDescription) != null;
|
|
27129
|
-
return (jsxs("div", { className: `bunny-flex bunny-flex-row bunny-gap-2 bunny-justify-between bunny-items-center bunny-p-4 bunny-rounded-md bunny-bg-white ${shadow ? `shadow-${shadow}` : ''} bunny-mb-2`, children: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx("div", { className: `bunny-font-medium bunny-text-center bunny-text-orange-600`, children: (_c = addonPriceList.plan) === null || _c === void 0 ? void 0 : _c.name }), jsx(PriceListCardDescription, { description: (_e = (_d = addonPriceList.plan) === null || _d === void 0 ? void 0 : _d.description) !== null && _e !== void 0 ? _e : '' }), !hasCustomPrice && (jsx(PriceListCardPrice, { priceList: addonPriceList, className: "bunny-text-sm bunny-font-medium bunny-text-gray-900" })), jsx(PriceListCardPriceDescription, { feature: activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.feature, priceList: addonPriceList }), jsx(Button, { type: "link", onClick:
|
|
27081
|
+
return (jsxs("div", { className: `bunny-flex bunny-flex-row bunny-gap-2 bunny-justify-between bunny-items-center bunny-p-4 bunny-rounded-md bunny-bg-white ${shadow ? `shadow-${shadow}` : ''} bunny-mb-2`, children: [jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsx("div", { className: `bunny-font-medium bunny-text-center bunny-text-orange-600`, children: (_c = addonPriceList.plan) === null || _c === void 0 ? void 0 : _c.name }), jsx(PriceListCardDescription, { description: (_e = (_d = addonPriceList.plan) === null || _d === void 0 ? void 0 : _d.description) !== null && _e !== void 0 ? _e : '' }), !hasCustomPrice && (jsx(PriceListCardPrice, { priceList: addonPriceList, className: "bunny-text-sm bunny-font-medium bunny-text-gray-900" })), jsx(PriceListCardPriceDescription, { feature: activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.feature, priceList: addonPriceList }), jsx(Button, { type: "link", onClick: () => {
|
|
27082
|
+
if (isInPreviewMode)
|
|
27083
|
+
return;
|
|
27084
|
+
onClickSelect();
|
|
27085
|
+
}, children: jsx(InfoCircleOutlined, {}) })] }), jsx(Switch, { id: addonPlanSwitchTestId((_g = (_f = addonPriceList.plan) === null || _f === void 0 ? void 0 : _f.name) !== null && _g !== void 0 ? _g : ''), loading: isPending && !switchDisabled, checked: addedQuoteChange || isPurchased, onChange: (checked) => {
|
|
27130
27086
|
if (checked) {
|
|
27131
27087
|
addAddonQuoteChange();
|
|
27132
27088
|
}
|
|
@@ -29273,7 +29229,8 @@ const UpgradeWrapper = ({ onChangePlanCancel, handlePortalErrors, upgradingSubsc
|
|
|
29273
29229
|
pluralType: 'upgradeSubscriptions',
|
|
29274
29230
|
token,
|
|
29275
29231
|
}),
|
|
29276
|
-
queryFn: () => getSubscriptions({
|
|
29232
|
+
queryFn: () => getSubscriptions({ token, apiHost, isInPreviewMode }),
|
|
29233
|
+
enabled: !isInPreviewMode, // Don't query subscriptions in preview mode
|
|
29277
29234
|
});
|
|
29278
29235
|
// find upgrading subscription based on upgradingSubscriptionId
|
|
29279
29236
|
const upgradingSubscription = (_b = (_a = subscriptionsData === null || subscriptionsData === void 0 ? void 0 : subscriptionsData.subscriptions) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.find(subscription => (subscription === null || subscription === void 0 ? void 0 : subscription.id) === upgradingSubscriptionId);
|
|
@@ -29336,7 +29293,8 @@ const SubscriptionsWrapper = ({ handlePortalErrors, companyName, isInPreviewMode
|
|
|
29336
29293
|
pluralType: 'subscriptions',
|
|
29337
29294
|
token,
|
|
29338
29295
|
}),
|
|
29339
|
-
queryFn: () => getSubscriptions$1({ token, apiHost }),
|
|
29296
|
+
queryFn: () => getSubscriptions$1({ token, apiHost, isInPreviewMode }),
|
|
29297
|
+
enabled: !isInPreviewMode, // Don't query subscriptions in preview mode
|
|
29340
29298
|
});
|
|
29341
29299
|
const subscriptions = (_b = (_a = subscriptionsData === null || subscriptionsData === void 0 ? void 0 : subscriptionsData.subscriptions) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.filter(subscription => subscription !== null);
|
|
29342
29300
|
const defaultStyles = {
|