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