@bunnyapp/components 1.8.0-beta.8 → 1.8.0-beta.9
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 +1015 -943
- package/dist/cjs/types/src/components/PaymentForm/DemoPay/DemoPayFormProvider.d.ts +10 -0
- package/dist/cjs/types/src/components/PaymentForm/DemoPay/hooks/usePay.d.ts +2 -4
- package/dist/cjs/types/src/components/PaymentForm/DemoPay/hooks/useSave.d.ts +1 -5
- package/dist/cjs/types/src/components/PaymentForm/PaymentForm.d.ts +40 -9
- package/dist/cjs/types/src/components/PaymentForm/Stripe/StripeFormProvider.d.ts +5 -0
- package/dist/cjs/types/src/components/PaymentForm/Stripe/hooks/usePay.d.ts +2 -4
- package/dist/cjs/types/src/components/PaymentForm/components/CheckoutNoPayment.d.ts +6 -0
- package/dist/cjs/types/src/components/PaymentForm/components/Pay.d.ts +5 -0
- package/dist/cjs/types/src/components/PaymentForm/components/PaymentMethodDetails/PaymentMethodDetails.d.ts +12 -0
- package/dist/cjs/types/src/components/PaymentForm/components/PaymentMethodDetails/components/Cancel.d.ts +1 -0
- package/dist/cjs/types/src/components/PaymentForm/components/PaymentMethodDetails/components/Save.d.ts +1 -0
- package/dist/cjs/types/src/components/PaymentForm/components/StoredPaymentMethods.d.ts +18 -0
- package/dist/cjs/types/src/components/PaymentForm/context/AccountIdContext.d.ts +5 -0
- package/dist/cjs/types/src/components/PaymentForm/context/CallbacksContext.d.ts +14 -0
- package/dist/cjs/types/src/components/PaymentForm/context/PaymentMethodFormVisibilityContext.d.ts +12 -0
- package/dist/cjs/types/src/components/PaymentForm/context/PaymentProvider.d.ts +46 -37
- package/dist/cjs/types/src/components/PaymentForm/hooks/usePay.d.ts +14 -0
- package/dist/cjs/types/src/components/PaymentForm/hooks/usePaymentButtonText.d.ts +7 -1
- package/dist/cjs/types/src/components/PaymentForm/hooks/usePaymentHold.d.ts +18 -0
- package/dist/cjs/types/src/components/PaymentForm/hooks/useSave.d.ts +16 -0
- package/dist/cjs/types/src/components/PaymentForm/types/PaymentType.d.ts +2 -1
- package/dist/cjs/types/src/hooks/usePaymentMethod.d.ts +4 -0
- package/dist/esm/index.js +1019 -947
- package/dist/esm/types/src/components/PaymentForm/DemoPay/DemoPayFormProvider.d.ts +10 -0
- package/dist/esm/types/src/components/PaymentForm/DemoPay/hooks/usePay.d.ts +2 -4
- package/dist/esm/types/src/components/PaymentForm/DemoPay/hooks/useSave.d.ts +1 -5
- package/dist/esm/types/src/components/PaymentForm/PaymentForm.d.ts +40 -9
- package/dist/esm/types/src/components/PaymentForm/Stripe/StripeFormProvider.d.ts +5 -0
- package/dist/esm/types/src/components/PaymentForm/Stripe/hooks/usePay.d.ts +2 -4
- package/dist/esm/types/src/components/PaymentForm/components/CheckoutNoPayment.d.ts +6 -0
- package/dist/esm/types/src/components/PaymentForm/components/Pay.d.ts +5 -0
- package/dist/esm/types/src/components/PaymentForm/components/PaymentMethodDetails/PaymentMethodDetails.d.ts +12 -0
- package/dist/esm/types/src/components/PaymentForm/components/PaymentMethodDetails/components/Cancel.d.ts +1 -0
- package/dist/esm/types/src/components/PaymentForm/components/PaymentMethodDetails/components/Save.d.ts +1 -0
- package/dist/esm/types/src/components/PaymentForm/components/StoredPaymentMethods.d.ts +18 -0
- package/dist/esm/types/src/components/PaymentForm/context/AccountIdContext.d.ts +5 -0
- package/dist/esm/types/src/components/PaymentForm/context/CallbacksContext.d.ts +14 -0
- package/dist/esm/types/src/components/PaymentForm/context/PaymentMethodFormVisibilityContext.d.ts +12 -0
- package/dist/esm/types/src/components/PaymentForm/context/PaymentProvider.d.ts +46 -37
- package/dist/esm/types/src/components/PaymentForm/hooks/usePay.d.ts +14 -0
- package/dist/esm/types/src/components/PaymentForm/hooks/usePaymentButtonText.d.ts +7 -1
- package/dist/esm/types/src/components/PaymentForm/hooks/usePaymentHold.d.ts +18 -0
- package/dist/esm/types/src/components/PaymentForm/hooks/useSave.d.ts +16 -0
- package/dist/esm/types/src/components/PaymentForm/types/PaymentType.d.ts +2 -1
- package/dist/esm/types/src/hooks/usePaymentMethod.d.ts +4 -0
- package/dist/index.d.ts +64 -9
- package/package.json +1 -1
- package/dist/cjs/types/src/components/PaymentForm/components/CheckoutFooter.d.ts +0 -2
- package/dist/cjs/types/src/components/PaymentForm/components/PaymentMethodDetails.d.ts +0 -2
- package/dist/cjs/types/src/components/PaymentForm/components/PaymentMethodFooter.d.ts +0 -4
- package/dist/cjs/types/src/components/PaymentForm/hooks/useHandlePayment.d.ts +0 -41
- package/dist/esm/types/src/components/PaymentForm/components/CheckoutFooter.d.ts +0 -2
- package/dist/esm/types/src/components/PaymentForm/components/PaymentMethodDetails.d.ts +0 -2
- package/dist/esm/types/src/components/PaymentForm/components/PaymentMethodFooter.d.ts +0 -4
- package/dist/esm/types/src/components/PaymentForm/hooks/useHandlePayment.d.ts +0 -41
- /package/dist/cjs/types/src/components/PaymentForm/components/{PaymentMethodSelector.d.ts → PaymentMethodDetails/components/PaymentMethodSelector.d.ts} +0 -0
- /package/dist/esm/types/src/components/PaymentForm/components/{PaymentMethodSelector.d.ts → PaymentMethodDetails/components/PaymentMethodSelector.d.ts} +0 -0
package/dist/esm/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { useState, useEffect, isValidElement, createContext, useContext, useMemo,
|
|
2
|
+
import { useState, useEffect, isValidElement, createContext, useContext, useMemo, useCallback, useRef, createElement, Fragment as Fragment$1 } from 'react';
|
|
3
3
|
import { WarningOutlined, CheckCircleOutlined, CreditCardOutlined, EllipsisOutlined, BankOutlined, DownloadOutlined, SearchOutlined, CheckCircleFilled, LoadingOutlined, InfoCircleOutlined, CloseOutlined } from '@ant-design/icons';
|
|
4
|
-
import { notification, theme, ConfigProvider, Tag, Button, Dropdown, Typography, Input, Modal, Checkbox,
|
|
5
|
-
import { QueryClient, MutationCache, QueryCache, QueryClientProvider, useQuery,
|
|
4
|
+
import { notification, theme, ConfigProvider, Tag, Button, Dropdown, Typography, Skeleton, Input, Modal, Checkbox, Collapse, Spin, Form, Tooltip as Tooltip$1, Drawer, Card as Card$1, Divider, Select, Popconfirm, Table, Radio, Space, Switch } from 'antd';
|
|
5
|
+
import { QueryClient, MutationCache, QueryCache, QueryClientProvider, useQuery, useQueryClient, useMutation, keepPreviousData, useIsMutating, useIsFetching } from '@tanstack/react-query';
|
|
6
6
|
import request$1 from 'graphql-request';
|
|
7
7
|
import { RecoilRoot } from 'recoil';
|
|
8
8
|
import { print } from 'graphql';
|
|
9
|
-
import { useElements, useStripe,
|
|
9
|
+
import { Elements, useElements, useStripe, PaymentElement } from '@stripe/react-stripe-js';
|
|
10
10
|
import { loadStripe } from '@stripe/stripe-js/pure/index.js';
|
|
11
11
|
import styled, { styled as styled$1 } from 'styled-components';
|
|
12
12
|
import { Markup } from 'interweave';
|
|
@@ -1281,7 +1281,7 @@ const DEFAULT_CONFIG = {
|
|
|
1281
1281
|
};
|
|
1282
1282
|
|
|
1283
1283
|
// This will be replaced at build time by rollup-plugin-replace
|
|
1284
|
-
const PACKAGE_VERSION = '1.8.0-beta.
|
|
1284
|
+
const PACKAGE_VERSION = '1.8.0-beta.8';
|
|
1285
1285
|
const createRequestHeaders = (token) => {
|
|
1286
1286
|
const headers = createClientDevHeaders({ token });
|
|
1287
1287
|
// Add the components version header
|
|
@@ -19843,60 +19843,6 @@ const PaymentForm_PaymentMethodsFragment = t(`
|
|
|
19843
19843
|
}
|
|
19844
19844
|
`, [MiniCreditCard_PaymentMethodFragment]);
|
|
19845
19845
|
|
|
19846
|
-
const query$9 = t(`
|
|
19847
|
-
query PaymentMethods($accountId: ID) {
|
|
19848
|
-
paymentMethods(accountId: $accountId) {
|
|
19849
|
-
nodes {
|
|
19850
|
-
id
|
|
19851
|
-
pluginId
|
|
19852
|
-
accountId
|
|
19853
|
-
expirationDate
|
|
19854
|
-
plugin {
|
|
19855
|
-
guid
|
|
19856
|
-
id
|
|
19857
|
-
}
|
|
19858
|
-
state
|
|
19859
|
-
metadata {
|
|
19860
|
-
issuer
|
|
19861
|
-
identifier
|
|
19862
|
-
kind
|
|
19863
|
-
description
|
|
19864
|
-
icon
|
|
19865
|
-
type
|
|
19866
|
-
}
|
|
19867
|
-
isDefault
|
|
19868
|
-
...PaymentForm_PaymentMethodsFragment
|
|
19869
|
-
}
|
|
19870
|
-
}
|
|
19871
|
-
}
|
|
19872
|
-
`, [PaymentForm_PaymentMethodsFragment]);
|
|
19873
|
-
const getPaymentMethods = async ({ apiHost, token, accountId, }) => {
|
|
19874
|
-
var _a, _b, _c;
|
|
19875
|
-
const response = await execute(query$9, { apiHost, token }, { accountId });
|
|
19876
|
-
// Filter out null values that are technically possible due to api schema
|
|
19877
|
-
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 : [];
|
|
19878
|
-
};
|
|
19879
|
-
const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
19880
|
-
// Context
|
|
19881
|
-
const { apiHost } = useContext(BunnyContext);
|
|
19882
|
-
const token = useToken();
|
|
19883
|
-
// Query
|
|
19884
|
-
const { data, isLoading } = useQuery({
|
|
19885
|
-
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
19886
|
-
accountId,
|
|
19887
|
-
token,
|
|
19888
|
-
}),
|
|
19889
|
-
queryFn: () => getPaymentMethods({ apiHost, token, accountId }),
|
|
19890
|
-
staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes
|
|
19891
|
-
enabled,
|
|
19892
|
-
});
|
|
19893
|
-
return {
|
|
19894
|
-
paymentMethods: data,
|
|
19895
|
-
defaultPaymentMethod: data === null || data === void 0 ? void 0 : data.find(paymentMethod => paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.isDefault),
|
|
19896
|
-
isLoading,
|
|
19897
|
-
};
|
|
19898
|
-
};
|
|
19899
|
-
|
|
19900
19846
|
const mutation$i = t(`
|
|
19901
19847
|
query PaymentPlugins($accountId: ID) {
|
|
19902
19848
|
paymentPlugins(accountId: $accountId) {
|
|
@@ -19952,63 +19898,53 @@ const usePaymentPlugins = (accountId) => {
|
|
|
19952
19898
|
};
|
|
19953
19899
|
};
|
|
19954
19900
|
|
|
19955
|
-
|
|
19956
|
-
* Creates a context and provider for a state value
|
|
19957
|
-
* @param useValue - A function that returns the state value
|
|
19958
|
-
* @returns A tuple containing the provider and the context value
|
|
19959
|
-
* @example take a look at how this is used in the quoteIdContext in the QuantityDrawer
|
|
19960
|
-
*/
|
|
19961
|
-
const createStateContext = (useValue) => {
|
|
19962
|
-
const StateContext = createContext(null);
|
|
19963
|
-
const StateProvider = ({ initialValue, children, }) => jsxs(StateContext.Provider, { value: useValue(initialValue), children: [" ", children, " "] });
|
|
19964
|
-
const useContextState = () => {
|
|
19965
|
-
const value = useContext(StateContext);
|
|
19966
|
-
if (value === null) {
|
|
19967
|
-
throw new Error('Provider missing');
|
|
19968
|
-
}
|
|
19969
|
-
return value;
|
|
19970
|
-
};
|
|
19971
|
-
return [StateProvider, useContextState];
|
|
19972
|
-
};
|
|
19901
|
+
const [PaymentFormCallbacksProvider, usePaymentFormCallbacks] = createValueContext();
|
|
19973
19902
|
|
|
19974
|
-
//
|
|
19975
|
-
const
|
|
19976
|
-
|
|
19977
|
-
|
|
19978
|
-
|
|
19979
|
-
|
|
19980
|
-
|
|
19981
|
-
|
|
19982
|
-
|
|
19983
|
-
|
|
19984
|
-
|
|
19985
|
-
|
|
19986
|
-
function
|
|
19987
|
-
|
|
19988
|
-
|
|
19989
|
-
|
|
19990
|
-
|
|
19991
|
-
|
|
19992
|
-
|
|
19993
|
-
|
|
19994
|
-
|
|
19995
|
-
|
|
19996
|
-
|
|
19997
|
-
|
|
19903
|
+
// Used for Signup component. Signup uses an apiClient token which api can't infer an account from, so accountId must be used
|
|
19904
|
+
const [AccountIdProvider, useAccountId] = createValueContext();
|
|
19905
|
+
|
|
19906
|
+
// Automatically sets the default payment method if there is none currently set
|
|
19907
|
+
const useAutoSetDefaultPaymentMethod = ({ handleSetDefault, setDefaultPaymentMethodLoading, enabled = true, }) => {
|
|
19908
|
+
const accountId = useAccountId();
|
|
19909
|
+
const token = useToken();
|
|
19910
|
+
const queryClient = useQueryClient();
|
|
19911
|
+
const { paymentMethods, defaultPaymentMethod } = usePaymentMethod({
|
|
19912
|
+
accountId,
|
|
19913
|
+
});
|
|
19914
|
+
// Set the default payment method on the cache. Prevents 'handleSetDefault' from being called too many times.
|
|
19915
|
+
function setDefaultPaymentMethodOnCache(targetPaymentMethod) {
|
|
19916
|
+
let cachedPaymentMethods = queryClient.getQueryData(QueryKeyFactory.accountPaymentMethodsKey({
|
|
19917
|
+
accountId,
|
|
19918
|
+
token,
|
|
19919
|
+
}));
|
|
19920
|
+
if (cachedPaymentMethods) {
|
|
19921
|
+
for (const paymentMethod of cachedPaymentMethods) {
|
|
19922
|
+
paymentMethod.isDefault = paymentMethod.id === targetPaymentMethod.id;
|
|
19923
|
+
}
|
|
19924
|
+
queryClient.setQueryData(QueryKeyFactory.accountPaymentMethodsKey({
|
|
19925
|
+
accountId,
|
|
19926
|
+
token,
|
|
19927
|
+
}), cachedPaymentMethods);
|
|
19928
|
+
}
|
|
19929
|
+
}
|
|
19998
19930
|
useEffect(() => {
|
|
19999
|
-
var _a
|
|
20000
|
-
if (
|
|
19931
|
+
var _a;
|
|
19932
|
+
if (setDefaultPaymentMethodLoading || !enabled)
|
|
20001
19933
|
return;
|
|
19934
|
+
if ((paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) && (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) > 0 && !defaultPaymentMethod) {
|
|
19935
|
+
handleSetDefault((_a = paymentMethods[0]) === null || _a === void 0 ? void 0 : _a.id);
|
|
19936
|
+
setDefaultPaymentMethodOnCache(paymentMethods[0]);
|
|
20002
19937
|
}
|
|
20003
|
-
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
|
|
20007
|
-
|
|
20008
|
-
|
|
20009
|
-
|
|
20010
|
-
|
|
20011
|
-
|
|
19938
|
+
}, [
|
|
19939
|
+
paymentMethods,
|
|
19940
|
+
defaultPaymentMethod,
|
|
19941
|
+
handleSetDefault,
|
|
19942
|
+
setDefaultPaymentMethodLoading,
|
|
19943
|
+
queryClient,
|
|
19944
|
+
accountId,
|
|
19945
|
+
token,
|
|
19946
|
+
]);
|
|
19947
|
+
};
|
|
20012
19948
|
|
|
20013
19949
|
const request = ({ method = 'GET', apiHost, endpoint, body, headers, token, }) => {
|
|
20014
19950
|
const { apiEndpoint } = DEFAULT_CONFIG;
|
|
@@ -20053,222 +19989,232 @@ const invokePlugin = async ({ method, payload, plugin, token, apiHost, component
|
|
|
20053
19989
|
throw new Error(error.message);
|
|
20054
19990
|
};
|
|
20055
19991
|
|
|
20056
|
-
|
|
20057
|
-
|
|
20058
|
-
const
|
|
20059
|
-
const isNavigation = (char) => [9, 37, 38, 39, 40].includes(char); // Tab, Arrows
|
|
20060
|
-
const isModifier = (char) => [16, 17, 18].includes(char); // Shift, Ctrl, Alt
|
|
20061
|
-
const isValidKey = (code) => isDeletion(code) || isNavigation(code) || isModifier(code);
|
|
20062
|
-
const isValidExpiry = (expiry) => {
|
|
20063
|
-
const month = parseInt(expiry.substring(0, 2), 10);
|
|
20064
|
-
const year = parseInt(expiry.substring(2, 4), 10) + 2000;
|
|
20065
|
-
if (isNaN(month) || isNaN(year))
|
|
20066
|
-
return false;
|
|
20067
|
-
if (month < 1 || month > 12)
|
|
20068
|
-
return false;
|
|
20069
|
-
return true;
|
|
20070
|
-
};
|
|
20071
|
-
const isCardExpired = (expiry) => {
|
|
20072
|
-
const month = parseInt(expiry.substring(0, 2), 10);
|
|
20073
|
-
const year = parseInt(expiry.substring(2, 4), 10) + 2000;
|
|
20074
|
-
const expiryDate = new Date(year, month, 1);
|
|
20075
|
-
return expiryDate < new Date();
|
|
20076
|
-
};
|
|
20077
|
-
const formatCardExpiry = (cardExpiry) => {
|
|
20078
|
-
if (cardExpiry.length <= 2)
|
|
20079
|
-
return cardExpiry;
|
|
20080
|
-
return cardExpiry.substring(0, 2) + '/' + cardExpiry.substring(2);
|
|
20081
|
-
};
|
|
20082
|
-
// removes spaces from a credit card number
|
|
20083
|
-
const unformatCardNumber = (cardNumber) => {
|
|
20084
|
-
const cardNumberArray = cardNumber.split('');
|
|
20085
|
-
const unformattedCardNumberArray = cardNumberArray.filter(character => character !== ' ');
|
|
20086
|
-
return unformattedCardNumberArray.join('');
|
|
20087
|
-
};
|
|
20088
|
-
const storePayment = async (options, plugin, apiHost, accountId) => {
|
|
20089
|
-
const { testCreditCardNumber, testCreditCardCvc, testCreditCardExpirationDate, token } = options;
|
|
20090
|
-
const response = await invokePlugin({
|
|
20091
|
-
method: 'store_payment_method',
|
|
20092
|
-
plugin,
|
|
20093
|
-
payload: {
|
|
20094
|
-
test_credit_card_number: testCreditCardNumber,
|
|
20095
|
-
test_credit_card_cvc: testCreditCardCvc,
|
|
20096
|
-
test_credit_card_expiration_date: testCreditCardExpirationDate,
|
|
20097
|
-
account_id: accountId,
|
|
20098
|
-
},
|
|
20099
|
-
token,
|
|
20100
|
-
apiHost,
|
|
20101
|
-
});
|
|
20102
|
-
if ((response === null || response === void 0 ? void 0 : response.status) !== 'success')
|
|
20103
|
-
throw new Error(response === null || response === void 0 ? void 0 : response.message);
|
|
20104
|
-
return response;
|
|
20105
|
-
};
|
|
20106
|
-
|
|
20107
|
-
function useSave$1({ onSaveSuccess, onSaveError, accountId, }) {
|
|
20108
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
20109
|
-
const { apiHost } = useContext(BunnyContext);
|
|
19992
|
+
function useSetDefaultPaymentMethod(onError, onSuccess) {
|
|
19993
|
+
// Context
|
|
19994
|
+
const accountId = useAccountId();
|
|
20110
19995
|
const token = useToken();
|
|
20111
|
-
const
|
|
20112
|
-
const
|
|
20113
|
-
|
|
20114
|
-
|
|
20115
|
-
|
|
20116
|
-
|
|
20117
|
-
|
|
20118
|
-
|
|
20119
|
-
|
|
20120
|
-
|
|
20121
|
-
|
|
20122
|
-
|
|
20123
|
-
|
|
20124
|
-
|
|
20125
|
-
pluginPaymentResponse: {
|
|
20126
|
-
plugin,
|
|
20127
|
-
token: response.token,
|
|
20128
|
-
savePaymentMethod: true,
|
|
20129
|
-
},
|
|
20130
|
-
savedPaymentMethodResponse: {
|
|
20131
|
-
paymentMethodId,
|
|
20132
|
-
},
|
|
20133
|
-
});
|
|
20134
|
-
return paymentMethodId;
|
|
20135
|
-
}
|
|
20136
|
-
catch (error) {
|
|
20137
|
-
onSaveError === null || onSaveError === void 0 ? void 0 : onSaveError(error);
|
|
20138
|
-
}
|
|
20139
|
-
finally {
|
|
20140
|
-
setIsSaving(false);
|
|
19996
|
+
const { apiHost } = useContext(BunnyContext);
|
|
19997
|
+
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
19998
|
+
const { paymentMethods } = usePaymentMethod({ accountId });
|
|
19999
|
+
// Hooks
|
|
20000
|
+
const showErrorNotification = useErrorNotification();
|
|
20001
|
+
const showSuccessNotification = useSuccessNotification();
|
|
20002
|
+
const queryClient = useQueryClient();
|
|
20003
|
+
// State
|
|
20004
|
+
const [loading, setLoading] = useState(false);
|
|
20005
|
+
const setDefaultPaymentMethod = useCallback(async (paymentMethodId) => {
|
|
20006
|
+
const paymentMethod = paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.find(paymentMethod => (paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id) === paymentMethodId);
|
|
20007
|
+
if (paymentMethod === undefined) {
|
|
20008
|
+
showErrorNotification('Payment method not found', 'Error setting default payment method');
|
|
20009
|
+
return;
|
|
20141
20010
|
}
|
|
20142
|
-
return
|
|
20143
|
-
|
|
20144
|
-
|
|
20145
|
-
|
|
20146
|
-
|
|
20147
|
-
|
|
20148
|
-
|
|
20149
|
-
|
|
20150
|
-
|
|
20151
|
-
|
|
20152
|
-
|
|
20153
|
-
|
|
20154
|
-
|
|
20155
|
-
|
|
20156
|
-
|
|
20157
|
-
|
|
20158
|
-
|
|
20159
|
-
|
|
20160
|
-
|
|
20161
|
-
|
|
20162
|
-
|
|
20163
|
-
|
|
20164
|
-
|
|
20165
|
-
|
|
20166
|
-
|
|
20167
|
-
|
|
20168
|
-
|
|
20169
|
-
|
|
20170
|
-
|
|
20171
|
-
|
|
20172
|
-
|
|
20173
|
-
|
|
20174
|
-
|
|
20175
|
-
|
|
20176
|
-
|
|
20011
|
+
const plugin = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.find(paymentPlugin => { var _a; return String(paymentPlugin.id) === ((_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.plugin) === null || _a === void 0 ? void 0 : _a.id); }); // TODO: type the response to PluginData
|
|
20012
|
+
if (plugin) {
|
|
20013
|
+
setLoading(true);
|
|
20014
|
+
await invokePlugin({
|
|
20015
|
+
plugin: plugin,
|
|
20016
|
+
method: 'assign_default_payment_method',
|
|
20017
|
+
payload: {
|
|
20018
|
+
payment_method_id: paymentMethod.id,
|
|
20019
|
+
account_id: accountId,
|
|
20020
|
+
},
|
|
20021
|
+
token,
|
|
20022
|
+
apiHost,
|
|
20023
|
+
})
|
|
20024
|
+
.then(() => {
|
|
20025
|
+
var _a;
|
|
20026
|
+
showSuccessNotification(`Payment method ${(_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.identifier} was set as default`, 'Success');
|
|
20027
|
+
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
|
|
20028
|
+
queryClient.invalidateQueries({
|
|
20029
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
20030
|
+
token,
|
|
20031
|
+
accountId,
|
|
20032
|
+
}),
|
|
20033
|
+
});
|
|
20034
|
+
})
|
|
20035
|
+
.catch((error) => {
|
|
20036
|
+
setLoading(false);
|
|
20037
|
+
showErrorNotification(error.message, 'Error removing payment method');
|
|
20038
|
+
})
|
|
20039
|
+
.finally(() => {
|
|
20040
|
+
setLoading(false);
|
|
20041
|
+
});
|
|
20042
|
+
}
|
|
20043
|
+
else {
|
|
20044
|
+
const availablePlugins = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.map((plugin) => { var _a, _b, _c; return (_c = (_b = (_a = plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name; });
|
|
20045
|
+
onError === null || onError === void 0 ? void 0 : onError(`Either the payment method was not found or the plugin was not present. Available plugins: ${availablePlugins === null || availablePlugins === void 0 ? void 0 : availablePlugins.join(', ')}`);
|
|
20046
|
+
}
|
|
20047
|
+
}, [paymentPlugins, token, apiHost, queryClient]);
|
|
20048
|
+
return { setDefaultPaymentMethod, loading };
|
|
20049
|
+
}
|
|
20050
|
+
|
|
20051
|
+
function useRemovePaymentMethod(onPaymentMethodRemoved, onError) {
|
|
20052
|
+
const queryClient = useQueryClient();
|
|
20053
|
+
const showErrorNotification = useErrorNotification();
|
|
20054
|
+
const showSuccessNotification = useSuccessNotification();
|
|
20055
|
+
const accountId = useAccountId();
|
|
20056
|
+
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
20057
|
+
const token = useToken();
|
|
20058
|
+
const { apiHost } = useContext(BunnyContext);
|
|
20059
|
+
const removePaymentMethod = useCallback(async (data) => {
|
|
20060
|
+
const plugin = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.find(paymentPlugin => { var _a; return String(paymentPlugin.id) === String((_a = data === null || data === void 0 ? void 0 : data.plugin) === null || _a === void 0 ? void 0 : _a.id); });
|
|
20061
|
+
if (data && plugin) {
|
|
20062
|
+
await invokePlugin({
|
|
20063
|
+
plugin: plugin, // TODO: type the plugin
|
|
20064
|
+
method: 'remove_payment_method',
|
|
20065
|
+
payload: {
|
|
20066
|
+
payment_method_id: data.id,
|
|
20067
|
+
account_id: accountId,
|
|
20068
|
+
},
|
|
20069
|
+
token,
|
|
20070
|
+
apiHost,
|
|
20071
|
+
})
|
|
20072
|
+
.then(() => {
|
|
20073
|
+
showSuccessNotification('Payment method was removed', 'Success');
|
|
20074
|
+
queryClient.invalidateQueries({
|
|
20075
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
20076
|
+
token,
|
|
20077
|
+
accountId,
|
|
20078
|
+
}),
|
|
20079
|
+
});
|
|
20080
|
+
onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(data);
|
|
20081
|
+
})
|
|
20082
|
+
.catch((error) => {
|
|
20083
|
+
showErrorNotification(error.message, 'Error removing payment method');
|
|
20084
|
+
});
|
|
20085
|
+
}
|
|
20086
|
+
else {
|
|
20087
|
+
const availablePlugins = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.map(plugin => {
|
|
20088
|
+
var _a, _b;
|
|
20089
|
+
const components = plugin.components;
|
|
20090
|
+
return (_b = (_a = components === null || components === void 0 ? void 0 : components.frontend) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name;
|
|
20091
|
+
});
|
|
20092
|
+
onError === null || onError === void 0 ? void 0 : onError(`Either the payment method was not found or the plugin was not present. Available plugins: ${availablePlugins === null || availablePlugins === void 0 ? void 0 : availablePlugins.join(', ')}`);
|
|
20093
|
+
}
|
|
20094
|
+
}, [paymentPlugins, token, apiHost, queryClient, onPaymentMethodRemoved, accountId, onError]);
|
|
20095
|
+
return removePaymentMethod;
|
|
20096
|
+
}
|
|
20097
|
+
|
|
20098
|
+
const StoredPaymentMethods_PaymentMethodsFragment = t(`
|
|
20099
|
+
fragment StoredPaymentMethods_PaymentMethodsFragment on PaymentMethod {
|
|
20100
|
+
...MiniCreditCard_PaymentMethodFragment
|
|
20101
|
+
id
|
|
20102
|
+
plugin {
|
|
20177
20103
|
id
|
|
20178
|
-
amount
|
|
20179
20104
|
}
|
|
20180
20105
|
}
|
|
20181
|
-
|
|
20182
|
-
|
|
20183
|
-
|
|
20184
|
-
const
|
|
20185
|
-
|
|
20186
|
-
|
|
20187
|
-
|
|
20188
|
-
};
|
|
20189
|
-
|
|
20190
|
-
|
|
20191
|
-
|
|
20192
|
-
|
|
20193
|
-
|
|
20106
|
+
`, [MiniCreditCard_PaymentMethodFragment]);
|
|
20107
|
+
const showErrorNotification$d = useErrorNotification();
|
|
20108
|
+
function StoredPaymentMethods(props = {}) {
|
|
20109
|
+
const { className } = props;
|
|
20110
|
+
const accountId = useAccountId();
|
|
20111
|
+
const { paymentMethods, isLoading: isPaymentMethodLoading } = usePaymentMethod({ accountId });
|
|
20112
|
+
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
20113
|
+
const { onSetDefaultPaymentMethod, onPaymentMethodRemoved } = usePaymentFormCallbacks();
|
|
20114
|
+
// Custom hooks
|
|
20115
|
+
const { setDefaultPaymentMethod: handleSetDefault, loading: setDefaultPaymentMethodLoading } = useSetDefaultPaymentMethod(message => {
|
|
20116
|
+
showErrorNotification$d(message, 'Error setting default payment method');
|
|
20117
|
+
}, () => {
|
|
20118
|
+
onSetDefaultPaymentMethod === null || onSetDefaultPaymentMethod === void 0 ? void 0 : onSetDefaultPaymentMethod();
|
|
20119
|
+
});
|
|
20120
|
+
useAutoSetDefaultPaymentMethod({
|
|
20121
|
+
handleSetDefault,
|
|
20122
|
+
setDefaultPaymentMethodLoading,
|
|
20123
|
+
enabled: !!paymentPlugins,
|
|
20124
|
+
});
|
|
20125
|
+
const handleRemovePaymentMethod = useRemovePaymentMethod(onPaymentMethodRemoved, message => {
|
|
20126
|
+
showErrorNotification$d(message, 'Error removing payment method');
|
|
20127
|
+
});
|
|
20128
|
+
if (isPaymentMethodLoading) {
|
|
20129
|
+
return jsx(Skeleton, { active: true, className: "bunny-p-4" });
|
|
20194
20130
|
}
|
|
20195
|
-
|
|
20196
|
-
|
|
20197
|
-
|
|
20198
|
-
|
|
20199
|
-
|
|
20131
|
+
return (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 ${className}`, children: [paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.map(maskedPaymentMethod => {
|
|
20132
|
+
const paymentMethod = readFragment(StoredPaymentMethods_PaymentMethodsFragment, maskedPaymentMethod);
|
|
20133
|
+
return (jsx(MiniCreditCard, { onClickRemove: () => handleRemovePaymentMethod(paymentMethod), onClickSetDefault: () => handleSetDefault(paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id), paymentMethod: paymentMethod, id: `payment-method-${paymentMethod.id}` }, paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id));
|
|
20134
|
+
}), (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) === 0 && jsx(MiniCreditCard, {})] }));
|
|
20135
|
+
}
|
|
20136
|
+
|
|
20137
|
+
const query$9 = t(`
|
|
20138
|
+
query PaymentMethods($accountId: ID) {
|
|
20139
|
+
paymentMethods(accountId: $accountId) {
|
|
20140
|
+
nodes {
|
|
20141
|
+
id
|
|
20142
|
+
pluginId
|
|
20143
|
+
accountId
|
|
20144
|
+
expirationDate
|
|
20145
|
+
plugin {
|
|
20146
|
+
guid
|
|
20147
|
+
id
|
|
20148
|
+
}
|
|
20149
|
+
state
|
|
20150
|
+
metadata {
|
|
20151
|
+
issuer
|
|
20152
|
+
identifier
|
|
20153
|
+
kind
|
|
20154
|
+
description
|
|
20155
|
+
icon
|
|
20156
|
+
type
|
|
20157
|
+
}
|
|
20158
|
+
isDefault
|
|
20159
|
+
...PaymentForm_PaymentMethodsFragment
|
|
20160
|
+
...StoredPaymentMethods_PaymentMethodsFragment
|
|
20161
|
+
}
|
|
20162
|
+
}
|
|
20163
|
+
}
|
|
20164
|
+
`, [PaymentForm_PaymentMethodsFragment, StoredPaymentMethods_PaymentMethodsFragment]);
|
|
20165
|
+
const getPaymentMethods = async ({ apiHost, token, accountId, }) => {
|
|
20166
|
+
var _a, _b, _c;
|
|
20167
|
+
const response = await execute(query$9, { apiHost, token }, { accountId });
|
|
20168
|
+
// Filter out null values that are technically possible due to api schema
|
|
20169
|
+
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 : [];
|
|
20170
|
+
};
|
|
20171
|
+
const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
20172
|
+
// Context
|
|
20173
|
+
const { apiHost } = useContext(BunnyContext);
|
|
20174
|
+
const token = useToken();
|
|
20175
|
+
// Query
|
|
20176
|
+
const { data, isLoading } = useQuery({
|
|
20177
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
20178
|
+
accountId,
|
|
20179
|
+
token,
|
|
20180
|
+
}),
|
|
20181
|
+
queryFn: () => getPaymentMethods({ apiHost, token, accountId }),
|
|
20182
|
+
staleTime: 5 * 60 * 1000, // Consider data fresh for 5 minutes
|
|
20183
|
+
enabled,
|
|
20200
20184
|
});
|
|
20201
|
-
const { errors } = response === null || response === void 0 ? void 0 : response.checkout;
|
|
20202
|
-
if (errors)
|
|
20203
|
-
throw errors;
|
|
20204
20185
|
return {
|
|
20205
|
-
|
|
20186
|
+
paymentMethods: data,
|
|
20187
|
+
defaultPaymentMethod: data === null || data === void 0 ? void 0 : data.find(paymentMethod => paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.isDefault),
|
|
20188
|
+
isLoading,
|
|
20206
20189
|
};
|
|
20207
20190
|
};
|
|
20208
20191
|
|
|
20209
|
-
|
|
20210
|
-
|
|
20211
|
-
|
|
20212
|
-
|
|
20213
|
-
|
|
20214
|
-
|
|
20215
|
-
|
|
20216
|
-
|
|
20217
|
-
|
|
20218
|
-
|
|
20219
|
-
|
|
20220
|
-
|
|
20221
|
-
|
|
20222
|
-
}
|
|
20223
|
-
|
|
20224
|
-
var dayjs_minExports = requireDayjs_min();
|
|
20225
|
-
var dayjs = /*@__PURE__*/getDefaultExportFromCjs(dayjs_minExports);
|
|
20226
|
-
|
|
20227
|
-
var localizedFormat$2 = {exports: {}};
|
|
20228
|
-
|
|
20229
|
-
var localizedFormat$1 = localizedFormat$2.exports;
|
|
20230
|
-
|
|
20231
|
-
var hasRequiredLocalizedFormat;
|
|
20232
|
-
|
|
20233
|
-
function requireLocalizedFormat () {
|
|
20234
|
-
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
20235
|
-
hasRequiredLocalizedFormat = 1;
|
|
20236
|
-
(function (module, exports) {
|
|
20237
|
-
!function(e,t){module.exports=t();}(localizedFormat$1,(function(){var e={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};return function(t,o,n){var r=o.prototype,i=r.format;n.en.formats=e,r.format=function(t){void 0===t&&(t="YYYY-MM-DDTHH:mm:ssZ");var o=this.$locale().formats,n=function(t,o){return t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var i=r&&r.toUpperCase();return n||o[r]||e[r]||o[i].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,o){return t||o.slice(1)}))}))}(t,void 0===o?{}:o);return i.call(this,n)};}}));
|
|
20238
|
-
} (localizedFormat$2));
|
|
20239
|
-
return localizedFormat$2.exports;
|
|
20240
|
-
}
|
|
20241
|
-
|
|
20242
|
-
var localizedFormatExports = requireLocalizedFormat();
|
|
20243
|
-
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
20244
|
-
|
|
20245
|
-
dayjs.extend(localizedFormat);
|
|
20246
|
-
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
20247
|
-
if (value !== 0 && !value)
|
|
20248
|
-
return '';
|
|
20249
|
-
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
20250
|
-
if (isNaN(currencyValue))
|
|
20192
|
+
/**
|
|
20193
|
+
* Creates a context and provider for a state value
|
|
20194
|
+
* @param useValue - A function that returns the state value
|
|
20195
|
+
* @returns A tuple containing the provider and the context value
|
|
20196
|
+
* @example take a look at how this is used in the quoteIdContext in the QuantityDrawer
|
|
20197
|
+
*/
|
|
20198
|
+
const createStateContext = (useValue) => {
|
|
20199
|
+
const StateContext = createContext(null);
|
|
20200
|
+
const StateProvider = ({ initialValue, children, }) => jsxs(StateContext.Provider, { value: useValue(initialValue), children: [" ", children, " "] });
|
|
20201
|
+
const useContextState = () => {
|
|
20202
|
+
const value = useContext(StateContext);
|
|
20203
|
+
if (value === null) {
|
|
20204
|
+
throw new Error('Provider missing');
|
|
20205
|
+
}
|
|
20251
20206
|
return value;
|
|
20252
|
-
const localeOptions = {
|
|
20253
|
-
minimumFractionDigits: decimals,
|
|
20254
|
-
maximumFractionDigits: decimals,
|
|
20255
20207
|
};
|
|
20256
|
-
|
|
20257
|
-
localeOptions.currency = currencyIsoCode;
|
|
20258
|
-
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
20208
|
+
return [StateProvider, useContextState];
|
|
20259
20209
|
};
|
|
20260
20210
|
|
|
20261
|
-
const
|
|
20262
|
-
|
|
20263
|
-
|
|
20264
|
-
|
|
20265
|
-
}
|
|
20266
|
-
`, []);
|
|
20267
|
-
const getQuoteAmountDue = (maskedQuote) => {
|
|
20268
|
-
var _a;
|
|
20269
|
-
const quote = readFragment(getQuoteAmountDue_QuoteFragment, maskedQuote);
|
|
20270
|
-
return (_a = quote.amountDue) !== null && _a !== void 0 ? _a : quote.amount;
|
|
20211
|
+
const defaultCardDetails = {
|
|
20212
|
+
number: '4242424242424242',
|
|
20213
|
+
expiry: '',
|
|
20214
|
+
cvc: '',
|
|
20271
20215
|
};
|
|
20216
|
+
const useDemoPayCardDetailsState = (initialValue) => useState(initialValue !== null && initialValue !== void 0 ? initialValue : defaultCardDetails);
|
|
20217
|
+
const [DemoPayFormProvider, useDemoPayCardDetails] = createStateContext(useDemoPayCardDetailsState);
|
|
20272
20218
|
|
|
20273
20219
|
const { useToken: useAntdToken$1 } = theme;
|
|
20274
20220
|
const createPaymentMethod = async ({ paymentMethodId, plugin, token, apiHost, accountId, }) => {
|
|
@@ -20410,6 +20356,277 @@ const useStripePlugin = (plugin, currencyId, accountId) => {
|
|
|
20410
20356
|
return { stripe, options };
|
|
20411
20357
|
};
|
|
20412
20358
|
|
|
20359
|
+
// Contexts
|
|
20360
|
+
const useSelectedPluginIdState = (id) => useState(id);
|
|
20361
|
+
const [SelectedPluginIdProvider, useSelectedPluginId] = createStateContext(useSelectedPluginIdState);
|
|
20362
|
+
const [SelectedPluginDataProvider, useSelectedPlugin] = createValueContext(); // TODO: type the response to PluginData
|
|
20363
|
+
/**
|
|
20364
|
+
* SelectedPluginProvider manages the selected payment plugin state.
|
|
20365
|
+
*
|
|
20366
|
+
* Data Flow Pattern:
|
|
20367
|
+
* - Children components should set the plugin ID using `setSelectedPluginId` from `useSelectedPluginId`
|
|
20368
|
+
* - This provider then derives the `selectedPlugin` from that ID and provides it via `useSelectedPlugin`
|
|
20369
|
+
* - This ensures that data flows only downward: children control the ID, and the provider computes and provides the data
|
|
20370
|
+
*/
|
|
20371
|
+
function SelectedPluginProvider({ children, accountId, }) {
|
|
20372
|
+
return (jsx(SelectedPluginIdProvider, { initialValue: undefined, children: jsx(Content, { accountId: accountId, children: children }) }));
|
|
20373
|
+
}
|
|
20374
|
+
function Content({ children, accountId }) {
|
|
20375
|
+
// Context
|
|
20376
|
+
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
20377
|
+
const { defaultPaymentMethod } = usePaymentMethod({ accountId });
|
|
20378
|
+
const [selectedPluginId, setSelectedPluginId] = useSelectedPluginId();
|
|
20379
|
+
// Derived state
|
|
20380
|
+
const selectedPlugin = useMemo(() => {
|
|
20381
|
+
return paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.find(plugin => plugin.id === selectedPluginId);
|
|
20382
|
+
}, [paymentPlugins, selectedPluginId]);
|
|
20383
|
+
useEffect(() => {
|
|
20384
|
+
var _a, _b;
|
|
20385
|
+
if (selectedPluginId) {
|
|
20386
|
+
return;
|
|
20387
|
+
}
|
|
20388
|
+
if (defaultPaymentMethod) {
|
|
20389
|
+
setSelectedPluginId((_a = defaultPaymentMethod.plugin) === null || _a === void 0 ? void 0 : _a.id);
|
|
20390
|
+
}
|
|
20391
|
+
else {
|
|
20392
|
+
setSelectedPluginId((_b = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins[0]) === null || _b === void 0 ? void 0 : _b.id);
|
|
20393
|
+
}
|
|
20394
|
+
}, [defaultPaymentMethod, paymentPlugins]);
|
|
20395
|
+
return jsx(SelectedPluginDataProvider, { value: selectedPlugin, children: children });
|
|
20396
|
+
}
|
|
20397
|
+
|
|
20398
|
+
function StripeFormProvider({ children, currencyId, accountId, }) {
|
|
20399
|
+
const plugin = useSelectedPlugin();
|
|
20400
|
+
const { stripe, options } = useStripePlugin(plugin, currencyId, accountId);
|
|
20401
|
+
return (jsx(Elements, { options: options, stripe: stripe, children: children }));
|
|
20402
|
+
}
|
|
20403
|
+
|
|
20404
|
+
const MUTATION$4 = `
|
|
20405
|
+
mutation checkout(
|
|
20406
|
+
$invoiceId: ID,
|
|
20407
|
+
$quoteId: ID,
|
|
20408
|
+
$paymentMethodId: ID,
|
|
20409
|
+
$paymentMethodData: CheckoutPaymentMethodAttributes
|
|
20410
|
+
) {
|
|
20411
|
+
checkout(
|
|
20412
|
+
invoiceId: $invoiceId,
|
|
20413
|
+
quoteId: $quoteId,
|
|
20414
|
+
paymentMethodId: $paymentMethodId,
|
|
20415
|
+
paymentMethodData: $paymentMethodData
|
|
20416
|
+
) {
|
|
20417
|
+
invoice {
|
|
20418
|
+
id
|
|
20419
|
+
state
|
|
20420
|
+
amount
|
|
20421
|
+
amountDue
|
|
20422
|
+
}
|
|
20423
|
+
payment {
|
|
20424
|
+
id
|
|
20425
|
+
state
|
|
20426
|
+
amount
|
|
20427
|
+
}
|
|
20428
|
+
paymentApplication {
|
|
20429
|
+
id
|
|
20430
|
+
invoiceId
|
|
20431
|
+
paymentId
|
|
20432
|
+
}
|
|
20433
|
+
transaction {
|
|
20434
|
+
id
|
|
20435
|
+
amount
|
|
20436
|
+
}
|
|
20437
|
+
}
|
|
20438
|
+
}
|
|
20439
|
+
`;
|
|
20440
|
+
const checkout = async ({ quoteId, invoiceId, paymentMethodId, paymentMethodData, token, apiHost, }) => {
|
|
20441
|
+
const mutationVars = {
|
|
20442
|
+
quoteId,
|
|
20443
|
+
invoiceId,
|
|
20444
|
+
paymentMethodId,
|
|
20445
|
+
};
|
|
20446
|
+
if (paymentMethodData) {
|
|
20447
|
+
mutationVars.paymentMethodData = {
|
|
20448
|
+
...paymentMethodData,
|
|
20449
|
+
metadata: paymentMethodData.metadata,
|
|
20450
|
+
};
|
|
20451
|
+
}
|
|
20452
|
+
const response = await gqlRequest({
|
|
20453
|
+
query: MUTATION$4,
|
|
20454
|
+
token,
|
|
20455
|
+
vars: mutationVars,
|
|
20456
|
+
apiHost: apiHost,
|
|
20457
|
+
});
|
|
20458
|
+
const { errors } = response === null || response === void 0 ? void 0 : response.checkout;
|
|
20459
|
+
if (errors)
|
|
20460
|
+
throw errors;
|
|
20461
|
+
return {
|
|
20462
|
+
savePaymentMethod: paymentMethodData === null || paymentMethodData === void 0 ? void 0 : paymentMethodData.savePaymentMethod,
|
|
20463
|
+
};
|
|
20464
|
+
};
|
|
20465
|
+
|
|
20466
|
+
const getQuoteAmountDue_QuoteFragment = t(`
|
|
20467
|
+
fragment getQuoteAmountDue_QuoteFragment on Quote {
|
|
20468
|
+
amountDue
|
|
20469
|
+
amount
|
|
20470
|
+
}
|
|
20471
|
+
`, []);
|
|
20472
|
+
const getQuoteAmountDue = (maskedQuote) => {
|
|
20473
|
+
var _a;
|
|
20474
|
+
const quote = readFragment(getQuoteAmountDue_QuoteFragment, maskedQuote);
|
|
20475
|
+
return (_a = quote.amountDue) !== null && _a !== void 0 ? _a : quote.amount;
|
|
20476
|
+
};
|
|
20477
|
+
|
|
20478
|
+
var dayjs_min$1 = {exports: {}};
|
|
20479
|
+
|
|
20480
|
+
var dayjs_min = dayjs_min$1.exports;
|
|
20481
|
+
|
|
20482
|
+
var hasRequiredDayjs_min;
|
|
20483
|
+
|
|
20484
|
+
function requireDayjs_min () {
|
|
20485
|
+
if (hasRequiredDayjs_min) return dayjs_min$1.exports;
|
|
20486
|
+
hasRequiredDayjs_min = 1;
|
|
20487
|
+
(function (module, exports) {
|
|
20488
|
+
!function(t,e){module.exports=e();}(dayjs_min,(function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return "["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return !r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return (e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return -t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return +(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return {M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},g="en",D={};D[g]=M;var p="$isDayjsObject",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else {var a=e.name;D[a]=e,i=a;}return !r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0;}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init();},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds();},m.$utils=function(){return b},m.isValid=function(){return !(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v="set"+(this.$u?"UTC":"");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+"Hours",0);case u:return $(v+"Minutes",1);case s:return $(v+"Seconds",2);case i:return $(v+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f="set"+(this.$u?"UTC":""),l=(n={},n[a]=f+"Date",n[d]=f+"Date",n[c]=f+"Month",n[h]=f+"FullYear",n[u]=f+"Hours",n[s]=f+"Minutes",n[i]=f+"Seconds",n[r]=f+"Milliseconds",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d;}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,"0")},$=f||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return b.s(e.$y,4,"0");case"M":return a+1;case"MM":return b.s(a+1,2,"0");case"MMM":return h(n.monthsShort,a,c,3);case"MMMM":return h(c,a);case"D":return e.$D;case"DD":return b.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(n.weekdaysMin,e.$W,o,2);case"ddd":return h(n.weekdaysShort,e.$W,o,3);case"dddd":return o[e.$W];case"H":return String(s);case"HH":return b.s(s,2,"0");case"h":return d(1);case"hh":return d(2);case"a":return $(s,u,!0);case"A":return $(s,u,!1);case"m":return String(u);case"mm":return b.s(u,2,"0");case"s":return String(e.$s);case"ss":return b.s(e.$s,2,"0");case"SSS":return b.s(e.$ms,3,"0");case"Z":return i}return null}(t)||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g;}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",c],["$y",h],["$D",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])};})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));
|
|
20489
|
+
} (dayjs_min$1));
|
|
20490
|
+
return dayjs_min$1.exports;
|
|
20491
|
+
}
|
|
20492
|
+
|
|
20493
|
+
var dayjs_minExports = requireDayjs_min();
|
|
20494
|
+
var dayjs = /*@__PURE__*/getDefaultExportFromCjs(dayjs_minExports);
|
|
20495
|
+
|
|
20496
|
+
var localizedFormat$2 = {exports: {}};
|
|
20497
|
+
|
|
20498
|
+
var localizedFormat$1 = localizedFormat$2.exports;
|
|
20499
|
+
|
|
20500
|
+
var hasRequiredLocalizedFormat;
|
|
20501
|
+
|
|
20502
|
+
function requireLocalizedFormat () {
|
|
20503
|
+
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
20504
|
+
hasRequiredLocalizedFormat = 1;
|
|
20505
|
+
(function (module, exports) {
|
|
20506
|
+
!function(e,t){module.exports=t();}(localizedFormat$1,(function(){var e={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};return function(t,o,n){var r=o.prototype,i=r.format;n.en.formats=e,r.format=function(t){void 0===t&&(t="YYYY-MM-DDTHH:mm:ssZ");var o=this.$locale().formats,n=function(t,o){return t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var i=r&&r.toUpperCase();return n||o[r]||e[r]||o[i].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,o){return t||o.slice(1)}))}))}(t,void 0===o?{}:o);return i.call(this,n)};}}));
|
|
20507
|
+
} (localizedFormat$2));
|
|
20508
|
+
return localizedFormat$2.exports;
|
|
20509
|
+
}
|
|
20510
|
+
|
|
20511
|
+
var localizedFormatExports = requireLocalizedFormat();
|
|
20512
|
+
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
20513
|
+
|
|
20514
|
+
dayjs.extend(localizedFormat);
|
|
20515
|
+
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
20516
|
+
if (value !== 0 && !value)
|
|
20517
|
+
return '';
|
|
20518
|
+
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
20519
|
+
if (isNaN(currencyValue))
|
|
20520
|
+
return value;
|
|
20521
|
+
const localeOptions = {
|
|
20522
|
+
minimumFractionDigits: decimals,
|
|
20523
|
+
maximumFractionDigits: decimals,
|
|
20524
|
+
};
|
|
20525
|
+
localeOptions.style = 'currency';
|
|
20526
|
+
localeOptions.currency = currencyIsoCode;
|
|
20527
|
+
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
20528
|
+
};
|
|
20529
|
+
|
|
20530
|
+
var PaymentType;
|
|
20531
|
+
(function (PaymentType) {
|
|
20532
|
+
PaymentType["PAY"] = "PAY";
|
|
20533
|
+
PaymentType["APPROVE_HOLD"] = "APPROVE_HOLD";
|
|
20534
|
+
PaymentType["CHECKOUT_NO_PAYMENT"] = "CHECKOUT_NO_PAYMENT";
|
|
20535
|
+
PaymentType["SAVE"] = "SAVE";
|
|
20536
|
+
})(PaymentType || (PaymentType = {}));
|
|
20537
|
+
|
|
20538
|
+
// Contexts
|
|
20539
|
+
// TODO: use useSelector to get the values from the context so we don't have unnecessary re-renders
|
|
20540
|
+
const [PayableProvider, usePayable] = createValueContext();
|
|
20541
|
+
const PaymentProvider_QuoteFragment = t(`
|
|
20542
|
+
fragment PaymentProvider_QuoteFragment on Quote {
|
|
20543
|
+
id
|
|
20544
|
+
currencyId
|
|
20545
|
+
...getQuoteAmountDue_QuoteFragment
|
|
20546
|
+
}
|
|
20547
|
+
`, [getQuoteAmountDue_QuoteFragment]);
|
|
20548
|
+
const PaymentProvider_InvoiceFragment = t(`
|
|
20549
|
+
fragment PaymentProvider_InvoiceFragment on Invoice {
|
|
20550
|
+
id
|
|
20551
|
+
currencyId
|
|
20552
|
+
amountDue
|
|
20553
|
+
}
|
|
20554
|
+
`);
|
|
20555
|
+
function PaymentProvider({ children, quote: maskedQuote, invoice: maskedInvoice, paymentHold, }) {
|
|
20556
|
+
var _a, _b;
|
|
20557
|
+
// Read fragments
|
|
20558
|
+
const quote = readFragment(PaymentProvider_QuoteFragment, maskedQuote);
|
|
20559
|
+
const invoice = readFragment(PaymentProvider_InvoiceFragment, maskedInvoice);
|
|
20560
|
+
// State
|
|
20561
|
+
const [isPaid, setIsPaid] = useState(false);
|
|
20562
|
+
const getAmountDue = () => {
|
|
20563
|
+
return quote ? getQuoteAmountDue(quote) : invoice === null || invoice === void 0 ? void 0 : invoice.amountDue;
|
|
20564
|
+
};
|
|
20565
|
+
const formattedAmountDue = () => {
|
|
20566
|
+
var _a;
|
|
20567
|
+
const amountDue = getAmountDue();
|
|
20568
|
+
const currencyId = (_a = quote === null || quote === void 0 ? void 0 : quote.currencyId) !== null && _a !== void 0 ? _a : invoice === null || invoice === void 0 ? void 0 : invoice.currencyId;
|
|
20569
|
+
return amountDue !== undefined && currencyId !== undefined
|
|
20570
|
+
? formatCurrency(amountDue, currencyId).toString()
|
|
20571
|
+
: undefined;
|
|
20572
|
+
};
|
|
20573
|
+
// Validation checks
|
|
20574
|
+
if (quote !== undefined && invoice !== undefined && paymentHold !== undefined) {
|
|
20575
|
+
throw new Error('Either quote or invoice or paymentHold must be provided, not all');
|
|
20576
|
+
}
|
|
20577
|
+
function getPaymentType() {
|
|
20578
|
+
if (getAmountDue() === undefined)
|
|
20579
|
+
return PaymentType.SAVE;
|
|
20580
|
+
if (getAmountDue() === 0)
|
|
20581
|
+
return PaymentType.CHECKOUT_NO_PAYMENT;
|
|
20582
|
+
return paymentHold
|
|
20583
|
+
? PaymentType.APPROVE_HOLD
|
|
20584
|
+
: PaymentType.PAY;
|
|
20585
|
+
}
|
|
20586
|
+
const paymentType = getPaymentType();
|
|
20587
|
+
const amountDue = getAmountDue();
|
|
20588
|
+
const formattedAmountDueValue = formattedAmountDue();
|
|
20589
|
+
return (jsx(PayableProvider, { value: {
|
|
20590
|
+
quoteId: (_a = quote === null || quote === void 0 ? void 0 : quote.id) !== null && _a !== void 0 ? _a : undefined,
|
|
20591
|
+
invoiceId: (_b = invoice === null || invoice === void 0 ? void 0 : invoice.id) !== null && _b !== void 0 ? _b : undefined,
|
|
20592
|
+
paymentHold,
|
|
20593
|
+
paymentType,
|
|
20594
|
+
amountDue: amountDue !== null && amountDue !== void 0 ? amountDue : undefined,
|
|
20595
|
+
formattedAmountDue: formattedAmountDueValue,
|
|
20596
|
+
isPaid,
|
|
20597
|
+
setIsPaid
|
|
20598
|
+
}, children: children }));
|
|
20599
|
+
}
|
|
20600
|
+
|
|
20601
|
+
function CheckoutNoPayment(props = {}) {
|
|
20602
|
+
const { className, disabled } = props;
|
|
20603
|
+
const { formattedAmountDue, quoteId } = usePayable();
|
|
20604
|
+
const token = useToken();
|
|
20605
|
+
const { apiHost } = useContext(BunnyContext);
|
|
20606
|
+
const handleAllErrorFormats = useAllErrorFormats$1();
|
|
20607
|
+
const { onPaymentSuccess } = usePaymentFormCallbacks();
|
|
20608
|
+
const { mutate: checkoutNoPayment, isPending } = useMutation({
|
|
20609
|
+
mutationFn: async () => {
|
|
20610
|
+
const paymentRequired = formattedAmountDue ? parseFloat(formattedAmountDue) > 0 : true;
|
|
20611
|
+
if (!quoteId)
|
|
20612
|
+
throw new Error('Quote ID is required');
|
|
20613
|
+
if (paymentRequired)
|
|
20614
|
+
throw new Error('Payment is required');
|
|
20615
|
+
return await checkout({ quoteId, token, apiHost });
|
|
20616
|
+
},
|
|
20617
|
+
onSuccess: () => {
|
|
20618
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess({});
|
|
20619
|
+
},
|
|
20620
|
+
onError: error => {
|
|
20621
|
+
handleAllErrorFormats(error);
|
|
20622
|
+
},
|
|
20623
|
+
});
|
|
20624
|
+
return (jsx("div", { className: className, children: jsx(Button, { className: "bunny-w-full", loading: isPending, disabled: isPending || disabled, onClick: () => checkoutNoPayment(), type: "primary", children: isPending ? 'Processing...' : 'Complete Order' }) }));
|
|
20625
|
+
}
|
|
20626
|
+
|
|
20627
|
+
const useShowPaymentDetailsState = (isOpen = false) => useState(isOpen);
|
|
20628
|
+
const [ShowPaymentDetailsProvider, useShowPaymentDetails] = createStateContext(useShowPaymentDetailsState);
|
|
20629
|
+
|
|
20413
20630
|
function useApproveHold$1({ onApproveHoldSuccess, onApproveHoldError, }) {
|
|
20414
20631
|
// Hooks
|
|
20415
20632
|
const [isApprovingHold, setIsApprovingHold] = useState(false);
|
|
@@ -20442,47 +20659,6 @@ function useApproveHold$1({ onApproveHoldSuccess, onApproveHoldError, }) {
|
|
|
20442
20659
|
return { approveHold, isApprovingHold };
|
|
20443
20660
|
}
|
|
20444
20661
|
|
|
20445
|
-
// Used for Signup component. Signup needs a custom checkout function
|
|
20446
|
-
const [CustomCheckoutFunctionProvider, useCustomCheckoutFunction] = createValueContext();
|
|
20447
|
-
|
|
20448
|
-
const showErrorNotification$a = useErrorNotification();
|
|
20449
|
-
function usePay$1({ onPaymentSuccess, onPaymentError, quoteId, invoice, plugin, }) {
|
|
20450
|
-
const { apiHost } = useContext(BunnyContext);
|
|
20451
|
-
const customCheckoutFunction = useCustomCheckoutFunction();
|
|
20452
|
-
const token = useToken();
|
|
20453
|
-
const [isPaying, setIsPaying] = useState(false);
|
|
20454
|
-
const pay = async (paymentMethodId) => {
|
|
20455
|
-
try {
|
|
20456
|
-
setIsPaying(true);
|
|
20457
|
-
if (customCheckoutFunction) {
|
|
20458
|
-
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.id)) {
|
|
20459
|
-
showErrorNotification$a('Plugin ID is required');
|
|
20460
|
-
return;
|
|
20461
|
-
}
|
|
20462
|
-
const response = await customCheckoutFunction(plugin === null || plugin === void 0 ? void 0 : plugin.id.toString(), paymentMethodId.toString());
|
|
20463
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20464
|
-
}
|
|
20465
|
-
else {
|
|
20466
|
-
const response = await checkout({
|
|
20467
|
-
invoiceId: invoice === null || invoice === void 0 ? void 0 : invoice.id,
|
|
20468
|
-
quoteId,
|
|
20469
|
-
paymentMethodId,
|
|
20470
|
-
token,
|
|
20471
|
-
apiHost,
|
|
20472
|
-
});
|
|
20473
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20474
|
-
}
|
|
20475
|
-
}
|
|
20476
|
-
catch (error) {
|
|
20477
|
-
onPaymentError === null || onPaymentError === void 0 ? void 0 : onPaymentError(error);
|
|
20478
|
-
}
|
|
20479
|
-
finally {
|
|
20480
|
-
setIsPaying(false);
|
|
20481
|
-
}
|
|
20482
|
-
};
|
|
20483
|
-
return { pay, isPaying };
|
|
20484
|
-
}
|
|
20485
|
-
|
|
20486
20662
|
function useApproveHold({ onApproveHoldSuccess, onApproveHoldError, }) {
|
|
20487
20663
|
// Hooks
|
|
20488
20664
|
const [isApprovingHold, setIsApprovingHold] = useState(false);
|
|
@@ -20515,209 +20691,147 @@ function useApproveHold({ onApproveHoldSuccess, onApproveHoldError, }) {
|
|
|
20515
20691
|
return { approveHold, isApprovingHold };
|
|
20516
20692
|
}
|
|
20517
20693
|
|
|
20518
|
-
const showErrorNotification$
|
|
20519
|
-
function
|
|
20520
|
-
|
|
20521
|
-
const
|
|
20522
|
-
const customCheckoutFunction = useCustomCheckoutFunction();
|
|
20523
|
-
const token = useToken();
|
|
20524
|
-
const [isPaying, setIsPaying] = useState(false);
|
|
20525
|
-
const pay = async (paymentMethodId) => {
|
|
20526
|
-
try {
|
|
20527
|
-
setIsPaying(true);
|
|
20528
|
-
if (customCheckoutFunction) {
|
|
20529
|
-
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.id)) {
|
|
20530
|
-
showErrorNotification$9('Plugin ID is required');
|
|
20531
|
-
return;
|
|
20532
|
-
}
|
|
20533
|
-
const response = await customCheckoutFunction(plugin === null || plugin === void 0 ? void 0 : plugin.id.toString(), paymentMethodId.toString());
|
|
20534
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20535
|
-
}
|
|
20536
|
-
else {
|
|
20537
|
-
if (!quoteId && !(invoice === null || invoice === void 0 ? void 0 : invoice.id)) {
|
|
20538
|
-
showErrorNotification$9('Quote ID or Invoice ID is required');
|
|
20539
|
-
return;
|
|
20540
|
-
}
|
|
20541
|
-
const response = await checkout({
|
|
20542
|
-
invoiceId: invoice === null || invoice === void 0 ? void 0 : invoice.id,
|
|
20543
|
-
quoteId,
|
|
20544
|
-
paymentMethodId,
|
|
20545
|
-
token,
|
|
20546
|
-
apiHost,
|
|
20547
|
-
});
|
|
20548
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20549
|
-
}
|
|
20550
|
-
}
|
|
20551
|
-
catch (error) {
|
|
20552
|
-
onPaymentError === null || onPaymentError === void 0 ? void 0 : onPaymentError(error);
|
|
20553
|
-
}
|
|
20554
|
-
finally {
|
|
20555
|
-
setIsPaying(false);
|
|
20556
|
-
}
|
|
20557
|
-
};
|
|
20558
|
-
return { pay, isPaying };
|
|
20559
|
-
}
|
|
20560
|
-
|
|
20561
|
-
var PaymentType;
|
|
20562
|
-
(function (PaymentType) {
|
|
20563
|
-
PaymentType["PAY"] = "PAY";
|
|
20564
|
-
PaymentType["APPROVE_HOLD"] = "APPROVE_HOLD";
|
|
20565
|
-
PaymentType["CHECKOUT_NO_PAYMENT"] = "CHECKOUT_NO_PAYMENT";
|
|
20566
|
-
})(PaymentType || (PaymentType = {}));
|
|
20567
|
-
|
|
20568
|
-
const handleAllErrorFormats$3 = useAllErrorFormats();
|
|
20569
|
-
const showErrorNotification$8 = useErrorNotification();
|
|
20570
|
-
const useHandlePayment_QuoteFragment = t(`
|
|
20571
|
-
fragment useHandlePayment_QuoteFragment on Quote {
|
|
20572
|
-
id
|
|
20573
|
-
amount
|
|
20574
|
-
currencyId
|
|
20575
|
-
...getQuoteAmountDue_QuoteFragment
|
|
20576
|
-
}
|
|
20577
|
-
`, [getQuoteAmountDue_QuoteFragment]);
|
|
20578
|
-
const useHandlePayment = ({ quote: maskedQuote, invoice, onPaymentSuccess, onPaymentHoldSuccess, paymentHoldPrecondition, plugin, paymentHoldOptions, accountId, }) => {
|
|
20579
|
-
// Read fragments
|
|
20580
|
-
const quote = readFragment(useHandlePayment_QuoteFragment, maskedQuote);
|
|
20581
|
-
// Context
|
|
20582
|
-
const { defaultPaymentMethod } = usePaymentMethod({ accountId });
|
|
20583
|
-
const { apiHost } = useContext(BunnyContext);
|
|
20584
|
-
const token = useToken();
|
|
20585
|
-
// State
|
|
20586
|
-
const [isPaid, setIsPaid] = useState(false);
|
|
20587
|
-
const getAmountDue = () => {
|
|
20588
|
-
return quote ? getQuoteAmountDue(quote) : invoice === null || invoice === void 0 ? void 0 : invoice.amountDue;
|
|
20589
|
-
};
|
|
20590
|
-
const formattedAmountDue = () => {
|
|
20591
|
-
var _a;
|
|
20592
|
-
const amountDue = getAmountDue();
|
|
20593
|
-
const currencyId = (_a = quote === null || quote === void 0 ? void 0 : quote.currencyId) !== null && _a !== void 0 ? _a : invoice === null || invoice === void 0 ? void 0 : invoice.currencyId;
|
|
20594
|
-
return amountDue !== undefined && currencyId !== undefined ? formatCurrency(amountDue, currencyId).toString() : undefined;
|
|
20595
|
-
};
|
|
20596
|
-
// Validation checks
|
|
20597
|
-
if (quote !== undefined && invoice !== undefined) {
|
|
20598
|
-
throw new Error('Either quote or invoice must be provided, not both');
|
|
20599
|
-
}
|
|
20600
|
-
// Payment hooks
|
|
20601
|
-
const { pay: payDemoPay, isPaying: isPayingDemoPay } = usePay$1({
|
|
20602
|
-
onPaymentSuccess: handlePaymentSuccess,
|
|
20603
|
-
onPaymentError: error => {
|
|
20604
|
-
handleAllErrorFormats$3(error);
|
|
20605
|
-
},
|
|
20606
|
-
quoteId: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
20607
|
-
invoice: invoice,
|
|
20608
|
-
plugin,
|
|
20609
|
-
});
|
|
20610
|
-
const { pay: payStripe, isPaying: isPayingStripe } = usePay({
|
|
20611
|
-
onPaymentSuccess: handlePaymentSuccess,
|
|
20612
|
-
onPaymentError: error => {
|
|
20613
|
-
handleAllErrorFormats$3(error);
|
|
20614
|
-
},
|
|
20615
|
-
quoteId: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
20616
|
-
invoice: invoice,
|
|
20617
|
-
plugin,
|
|
20618
|
-
});
|
|
20619
|
-
// Approve hold hooks
|
|
20694
|
+
const showErrorNotification$c = useErrorNotification();
|
|
20695
|
+
function usePaymentHold({ plugin, onPaymentHoldSuccess, onPaymentHoldError, }) {
|
|
20696
|
+
var _a, _b, _c;
|
|
20697
|
+
const pluginName = (_c = (_b = (_a = plugin === null || plugin === void 0 ? void 0 : plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name;
|
|
20620
20698
|
const { approveHold: approveHoldStripe, isApprovingHold: isApprovingHoldStripe } = useApproveHold({
|
|
20621
|
-
onApproveHoldSuccess:
|
|
20622
|
-
|
|
20623
|
-
},
|
|
20624
|
-
onApproveHoldError: error => {
|
|
20625
|
-
handleAllErrorFormats$3(error);
|
|
20626
|
-
},
|
|
20699
|
+
onApproveHoldSuccess: onPaymentHoldSuccess,
|
|
20700
|
+
onApproveHoldError: onPaymentHoldError,
|
|
20627
20701
|
});
|
|
20628
20702
|
const { approveHold: approveHoldDemoPay, isApprovingHold: isApprovingHoldDemoPay } = useApproveHold$1({
|
|
20629
|
-
onApproveHoldSuccess:
|
|
20630
|
-
|
|
20631
|
-
},
|
|
20632
|
-
onApproveHoldError: error => {
|
|
20633
|
-
handleAllErrorFormats$3(error);
|
|
20634
|
-
},
|
|
20635
|
-
});
|
|
20636
|
-
// Mutations
|
|
20637
|
-
const { mutate: checkoutNoPayment, isPending: isCheckingOutNoPayment } = useMutation({
|
|
20638
|
-
mutationFn: async () => {
|
|
20639
|
-
const amountDue = formattedAmountDue();
|
|
20640
|
-
const paymentRequired = amountDue ? parseFloat(amountDue) > 0 : true;
|
|
20641
|
-
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
20642
|
-
throw new Error('Quote ID is required');
|
|
20643
|
-
if (paymentRequired)
|
|
20644
|
-
throw new Error('Payment is required');
|
|
20645
|
-
return await checkout({ quoteId: quote.id, token, apiHost });
|
|
20646
|
-
},
|
|
20647
|
-
onSuccess: () => {
|
|
20648
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess({});
|
|
20649
|
-
},
|
|
20650
|
-
onError: error => {
|
|
20651
|
-
handleAllErrorFormats$3(error);
|
|
20652
|
-
},
|
|
20703
|
+
onApproveHoldSuccess: onPaymentHoldSuccess,
|
|
20704
|
+
onApproveHoldError: onPaymentHoldError,
|
|
20653
20705
|
});
|
|
20654
|
-
const
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
const allowed = await paymentHoldPrecondition();
|
|
20658
|
-
if (!allowed)
|
|
20659
|
-
return;
|
|
20660
|
-
}
|
|
20661
|
-
const paymentMethodId = overridePaymentMethodId !== null && overridePaymentMethodId !== void 0 ? overridePaymentMethodId : defaultPaymentMethod === null || defaultPaymentMethod === void 0 ? void 0 : defaultPaymentMethod.id;
|
|
20706
|
+
const approveHold = async ({ quote, paymentMethodId, }) => {
|
|
20707
|
+
if (!pluginName)
|
|
20708
|
+
return showErrorNotification$c('plugin name is required');
|
|
20662
20709
|
if (!plugin)
|
|
20663
|
-
return showErrorNotification$
|
|
20664
|
-
|
|
20665
|
-
return showErrorNotification$8('quote id and amount are required to approve hold');
|
|
20666
|
-
if (!paymentMethodId)
|
|
20667
|
-
return;
|
|
20668
|
-
switch ((_b = (_a = plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name) {
|
|
20710
|
+
return showErrorNotification$c('plugin is required');
|
|
20711
|
+
switch (pluginName) {
|
|
20669
20712
|
case 'StripePayment':
|
|
20670
|
-
await approveHoldStripe({
|
|
20671
|
-
|
|
20672
|
-
quote: { id: quote.id, amount: quote.amount },
|
|
20673
|
-
paymentMethodId,
|
|
20674
|
-
});
|
|
20675
|
-
break;
|
|
20713
|
+
await approveHoldStripe({ plugin, quote, paymentMethodId });
|
|
20714
|
+
return;
|
|
20676
20715
|
case 'DemoPayPayment':
|
|
20677
|
-
await approveHoldDemoPay({
|
|
20716
|
+
await approveHoldDemoPay({ plugin, quote, paymentMethodId });
|
|
20717
|
+
return;
|
|
20718
|
+
default:
|
|
20719
|
+
showErrorNotification$c(`Payment holds are not supported by ${pluginName}`);
|
|
20720
|
+
return;
|
|
20721
|
+
}
|
|
20722
|
+
};
|
|
20723
|
+
return {
|
|
20724
|
+
approveHold,
|
|
20725
|
+
isApprovingHold: isApprovingHoldStripe || isApprovingHoldDemoPay,
|
|
20726
|
+
};
|
|
20727
|
+
}
|
|
20728
|
+
|
|
20729
|
+
const DIGIT_REGEX = /\d/;
|
|
20730
|
+
const isDigit = (char) => DIGIT_REGEX.test(char);
|
|
20731
|
+
const isDeletion = (char) => [8, 46].includes(char); // Backspace or Delete
|
|
20732
|
+
const isNavigation = (char) => [9, 37, 38, 39, 40].includes(char); // Tab, Arrows
|
|
20733
|
+
const isModifier = (char) => [16, 17, 18].includes(char); // Shift, Ctrl, Alt
|
|
20734
|
+
const isValidKey = (code) => isDeletion(code) || isNavigation(code) || isModifier(code);
|
|
20735
|
+
const isValidExpiry = (expiry) => {
|
|
20736
|
+
const month = parseInt(expiry.substring(0, 2), 10);
|
|
20737
|
+
const year = parseInt(expiry.substring(2, 4), 10) + 2000;
|
|
20738
|
+
if (isNaN(month) || isNaN(year))
|
|
20739
|
+
return false;
|
|
20740
|
+
if (month < 1 || month > 12)
|
|
20741
|
+
return false;
|
|
20742
|
+
return true;
|
|
20743
|
+
};
|
|
20744
|
+
const isCardExpired = (expiry) => {
|
|
20745
|
+
const month = parseInt(expiry.substring(0, 2), 10);
|
|
20746
|
+
const year = parseInt(expiry.substring(2, 4), 10) + 2000;
|
|
20747
|
+
const expiryDate = new Date(year, month, 1);
|
|
20748
|
+
return expiryDate < new Date();
|
|
20749
|
+
};
|
|
20750
|
+
const formatCardExpiry = (cardExpiry) => {
|
|
20751
|
+
if (cardExpiry.length <= 2)
|
|
20752
|
+
return cardExpiry;
|
|
20753
|
+
return cardExpiry.substring(0, 2) + '/' + cardExpiry.substring(2);
|
|
20754
|
+
};
|
|
20755
|
+
// removes spaces from a credit card number
|
|
20756
|
+
const unformatCardNumber = (cardNumber) => {
|
|
20757
|
+
const cardNumberArray = cardNumber.split('');
|
|
20758
|
+
const unformattedCardNumberArray = cardNumberArray.filter(character => character !== ' ');
|
|
20759
|
+
return unformattedCardNumberArray.join('');
|
|
20760
|
+
};
|
|
20761
|
+
const storePayment = async (options, plugin, apiHost, accountId) => {
|
|
20762
|
+
const { testCreditCardNumber, testCreditCardCvc, testCreditCardExpirationDate, token } = options;
|
|
20763
|
+
const response = await invokePlugin({
|
|
20764
|
+
method: 'store_payment_method',
|
|
20765
|
+
plugin,
|
|
20766
|
+
payload: {
|
|
20767
|
+
test_credit_card_number: testCreditCardNumber,
|
|
20768
|
+
test_credit_card_cvc: testCreditCardCvc,
|
|
20769
|
+
test_credit_card_expiration_date: testCreditCardExpirationDate,
|
|
20770
|
+
account_id: accountId,
|
|
20771
|
+
},
|
|
20772
|
+
token,
|
|
20773
|
+
apiHost,
|
|
20774
|
+
});
|
|
20775
|
+
if ((response === null || response === void 0 ? void 0 : response.status) !== 'success')
|
|
20776
|
+
throw new Error(response === null || response === void 0 ? void 0 : response.message);
|
|
20777
|
+
return response;
|
|
20778
|
+
};
|
|
20779
|
+
|
|
20780
|
+
const TEST_CARD = '4242424242424242';
|
|
20781
|
+
function useSave$2({ onSaveSuccess, onSaveError, accountId, }) {
|
|
20782
|
+
const [isSaving, setIsSaving] = useState(false);
|
|
20783
|
+
const { apiHost } = useContext(BunnyContext);
|
|
20784
|
+
const token = useToken();
|
|
20785
|
+
const plugin = useSelectedPlugin();
|
|
20786
|
+
const [cardDetails, setCardDetails] = useDemoPayCardDetails();
|
|
20787
|
+
const save = async () => {
|
|
20788
|
+
try {
|
|
20789
|
+
validateCardDetails();
|
|
20790
|
+
setIsSaving(true);
|
|
20791
|
+
const response = await storePayment({
|
|
20792
|
+
testCreditCardNumber: unformatCardNumber(cardDetails.number),
|
|
20793
|
+
testCreditCardCvc: cardDetails.cvc.toString(),
|
|
20794
|
+
testCreditCardExpirationDate: cardDetails.expiry,
|
|
20795
|
+
token,
|
|
20796
|
+
}, plugin, apiHost, accountId);
|
|
20797
|
+
const paymentMethodId = response.payload[0].id;
|
|
20798
|
+
if (response.status !== 'success')
|
|
20799
|
+
throw new Error(response === null || response === void 0 ? void 0 : response.message);
|
|
20800
|
+
onSaveSuccess === null || onSaveSuccess === void 0 ? void 0 : onSaveSuccess({
|
|
20801
|
+
pluginPaymentResponse: {
|
|
20678
20802
|
plugin,
|
|
20679
|
-
|
|
20803
|
+
token: response.token,
|
|
20804
|
+
savePaymentMethod: true,
|
|
20805
|
+
},
|
|
20806
|
+
savedPaymentMethodResponse: {
|
|
20680
20807
|
paymentMethodId,
|
|
20681
|
-
}
|
|
20682
|
-
|
|
20683
|
-
|
|
20684
|
-
|
|
20685
|
-
break;
|
|
20808
|
+
},
|
|
20809
|
+
});
|
|
20810
|
+
setCardDetails({ number: cardDetails.number, expiry: '', cvc: '' });
|
|
20811
|
+
return paymentMethodId;
|
|
20686
20812
|
}
|
|
20687
|
-
|
|
20688
|
-
|
|
20689
|
-
setIsPaid(true);
|
|
20690
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20691
|
-
}
|
|
20692
|
-
const handlePayment = async (overridePaymentMethodId) => {
|
|
20693
|
-
var _a, _b;
|
|
20694
|
-
if (!plugin)
|
|
20695
|
-
return;
|
|
20696
|
-
switch ((_b = (_a = plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name) {
|
|
20697
|
-
case 'StripePayment':
|
|
20698
|
-
await payStripe(overridePaymentMethodId);
|
|
20699
|
-
break;
|
|
20700
|
-
case 'DemoPayPayment':
|
|
20701
|
-
await payDemoPay(overridePaymentMethodId);
|
|
20702
|
-
break;
|
|
20813
|
+
catch (error) {
|
|
20814
|
+
onSaveError === null || onSaveError === void 0 ? void 0 : onSaveError(error);
|
|
20703
20815
|
}
|
|
20816
|
+
finally {
|
|
20817
|
+
setIsSaving(false);
|
|
20818
|
+
}
|
|
20819
|
+
return undefined;
|
|
20704
20820
|
};
|
|
20705
|
-
|
|
20706
|
-
|
|
20707
|
-
|
|
20708
|
-
|
|
20709
|
-
|
|
20710
|
-
|
|
20711
|
-
|
|
20712
|
-
|
|
20713
|
-
|
|
20714
|
-
|
|
20715
|
-
|
|
20716
|
-
|
|
20717
|
-
};
|
|
20718
|
-
};
|
|
20821
|
+
function validateCardDetails() {
|
|
20822
|
+
if (cardDetails.number !== TEST_CARD)
|
|
20823
|
+
throw new Error('Only the card number 4242 4242 4242 4242 will be accepted.');
|
|
20824
|
+
if (!isValidExpiry(cardDetails.expiry))
|
|
20825
|
+
throw new Error('Invalid expiry date');
|
|
20826
|
+
if (isCardExpired(cardDetails.expiry))
|
|
20827
|
+
throw new Error('Card is expired');
|
|
20828
|
+
if (cardDetails.cvc.length !== 3)
|
|
20829
|
+
throw new Error('Invalid CVC');
|
|
20830
|
+
}
|
|
20831
|
+
return { save, isSaving };
|
|
20832
|
+
}
|
|
20719
20833
|
|
|
20720
|
-
function useSave({ onSaveSuccess, onSaveError, accountId, }) {
|
|
20834
|
+
function useSave$1({ onSaveSuccess, onSaveError, accountId, }) {
|
|
20721
20835
|
// Hooks
|
|
20722
20836
|
const [isSaving, setIsSaving] = useState(false);
|
|
20723
20837
|
const elements = useElements();
|
|
@@ -20793,169 +20907,176 @@ function useSave({ onSaveSuccess, onSaveError, accountId, }) {
|
|
|
20793
20907
|
return { save, createStripePaymentMethodId, isSaving };
|
|
20794
20908
|
}
|
|
20795
20909
|
|
|
20796
|
-
const
|
|
20797
|
-
const
|
|
20798
|
-
|
|
20799
|
-
const handleAllErrorFormats$2 = useAllErrorFormats();
|
|
20800
|
-
const showErrorNotification$7 = useErrorNotification();
|
|
20801
|
-
// Contexts
|
|
20802
|
-
const [FormattedAmountDueProvider, useFormattedAmountDue] = createValueContext();
|
|
20803
|
-
const [PaymentTypeProvider, usePaymentType] = createValueContext();
|
|
20804
|
-
const [IsPayingProvider, useIsPaying] = createValueContext();
|
|
20805
|
-
const [HandlePaymentFormSubmitProvider, useHandlePaymentFormSubmit] = createValueContext();
|
|
20806
|
-
const [IsSavingProvider, useIsSaving] = createValueContext();
|
|
20807
|
-
// Used for PaymentMethodFooter to disable pay button if payment is already successful
|
|
20808
|
-
const [IsPaidProvider, useIsPaid] = createValueContext();
|
|
20809
|
-
// Used for Signup component. Signup uses an apiClient token which api can't infer an account from, so accountId must be used
|
|
20810
|
-
const [AccountIdProvider, useAccountId] = createValueContext();
|
|
20811
|
-
// Optional external control to disable the pay button (e.g. while quote is updating)
|
|
20812
|
-
const [IsPayButtonDisabledProvider, useIsPayButtonDisabled] = createValueContext();
|
|
20813
|
-
const PaymentProvider_QuoteFragment = t(`
|
|
20814
|
-
fragment PaymentProvider_QuoteFragment on Quote {
|
|
20815
|
-
id
|
|
20816
|
-
...useHandlePayment_QuoteFragment
|
|
20817
|
-
}
|
|
20818
|
-
`, [useHandlePayment_QuoteFragment]);
|
|
20819
|
-
function PaymentProvider({ children, accountId, quote: maskedQuote, invoice, onPaymentSuccess, onPaymentHoldSuccess, paymentHoldPrecondition, paymentHoldOptions, onSavePaymentMethod, }) {
|
|
20910
|
+
const handleAllErrorFormats$3 = useAllErrorFormats();
|
|
20911
|
+
const showErrorNotification$b = useErrorNotification();
|
|
20912
|
+
function useSave({ accountId, onSaveSuccess, onSaveError, invalidatePaymentMethodsQuery = true, }) {
|
|
20820
20913
|
var _a, _b, _c;
|
|
20821
|
-
// Read fragments
|
|
20822
|
-
const quote = readFragment(PaymentProvider_QuoteFragment, maskedQuote);
|
|
20823
|
-
// Context
|
|
20824
|
-
const [showPaymentMethodForm, setShowPaymentMethodForm] = useShowPaymentDetails();
|
|
20825
20914
|
const selectedPlugin = useSelectedPlugin();
|
|
20826
|
-
// Hooks
|
|
20827
20915
|
const queryClient = useQueryClient();
|
|
20828
20916
|
const token = useToken();
|
|
20829
|
-
const
|
|
20830
|
-
|
|
20831
|
-
|
|
20832
|
-
|
|
20833
|
-
// TODO: type the response to PaymentSuccessResponse
|
|
20834
|
-
// Hide payment method selector and form
|
|
20835
|
-
setShowPaymentMethodForm(false);
|
|
20836
|
-
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20837
|
-
},
|
|
20838
|
-
onPaymentHoldSuccess,
|
|
20839
|
-
paymentHoldPrecondition,
|
|
20840
|
-
plugin: selectedPlugin, // TODO: type the response to PluginData
|
|
20841
|
-
paymentHoldOptions,
|
|
20917
|
+
const onSaveErrorFinal = onSaveError !== null && onSaveError !== void 0 ? onSaveError : handleAllErrorFormats$3;
|
|
20918
|
+
// Derived state
|
|
20919
|
+
const pluginName = (_c = (_b = (_a = selectedPlugin === null || selectedPlugin === void 0 ? void 0 : selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name;
|
|
20920
|
+
const { save: saveDemoPay, isSaving: isSavingDemoPay } = useSave$2({
|
|
20842
20921
|
accountId,
|
|
20843
|
-
|
|
20844
|
-
|
|
20845
|
-
|
|
20846
|
-
|
|
20847
|
-
|
|
20848
|
-
|
|
20849
|
-
|
|
20850
|
-
accountId,
|
|
20851
|
-
token,
|
|
20852
|
-
}),
|
|
20853
|
-
});
|
|
20854
|
-
setShowPaymentMethodForm(false);
|
|
20922
|
+
onSaveSuccess: response => {
|
|
20923
|
+
onSaveSuccess === null || onSaveSuccess === void 0 ? void 0 : onSaveSuccess(response);
|
|
20924
|
+
if (invalidatePaymentMethodsQuery) {
|
|
20925
|
+
queryClient.invalidateQueries({
|
|
20926
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({ accountId, token }),
|
|
20927
|
+
});
|
|
20928
|
+
}
|
|
20855
20929
|
},
|
|
20856
|
-
onSaveError:
|
|
20857
|
-
accountId,
|
|
20930
|
+
onSaveError: onSaveErrorFinal,
|
|
20858
20931
|
});
|
|
20859
|
-
const { save: saveStripe, isSaving: isSavingStripe } = useSave({
|
|
20860
|
-
onSaveSuccess: async (response) => {
|
|
20861
|
-
onSavePaymentMethod === null || onSavePaymentMethod === void 0 ? void 0 : onSavePaymentMethod(response);
|
|
20862
|
-
queryClient.invalidateQueries({
|
|
20863
|
-
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
20864
|
-
accountId,
|
|
20865
|
-
token,
|
|
20866
|
-
}),
|
|
20867
|
-
});
|
|
20868
|
-
setShowPaymentMethodForm(false);
|
|
20869
|
-
},
|
|
20870
|
-
onSaveError: handleAllErrorFormats$2,
|
|
20932
|
+
const { save: saveStripe, isSaving: isSavingStripe } = useSave$1({
|
|
20871
20933
|
accountId,
|
|
20934
|
+
onSaveSuccess: response => {
|
|
20935
|
+
onSaveSuccess === null || onSaveSuccess === void 0 ? void 0 : onSaveSuccess(response);
|
|
20936
|
+
if (invalidatePaymentMethodsQuery) {
|
|
20937
|
+
queryClient.invalidateQueries({
|
|
20938
|
+
queryKey: QueryKeyFactory.accountPaymentMethodsKey({ accountId, token }),
|
|
20939
|
+
});
|
|
20940
|
+
}
|
|
20941
|
+
},
|
|
20942
|
+
onSaveError: onSaveErrorFinal,
|
|
20872
20943
|
});
|
|
20873
|
-
const
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
if (pluginName === 'StripePayment') {
|
|
20944
|
+
const save = async () => {
|
|
20945
|
+
var _a, _b, _c;
|
|
20946
|
+
if (pluginName === 'StripePayment')
|
|
20877
20947
|
return await saveStripe();
|
|
20878
|
-
|
|
20879
|
-
|
|
20880
|
-
|
|
20881
|
-
|
|
20882
|
-
else {
|
|
20883
|
-
showErrorNotification$7(`Can not find form for plugin ${(_b = (_a = selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name}`);
|
|
20884
|
-
return undefined;
|
|
20885
|
-
}
|
|
20948
|
+
if (pluginName === 'DemoPayPayment')
|
|
20949
|
+
return await saveDemoPay();
|
|
20950
|
+
showErrorNotification$b(`Can not find form for plugin ${(_c = (_b = (_a = selectedPlugin === null || selectedPlugin === void 0 ? void 0 : selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name}`);
|
|
20951
|
+
return undefined;
|
|
20886
20952
|
};
|
|
20887
|
-
|
|
20888
|
-
|
|
20889
|
-
|
|
20890
|
-
|
|
20953
|
+
return { save, isSaving: isSavingDemoPay || isSavingStripe };
|
|
20954
|
+
}
|
|
20955
|
+
|
|
20956
|
+
// Used for Signup component. Signup needs a custom checkout function
|
|
20957
|
+
const [CustomCheckoutFunctionProvider, useCustomCheckoutFunction] = createValueContext();
|
|
20958
|
+
|
|
20959
|
+
const showErrorNotification$a = useErrorNotification();
|
|
20960
|
+
function usePay$2({ onPaymentSuccess, onPaymentError, quoteId, invoiceId, plugin, }) {
|
|
20961
|
+
const { apiHost } = useContext(BunnyContext);
|
|
20962
|
+
const customCheckoutFunction = useCustomCheckoutFunction();
|
|
20963
|
+
const token = useToken();
|
|
20964
|
+
const [isPaying, setIsPaying] = useState(false);
|
|
20965
|
+
const pay = async (paymentMethodId) => {
|
|
20966
|
+
try {
|
|
20967
|
+
setIsPaying(true);
|
|
20968
|
+
if (customCheckoutFunction) {
|
|
20969
|
+
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.id)) {
|
|
20970
|
+
showErrorNotification$a('Plugin ID is required');
|
|
20971
|
+
return;
|
|
20972
|
+
}
|
|
20973
|
+
const response = await customCheckoutFunction(plugin === null || plugin === void 0 ? void 0 : plugin.id.toString(), paymentMethodId.toString());
|
|
20974
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20975
|
+
}
|
|
20976
|
+
else {
|
|
20977
|
+
const response = await checkout({
|
|
20978
|
+
invoiceId,
|
|
20979
|
+
quoteId,
|
|
20980
|
+
paymentMethodId,
|
|
20981
|
+
token,
|
|
20982
|
+
apiHost,
|
|
20983
|
+
});
|
|
20984
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20985
|
+
}
|
|
20891
20986
|
}
|
|
20892
|
-
|
|
20893
|
-
|
|
20987
|
+
catch (error) {
|
|
20988
|
+
onPaymentError === null || onPaymentError === void 0 ? void 0 : onPaymentError(error);
|
|
20894
20989
|
}
|
|
20895
|
-
|
|
20896
|
-
|
|
20990
|
+
finally {
|
|
20991
|
+
setIsPaying(false);
|
|
20897
20992
|
}
|
|
20898
20993
|
};
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
|
|
20905
|
-
|
|
20906
|
-
|
|
20907
|
-
|
|
20908
|
-
|
|
20909
|
-
|
|
20910
|
-
|
|
20911
|
-
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
}
|
|
20917
|
-
if (paymentType === PaymentType.PAY) {
|
|
20918
|
-
if (showPaymentMethodForm) {
|
|
20919
|
-
// If paying and showing payment method form, save payment method first, then pay (1 click for user convenience)
|
|
20920
|
-
const savedPaymentMethodId = await handleSave(demoPayCardDetails);
|
|
20921
|
-
if (savedPaymentMethodId) {
|
|
20922
|
-
await handlePayment(savedPaymentMethodId);
|
|
20994
|
+
return { pay, isPaying };
|
|
20995
|
+
}
|
|
20996
|
+
|
|
20997
|
+
const showErrorNotification$9 = useErrorNotification();
|
|
20998
|
+
function usePay$1({ onPaymentSuccess, onPaymentError, quoteId, invoiceId, plugin, }) {
|
|
20999
|
+
// Hooks
|
|
21000
|
+
const { apiHost } = useContext(BunnyContext);
|
|
21001
|
+
const customCheckoutFunction = useCustomCheckoutFunction();
|
|
21002
|
+
const token = useToken();
|
|
21003
|
+
const [isPaying, setIsPaying] = useState(false);
|
|
21004
|
+
const pay = async (paymentMethodId) => {
|
|
21005
|
+
try {
|
|
21006
|
+
setIsPaying(true);
|
|
21007
|
+
if (customCheckoutFunction) {
|
|
21008
|
+
if (!(plugin === null || plugin === void 0 ? void 0 : plugin.id)) {
|
|
21009
|
+
showErrorNotification$9('Plugin ID is required');
|
|
21010
|
+
return;
|
|
20923
21011
|
}
|
|
21012
|
+
const response = await customCheckoutFunction(plugin === null || plugin === void 0 ? void 0 : plugin.id.toString(), paymentMethodId.toString());
|
|
21013
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20924
21014
|
}
|
|
20925
21015
|
else {
|
|
20926
|
-
if (!
|
|
20927
|
-
showErrorNotification$
|
|
21016
|
+
if (!quoteId && !invoiceId) {
|
|
21017
|
+
showErrorNotification$9('Quote ID or Invoice ID is required');
|
|
20928
21018
|
return;
|
|
20929
21019
|
}
|
|
20930
|
-
|
|
21020
|
+
const response = await checkout({
|
|
21021
|
+
invoiceId,
|
|
21022
|
+
quoteId,
|
|
21023
|
+
paymentMethodId,
|
|
21024
|
+
token,
|
|
21025
|
+
apiHost,
|
|
21026
|
+
});
|
|
21027
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
20931
21028
|
}
|
|
20932
|
-
|
|
21029
|
+
}
|
|
21030
|
+
catch (error) {
|
|
21031
|
+
onPaymentError === null || onPaymentError === void 0 ? void 0 : onPaymentError(error);
|
|
21032
|
+
}
|
|
21033
|
+
finally {
|
|
21034
|
+
setIsPaying(false);
|
|
20933
21035
|
}
|
|
20934
21036
|
};
|
|
20935
|
-
|
|
20936
|
-
[FormattedAmountDueProvider, { value: formattedAmountDue }],
|
|
20937
|
-
[PaymentTypeProvider, { value: paymentType }],
|
|
20938
|
-
[IsPayingProvider, { value: isPaying }],
|
|
20939
|
-
[HandlePaymentFormSubmitProvider, { value: handlePaymentFormSubmit }],
|
|
20940
|
-
[IsSavingProvider, { value: isSavingDemoPay || isSavingStripe }],
|
|
20941
|
-
[IsPaidProvider, { value: isPaid }],
|
|
20942
|
-
[AccountIdProvider, { value: accountId }],
|
|
20943
|
-
];
|
|
20944
|
-
return (jsx(Fragment, { children: providers.reduceRight((acc, [Provider, props]) => createElement(Provider, props, acc), children) }));
|
|
21037
|
+
return { pay, isPaying };
|
|
20945
21038
|
}
|
|
20946
|
-
|
|
20947
|
-
|
|
20948
|
-
|
|
20949
|
-
|
|
21039
|
+
|
|
21040
|
+
const showErrorNotification$8 = useErrorNotification();
|
|
21041
|
+
function usePay({ plugin, quoteId, invoiceId, onPaymentSuccess, onPaymentError, }) {
|
|
21042
|
+
var _a, _b, _c;
|
|
21043
|
+
const pluginName = (_c = (_b = (_a = plugin === null || plugin === void 0 ? void 0 : plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name;
|
|
21044
|
+
const { pay: payStripe, isPaying: isPayingStripe } = usePay$1({
|
|
21045
|
+
onPaymentSuccess,
|
|
21046
|
+
onPaymentError,
|
|
21047
|
+
quoteId,
|
|
21048
|
+
invoiceId,
|
|
21049
|
+
plugin,
|
|
21050
|
+
});
|
|
21051
|
+
const { pay: payDemoPay, isPaying: isPayingDemoPay } = usePay$2({
|
|
21052
|
+
onPaymentSuccess,
|
|
21053
|
+
onPaymentError,
|
|
21054
|
+
quoteId,
|
|
21055
|
+
invoiceId,
|
|
21056
|
+
plugin,
|
|
21057
|
+
});
|
|
21058
|
+
const pay = async (paymentMethodId) => {
|
|
21059
|
+
if (!pluginName)
|
|
21060
|
+
return showErrorNotification$8('plugin name is required');
|
|
21061
|
+
switch (pluginName) {
|
|
21062
|
+
case 'StripePayment':
|
|
21063
|
+
await payStripe(paymentMethodId);
|
|
21064
|
+
return;
|
|
21065
|
+
case 'DemoPayPayment':
|
|
21066
|
+
await payDemoPay(paymentMethodId);
|
|
21067
|
+
return;
|
|
21068
|
+
default:
|
|
21069
|
+
showErrorNotification$8(`Payments are not supported by ${pluginName}`);
|
|
21070
|
+
return;
|
|
21071
|
+
}
|
|
21072
|
+
};
|
|
21073
|
+
return { pay, isPaying: isPayingStripe || isPayingDemoPay };
|
|
20950
21074
|
}
|
|
20951
21075
|
|
|
20952
|
-
function usePaymentButtonText() {
|
|
20953
|
-
const
|
|
20954
|
-
const paymentType =
|
|
20955
|
-
const
|
|
20956
|
-
const isSaving = useIsSaving();
|
|
20957
|
-
const isPaying = useIsPaying();
|
|
20958
|
-
const isProcessing = isSaving || isPaying;
|
|
21076
|
+
function usePaymentButtonText(props = {}) {
|
|
21077
|
+
const { isSaving, isPaying, isApprovingHold } = props;
|
|
21078
|
+
const { formattedAmountDue, paymentType, isPaid } = usePayable();
|
|
21079
|
+
const isProcessing = isSaving || isPaying || isApprovingHold;
|
|
20959
21080
|
// If payment is already successful, show the amount paid
|
|
20960
21081
|
if (isPaid) {
|
|
20961
21082
|
return 'Paid ' + (formattedAmountDue !== null && formattedAmountDue !== void 0 ? formattedAmountDue : '');
|
|
@@ -20970,34 +21091,95 @@ function usePaymentButtonText() {
|
|
|
20970
21091
|
return paymentTypeText + ' ' + (formattedAmountDue !== null && formattedAmountDue !== void 0 ? formattedAmountDue : '');
|
|
20971
21092
|
}
|
|
20972
21093
|
|
|
20973
|
-
const
|
|
20974
|
-
|
|
20975
|
-
|
|
20976
|
-
const
|
|
20977
|
-
const
|
|
20978
|
-
const
|
|
20979
|
-
const
|
|
20980
|
-
|
|
20981
|
-
|
|
20982
|
-
|
|
21094
|
+
const handleAllErrorFormats$2 = useAllErrorFormats();
|
|
21095
|
+
const showErrorNotification$7 = useErrorNotification();
|
|
21096
|
+
function Pay(props = {}) {
|
|
21097
|
+
const { disabled } = props;
|
|
21098
|
+
const isMobile = useIsMobile();
|
|
21099
|
+
const { onPaymentSuccess, onPaymentHoldSuccess, onSavePaymentMethod, paymentHoldPrecondition } = usePaymentFormCallbacks();
|
|
21100
|
+
const selectedPlugin = useSelectedPlugin();
|
|
21101
|
+
const { quoteId, invoiceId, paymentHold, paymentType, setIsPaid } = usePayable();
|
|
21102
|
+
const accountId = useAccountId();
|
|
21103
|
+
const { defaultPaymentMethod } = usePaymentMethod({ accountId });
|
|
21104
|
+
const [showPaymentDetailsForm, setShowPaymentDetailsForm] = useShowPaymentDetails();
|
|
21105
|
+
const { save, isSaving } = useSave({
|
|
21106
|
+
accountId,
|
|
21107
|
+
onSaveSuccess: (response) => {
|
|
21108
|
+
onSavePaymentMethod === null || onSavePaymentMethod === void 0 ? void 0 : onSavePaymentMethod(response);
|
|
21109
|
+
},
|
|
21110
|
+
onSaveError: handleAllErrorFormats$2,
|
|
21111
|
+
invalidatePaymentMethodsQuery: true,
|
|
21112
|
+
});
|
|
21113
|
+
const { pay, isPaying } = usePay({
|
|
21114
|
+
plugin: selectedPlugin,
|
|
21115
|
+
quoteId,
|
|
21116
|
+
invoiceId,
|
|
21117
|
+
onPaymentSuccess: (response) => {
|
|
21118
|
+
setIsPaid(true);
|
|
21119
|
+
setShowPaymentDetailsForm(false);
|
|
21120
|
+
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess(response);
|
|
21121
|
+
},
|
|
21122
|
+
onPaymentError: error => handleAllErrorFormats$2(error),
|
|
21123
|
+
});
|
|
21124
|
+
const { approveHold, isApprovingHold } = usePaymentHold({
|
|
21125
|
+
plugin: selectedPlugin,
|
|
21126
|
+
onPaymentHoldSuccess: onPaymentHoldSuccess,
|
|
21127
|
+
onPaymentHoldError: error => handleAllErrorFormats$2(error),
|
|
21128
|
+
});
|
|
21129
|
+
const paymentButtonText = usePaymentButtonText({ isSaving, isPaying, isApprovingHold });
|
|
21130
|
+
async function handlePayment() {
|
|
21131
|
+
if (paymentType === PaymentType.APPROVE_HOLD) {
|
|
21132
|
+
if (paymentHoldPrecondition) {
|
|
21133
|
+
const allowed = await paymentHoldPrecondition();
|
|
21134
|
+
if (!allowed)
|
|
21135
|
+
return;
|
|
21136
|
+
}
|
|
21137
|
+
if (!paymentHold) {
|
|
21138
|
+
showErrorNotification$7('Payment hold is undefined');
|
|
21139
|
+
return;
|
|
21140
|
+
}
|
|
21141
|
+
// If payment details form is shown, save payment method first, then approve hold
|
|
21142
|
+
if (showPaymentDetailsForm) {
|
|
21143
|
+
const savedPaymentMethodId = await save();
|
|
21144
|
+
if (!savedPaymentMethodId) {
|
|
21145
|
+
showErrorNotification$7('Saved payment method ID is undefined');
|
|
21146
|
+
return;
|
|
21147
|
+
}
|
|
21148
|
+
await approveHold({ quote: { id: paymentHold.quoteId, amount: paymentHold.amountToHold }, paymentMethodId: savedPaymentMethodId });
|
|
21149
|
+
return;
|
|
21150
|
+
}
|
|
21151
|
+
if (!(defaultPaymentMethod === null || defaultPaymentMethod === void 0 ? void 0 : defaultPaymentMethod.id)) {
|
|
21152
|
+
showErrorNotification$7('Default payment method ID is undefined');
|
|
21153
|
+
return;
|
|
21154
|
+
}
|
|
21155
|
+
await approveHold({ quote: { id: paymentHold.quoteId, amount: paymentHold.amountToHold }, paymentMethodId: defaultPaymentMethod.id });
|
|
21156
|
+
return;
|
|
21157
|
+
}
|
|
21158
|
+
if (paymentType === PaymentType.PAY) {
|
|
21159
|
+
if (showPaymentDetailsForm) {
|
|
21160
|
+
// If paying and showing payment method form, save payment method first, then pay (1 click for user convenience)
|
|
21161
|
+
const savedPaymentMethodId = await save();
|
|
21162
|
+
if (savedPaymentMethodId) {
|
|
21163
|
+
await pay(savedPaymentMethodId);
|
|
21164
|
+
}
|
|
21165
|
+
}
|
|
21166
|
+
else {
|
|
21167
|
+
if (!(defaultPaymentMethod === null || defaultPaymentMethod === void 0 ? void 0 : defaultPaymentMethod.id)) {
|
|
21168
|
+
showErrorNotification$7('Default payment method ID is undefined');
|
|
21169
|
+
return;
|
|
21170
|
+
}
|
|
21171
|
+
await pay(defaultPaymentMethod === null || defaultPaymentMethod === void 0 ? void 0 : defaultPaymentMethod.id);
|
|
21172
|
+
}
|
|
21173
|
+
return;
|
|
21174
|
+
}
|
|
21175
|
+
}
|
|
21176
|
+
return (jsx(Button, { className: "bunny-w-full", disabled: isPaying || isApprovingHold || isSaving || disabled, loading: isPaying || isApprovingHold || isSaving, onClick: handlePayment, size: isMobile ? 'large' : 'middle', type: "primary", children: paymentButtonText }));
|
|
21177
|
+
}
|
|
21178
|
+
|
|
20983
21179
|
const defaultStyled = typeof styled === "function" ? styled : styled.default;
|
|
20984
21180
|
// !!! This is a workaround to avoid the issue with styled-components not supporting ESM
|
|
20985
21181
|
// Workaround from https://github.com/styled-components/styled-components/issues/3437#issuecomment-1103085056
|
|
20986
21182
|
|
|
20987
|
-
function PaymentMethodFooter({ onSubmit, noPadding, }) {
|
|
20988
|
-
const isPaying = useIsPaying();
|
|
20989
|
-
const isSaving = useIsSaving();
|
|
20990
|
-
const formattedAmountDue = useFormattedAmountDue();
|
|
20991
|
-
const paymentButtonText = usePaymentButtonText();
|
|
20992
|
-
const isMobile = useIsMobile();
|
|
20993
|
-
const [, setShowPaymentMethodForm] = useShowPaymentDetails();
|
|
20994
|
-
// If amount due is undefined, show the save button
|
|
20995
|
-
const payableAvailable = formattedAmountDue !== undefined;
|
|
20996
|
-
const saveButtonText = isSaving ? 'Saving' : 'Save';
|
|
20997
|
-
const buttonText = payableAvailable ? paymentButtonText : saveButtonText;
|
|
20998
|
-
return (jsxs("div", { className: `bunny-flex bunny-justify-end bunny-gap-2 ${noPadding ? '' : 'pt-6'}`, children: [jsx(Button, { className: "bunny-w-full", size: isMobile ? 'large' : 'middle', onClick: () => setShowPaymentMethodForm(false), children: "Cancel" }), jsx(Button, { className: "bunny-w-full", disabled: isSaving || isPaying, loading: isSaving || isPaying, onClick: onSubmit, size: isMobile ? 'large' : 'middle', type: "primary", children: buttonText })] }));
|
|
20999
|
-
}
|
|
21000
|
-
|
|
21001
21183
|
const DemoPayCardCvc = ({ autoFocus, onChange, placeholder, value, }) => {
|
|
21002
21184
|
const onKeyPress = (event) => {
|
|
21003
21185
|
if (!isDigit(event.key) && !isValidKey(event.keyCode))
|
|
@@ -21037,46 +21219,19 @@ const DemoPayExpiry = ({ autoFocus, onChange, placeholder, value, }) => {
|
|
|
21037
21219
|
};
|
|
21038
21220
|
|
|
21039
21221
|
const { Text: Text$C } = Typography;
|
|
21040
|
-
const handleAllErrorFormats$1 = useAllErrorFormats();
|
|
21041
|
-
const TEST_CARD = '4242424242424242';
|
|
21042
21222
|
const DemoPayForm = () => {
|
|
21043
|
-
// Context
|
|
21044
21223
|
const { darkMode } = useContext(BunnyContext);
|
|
21045
|
-
const
|
|
21046
|
-
const [cardDetails, setCardDetails] = useState({
|
|
21047
|
-
number: '4242424242424242',
|
|
21048
|
-
expiry: '',
|
|
21049
|
-
cvc: '',
|
|
21050
|
-
});
|
|
21051
|
-
function onSubmit() {
|
|
21052
|
-
try {
|
|
21053
|
-
validateCardDetails();
|
|
21054
|
-
onPaymentFormSubmit(cardDetails);
|
|
21055
|
-
}
|
|
21056
|
-
catch (error) {
|
|
21057
|
-
handleAllErrorFormats$1(error);
|
|
21058
|
-
}
|
|
21059
|
-
}
|
|
21060
|
-
function validateCardDetails() {
|
|
21061
|
-
if (cardDetails.number !== TEST_CARD)
|
|
21062
|
-
throw new Error('Only the card number 4242 4242 4242 4242 will be accepted.');
|
|
21063
|
-
if (!isValidExpiry(cardDetails.expiry))
|
|
21064
|
-
throw new Error('Invalid expiry date');
|
|
21065
|
-
if (isCardExpired(cardDetails.expiry))
|
|
21066
|
-
throw new Error('Card is expired');
|
|
21067
|
-
if (cardDetails.cvc.length !== 3)
|
|
21068
|
-
throw new Error('Invalid CVC');
|
|
21069
|
-
}
|
|
21224
|
+
const [cardDetails, setCardDetails] = useDemoPayCardDetails();
|
|
21070
21225
|
const onCardNumberChange = (number) => {
|
|
21071
|
-
setCardDetails({ ...
|
|
21226
|
+
setCardDetails(prev => ({ ...prev, number }));
|
|
21072
21227
|
};
|
|
21073
21228
|
const onCardExpiryChange = (expiry) => {
|
|
21074
|
-
setCardDetails({ ...
|
|
21229
|
+
setCardDetails(prev => ({ ...prev, expiry }));
|
|
21075
21230
|
};
|
|
21076
21231
|
const onCardCvcChange = (cvc) => {
|
|
21077
|
-
setCardDetails({ ...
|
|
21232
|
+
setCardDetails(prev => ({ ...prev, cvc }));
|
|
21078
21233
|
};
|
|
21079
|
-
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsx(Text$C, { children: "DemoPay is for testing only." })
|
|
21234
|
+
return (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsx(Text$C, { children: "DemoPay is for testing only." })] }));
|
|
21080
21235
|
};
|
|
21081
21236
|
const StyledInputs = defaultStyled.div `
|
|
21082
21237
|
.ant-input {
|
|
@@ -21088,8 +21243,6 @@ const StyledInputs = defaultStyled.div `
|
|
|
21088
21243
|
`;
|
|
21089
21244
|
|
|
21090
21245
|
const StripeForm = () => {
|
|
21091
|
-
// Context
|
|
21092
|
-
const onPaymentFormSubmit = useHandlePaymentFormSubmit();
|
|
21093
21246
|
// State
|
|
21094
21247
|
const [isIdealWarningOpen, setIsIdealWarningOpen] = useState(false);
|
|
21095
21248
|
const idealWarningHasShown = useRef(false);
|
|
@@ -21101,25 +21254,19 @@ const StripeForm = () => {
|
|
|
21101
21254
|
};
|
|
21102
21255
|
return (jsxs("form", { children: [jsx(PaymentElement, { options: {
|
|
21103
21256
|
layout: { type: 'accordion' },
|
|
21104
|
-
}, onChange: onChange }), jsx(
|
|
21257
|
+
}, onChange: onChange }), jsx(IdealWarningModal, { isOpen: isIdealWarningOpen, onClose: () => setIsIdealWarningOpen(false) })] }));
|
|
21105
21258
|
};
|
|
21106
21259
|
function IdealWarningModal({ isOpen, onClose }) {
|
|
21107
21260
|
return (jsx(Modal, { open: isOpen, onCancel: onClose, footer: jsx(Button, { type: "primary", onClick: onClose, children: "Ok" }), children: jsx("div", { className: "bunny-p-4", children: "iDEAL will charge a 1 cent fee when storing this payment method. You will be refunded later." }) }));
|
|
21108
21261
|
}
|
|
21109
21262
|
|
|
21110
|
-
const
|
|
21111
|
-
|
|
21112
|
-
|
|
21113
|
-
|
|
21114
|
-
|
|
21115
|
-
|
|
21116
|
-
|
|
21117
|
-
return jsx(DemoPayForm, {});
|
|
21118
|
-
default:
|
|
21119
|
-
console.warn('Can not find form for plugin', selectedPlugin);
|
|
21120
|
-
return jsx(Fragment, {});
|
|
21121
|
-
}
|
|
21122
|
-
};
|
|
21263
|
+
const [PaymentMethodFormVisibilityProvider, usePaymentMethodFormVisibility] = createValueContext();
|
|
21264
|
+
|
|
21265
|
+
function Cancel() {
|
|
21266
|
+
const isMobile = useIsMobile();
|
|
21267
|
+
const [, setShowPaymentMethodForm] = useShowPaymentDetails();
|
|
21268
|
+
return (jsx(Button, { className: "bunny-w-full", size: isMobile ? 'large' : 'middle', onClick: () => setShowPaymentMethodForm(false), children: "Cancel" }));
|
|
21269
|
+
}
|
|
21123
21270
|
|
|
21124
21271
|
const CardIcon = ({ className }) => {
|
|
21125
21272
|
return (jsxs("svg", { className: className, width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsx("path", { d: "M15 3.75H3C2.17157 3.75 1.5 4.42157 1.5 5.25V12.75C1.5 13.5784 2.17157 14.25 3 14.25H15C15.8284 14.25 16.5 13.5784 16.5 12.75V5.25C16.5 4.42157 15.8284 3.75 15 3.75Z", stroke: SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), jsx("path", { d: "M1.5 7.5H16.5", stroke: SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
@@ -21154,48 +21301,72 @@ const PaymentOptionContainer = defaultStyled.div `
|
|
|
21154
21301
|
}
|
|
21155
21302
|
`;
|
|
21156
21303
|
|
|
21157
|
-
|
|
21158
|
-
|
|
21304
|
+
const handleAllErrorFormats$1 = useAllErrorFormats();
|
|
21305
|
+
function Save() {
|
|
21159
21306
|
const accountId = useAccountId();
|
|
21160
|
-
const
|
|
21161
|
-
const
|
|
21162
|
-
const
|
|
21307
|
+
const isMobile = useIsMobile();
|
|
21308
|
+
const { onSavePaymentMethod } = usePaymentFormCallbacks();
|
|
21309
|
+
const [_, setShowPaymentDetailsForm] = useShowPaymentDetails();
|
|
21310
|
+
const { save: handleSave, isSaving } = useSave({
|
|
21163
21311
|
accountId,
|
|
21312
|
+
onSaveSuccess: (response) => {
|
|
21313
|
+
onSavePaymentMethod === null || onSavePaymentMethod === void 0 ? void 0 : onSavePaymentMethod(response);
|
|
21314
|
+
setShowPaymentDetailsForm(false);
|
|
21315
|
+
},
|
|
21316
|
+
onSaveError: handleAllErrorFormats$1,
|
|
21317
|
+
invalidatePaymentMethodsQuery: true,
|
|
21164
21318
|
});
|
|
21165
|
-
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21175
|
-
|
|
21176
|
-
|
|
21177
|
-
|
|
21178
|
-
|
|
21319
|
+
const saveButtonText = isSaving ? 'Saving' : 'Save';
|
|
21320
|
+
return (jsx(Button, { className: "bunny-w-full", disabled: isSaving, loading: isSaving, onClick: handleSave, size: isMobile ? 'large' : 'middle', type: "primary", children: saveButtonText }));
|
|
21321
|
+
}
|
|
21322
|
+
|
|
21323
|
+
const showErrorNotification$6 = useErrorNotification();
|
|
21324
|
+
function PaymentMethodDetailsRoot(props = {}) {
|
|
21325
|
+
var _a, _b;
|
|
21326
|
+
const { footer } = props;
|
|
21327
|
+
const { showPaymentMethodForm, setShowPaymentMethodForm } = usePaymentMethodFormVisibility();
|
|
21328
|
+
const selectedPlugin = useSelectedPlugin();
|
|
21329
|
+
const accountId = useAccountId();
|
|
21330
|
+
const { paymentMethods } = usePaymentMethod({ accountId });
|
|
21331
|
+
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
21332
|
+
function handleClickAddPaymentMethod() {
|
|
21333
|
+
if ((paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length) === 0) {
|
|
21334
|
+
showErrorNotification$6('No payment plugins available', 'Error adding payment method');
|
|
21335
|
+
}
|
|
21336
|
+
else {
|
|
21337
|
+
setShowPaymentMethodForm(true);
|
|
21179
21338
|
}
|
|
21180
21339
|
}
|
|
21340
|
+
// Automatically show the payment method form if there are no payment methods
|
|
21181
21341
|
useEffect(() => {
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
return;
|
|
21185
|
-
if ((paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) && (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) > 0 && !defaultPaymentMethod) {
|
|
21186
|
-
handleSetDefault((_a = paymentMethods[0]) === null || _a === void 0 ? void 0 : _a.id);
|
|
21187
|
-
setDefaultPaymentMethodOnCache(paymentMethods[0]);
|
|
21342
|
+
if ((paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) === 0) {
|
|
21343
|
+
setShowPaymentMethodForm(true);
|
|
21188
21344
|
}
|
|
21189
|
-
}, [
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
|
|
21195
|
-
|
|
21196
|
-
|
|
21197
|
-
|
|
21345
|
+
}, [paymentMethods]);
|
|
21346
|
+
return (jsx("div", { className: "bunny-flex bunny-flex-col", children: jsx(Collapse, { bordered: false, activeKey: showPaymentMethodForm ? '1' : undefined, ghost: true, collapsible: "disabled", destroyOnHidden: true, items: [
|
|
21347
|
+
{
|
|
21348
|
+
key: '1',
|
|
21349
|
+
showArrow: false,
|
|
21350
|
+
label: !showPaymentMethodForm ? (jsx("div", { className: "bunny-pt-2", children: jsx(Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
|
|
21351
|
+
children: (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsx(PaymentMethodSelector, {}), selectedPlugin && (jsx("div", { className: "bunny-flex bunny-flex-col", children: getPaymentMethodForm((_b = (_a = selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0].name) })), footer] })),
|
|
21352
|
+
},
|
|
21353
|
+
] }) }));
|
|
21354
|
+
}
|
|
21355
|
+
const getPaymentMethodForm = (pluginName) => {
|
|
21356
|
+
switch (pluginName) {
|
|
21357
|
+
case 'StripePayment':
|
|
21358
|
+
return jsx(StripeForm, {});
|
|
21359
|
+
case 'DemoPayPayment':
|
|
21360
|
+
return jsx(DemoPayForm, {});
|
|
21361
|
+
default:
|
|
21362
|
+
console.warn('Can not find form for plugin', pluginName);
|
|
21363
|
+
return jsx(Fragment, {});
|
|
21364
|
+
}
|
|
21198
21365
|
};
|
|
21366
|
+
const PaymentMethodDetails = Object.assign(PaymentMethodDetailsRoot, {
|
|
21367
|
+
Cancel,
|
|
21368
|
+
Save
|
|
21369
|
+
});
|
|
21199
21370
|
|
|
21200
21371
|
const query$8 = t(`
|
|
21201
21372
|
query GetCurrentUserData {
|
|
@@ -21253,113 +21424,6 @@ function usePayableCurrency({ payableCurrencyId, accountCurrencyId }) {
|
|
|
21253
21424
|
return { currencyId, isCurrencyIdLoading: isCurrentUserDataLoading };
|
|
21254
21425
|
}
|
|
21255
21426
|
|
|
21256
|
-
function useRemovePaymentMethod(onPaymentMethodRemoved, onError) {
|
|
21257
|
-
const queryClient = useQueryClient();
|
|
21258
|
-
const showErrorNotification = useErrorNotification();
|
|
21259
|
-
const showSuccessNotification = useSuccessNotification();
|
|
21260
|
-
const accountId = useAccountId();
|
|
21261
|
-
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
21262
|
-
const token = useToken();
|
|
21263
|
-
const { apiHost } = useContext(BunnyContext);
|
|
21264
|
-
const removePaymentMethod = useCallback(async (data) => {
|
|
21265
|
-
const plugin = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.find(paymentPlugin => { var _a; return String(paymentPlugin.id) === String((_a = data === null || data === void 0 ? void 0 : data.plugin) === null || _a === void 0 ? void 0 : _a.id); });
|
|
21266
|
-
if (data && plugin) {
|
|
21267
|
-
await invokePlugin({
|
|
21268
|
-
plugin: plugin, // TODO: type the plugin
|
|
21269
|
-
method: 'remove_payment_method',
|
|
21270
|
-
payload: {
|
|
21271
|
-
payment_method_id: data.id,
|
|
21272
|
-
account_id: accountId,
|
|
21273
|
-
},
|
|
21274
|
-
token,
|
|
21275
|
-
apiHost,
|
|
21276
|
-
})
|
|
21277
|
-
.then(() => {
|
|
21278
|
-
showSuccessNotification('Payment method was removed', 'Success');
|
|
21279
|
-
queryClient.invalidateQueries({
|
|
21280
|
-
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
21281
|
-
token,
|
|
21282
|
-
accountId,
|
|
21283
|
-
}),
|
|
21284
|
-
});
|
|
21285
|
-
onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(data);
|
|
21286
|
-
})
|
|
21287
|
-
.catch((error) => {
|
|
21288
|
-
showErrorNotification(error.message, 'Error removing payment method');
|
|
21289
|
-
});
|
|
21290
|
-
}
|
|
21291
|
-
else {
|
|
21292
|
-
const availablePlugins = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.map(plugin => {
|
|
21293
|
-
var _a, _b;
|
|
21294
|
-
const components = plugin.components;
|
|
21295
|
-
return (_b = (_a = components === null || components === void 0 ? void 0 : components.frontend) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name;
|
|
21296
|
-
});
|
|
21297
|
-
onError === null || onError === void 0 ? void 0 : onError(`Either the payment method was not found or the plugin was not present. Available plugins: ${availablePlugins === null || availablePlugins === void 0 ? void 0 : availablePlugins.join(', ')}`);
|
|
21298
|
-
}
|
|
21299
|
-
}, [paymentPlugins, token, apiHost, queryClient, onPaymentMethodRemoved, accountId, onError]);
|
|
21300
|
-
return removePaymentMethod;
|
|
21301
|
-
}
|
|
21302
|
-
|
|
21303
|
-
function useSetDefaultPaymentMethod(onError, onSuccess) {
|
|
21304
|
-
// Context
|
|
21305
|
-
const accountId = useAccountId();
|
|
21306
|
-
const token = useToken();
|
|
21307
|
-
const { apiHost } = useContext(BunnyContext);
|
|
21308
|
-
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
21309
|
-
const { paymentMethods } = usePaymentMethod({ accountId });
|
|
21310
|
-
// Hooks
|
|
21311
|
-
const showErrorNotification = useErrorNotification();
|
|
21312
|
-
const showSuccessNotification = useSuccessNotification();
|
|
21313
|
-
const queryClient = useQueryClient();
|
|
21314
|
-
// State
|
|
21315
|
-
const [loading, setLoading] = useState(false);
|
|
21316
|
-
const setDefaultPaymentMethod = useCallback(async (paymentMethodId) => {
|
|
21317
|
-
const paymentMethod = paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.find(paymentMethod => (paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id) === paymentMethodId);
|
|
21318
|
-
if (paymentMethod === undefined) {
|
|
21319
|
-
showErrorNotification('Payment method not found', 'Error setting default payment method');
|
|
21320
|
-
return;
|
|
21321
|
-
}
|
|
21322
|
-
const plugin = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.find(paymentPlugin => { var _a; return String(paymentPlugin.id) === ((_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.plugin) === null || _a === void 0 ? void 0 : _a.id); }); // TODO: type the response to PluginData
|
|
21323
|
-
if (plugin) {
|
|
21324
|
-
setLoading(true);
|
|
21325
|
-
await invokePlugin({
|
|
21326
|
-
plugin: plugin,
|
|
21327
|
-
method: 'assign_default_payment_method',
|
|
21328
|
-
payload: {
|
|
21329
|
-
payment_method_id: paymentMethod.id,
|
|
21330
|
-
account_id: accountId,
|
|
21331
|
-
},
|
|
21332
|
-
token,
|
|
21333
|
-
apiHost,
|
|
21334
|
-
})
|
|
21335
|
-
.then(() => {
|
|
21336
|
-
var _a;
|
|
21337
|
-
showSuccessNotification(`Payment method ${(_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.identifier} was set as default`, 'Success');
|
|
21338
|
-
onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
|
|
21339
|
-
queryClient.invalidateQueries({
|
|
21340
|
-
queryKey: QueryKeyFactory.accountPaymentMethodsKey({
|
|
21341
|
-
token,
|
|
21342
|
-
accountId,
|
|
21343
|
-
}),
|
|
21344
|
-
});
|
|
21345
|
-
})
|
|
21346
|
-
.catch((error) => {
|
|
21347
|
-
setLoading(false);
|
|
21348
|
-
showErrorNotification(error.message, 'Error removing payment method');
|
|
21349
|
-
})
|
|
21350
|
-
.finally(() => {
|
|
21351
|
-
setLoading(false);
|
|
21352
|
-
});
|
|
21353
|
-
}
|
|
21354
|
-
else {
|
|
21355
|
-
const availablePlugins = paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.map((plugin) => { var _a, _b, _c; return (_c = (_b = (_a = plugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name; });
|
|
21356
|
-
onError === null || onError === void 0 ? void 0 : onError(`Either the payment method was not found or the plugin was not present. Available plugins: ${availablePlugins === null || availablePlugins === void 0 ? void 0 : availablePlugins.join(', ')}`);
|
|
21357
|
-
}
|
|
21358
|
-
}, [paymentPlugins, token, apiHost, queryClient]);
|
|
21359
|
-
return { setDefaultPaymentMethod, loading };
|
|
21360
|
-
}
|
|
21361
|
-
|
|
21362
|
-
const showErrorNotification$6 = useErrorNotification();
|
|
21363
21427
|
const PaymentForm_QuoteFragment = t(`
|
|
21364
21428
|
fragment PaymentForm_QuoteFragment on Quote {
|
|
21365
21429
|
id
|
|
@@ -21367,10 +21431,18 @@ const PaymentForm_QuoteFragment = t(`
|
|
|
21367
21431
|
...PaymentProvider_QuoteFragment
|
|
21368
21432
|
}
|
|
21369
21433
|
`, [PaymentProvider_QuoteFragment]);
|
|
21370
|
-
|
|
21434
|
+
const PaymentForm_InvoiceFragment = t(`
|
|
21435
|
+
fragment PaymentForm_InvoiceFragment on Invoice {
|
|
21436
|
+
id
|
|
21437
|
+
currencyId
|
|
21438
|
+
...PaymentProvider_InvoiceFragment
|
|
21439
|
+
}
|
|
21440
|
+
`, [PaymentProvider_InvoiceFragment]);
|
|
21441
|
+
function PaymentFormRoot({ currencyId: accountCurrencyId, invoice: maskedInvoice, quote: maskedQuote, paymentHold, onPaymentSuccess, onPaymentHoldSuccess, paymentHoldPrecondition, accountId, onSavePaymentMethod, onPaymentMethodRemoved, onSetDefaultPaymentMethod, overrideToken, customCheckoutFunction, children, }) {
|
|
21371
21442
|
var _a;
|
|
21372
21443
|
// Read fragments
|
|
21373
21444
|
const quote = readFragment(PaymentForm_QuoteFragment, maskedQuote);
|
|
21445
|
+
const invoice = readFragment(PaymentForm_InvoiceFragment, maskedInvoice);
|
|
21374
21446
|
const { currencyId, isCurrencyIdLoading } = usePayableCurrency({
|
|
21375
21447
|
payableCurrencyId: (_a = quote === null || quote === void 0 ? void 0 : quote.currencyId) !== null && _a !== void 0 ? _a : invoice === null || invoice === void 0 ? void 0 : invoice.currencyId,
|
|
21376
21448
|
accountCurrencyId,
|
|
@@ -21387,66 +21459,66 @@ function PaymentForm({ currencyId: accountCurrencyId, invoice, quote: maskedQuot
|
|
|
21387
21459
|
const providers = [
|
|
21388
21460
|
[ShowPaymentDetailsProvider, { value: undefined }],
|
|
21389
21461
|
[CustomCheckoutFunctionProvider, { value: customCheckoutFunction }],
|
|
21390
|
-
[
|
|
21462
|
+
[AccountIdProvider, { value: accountId }],
|
|
21391
21463
|
];
|
|
21392
|
-
return (jsx(Fragment, { children: providers.reduceRight((acc, [Provider, props]) => createElement(Provider, props, acc), jsx(OverrideTokenContext.Provider, { value: { overrideToken }, children: jsx(SelectedPluginProvider, { accountId: accountId, children: jsx(
|
|
21464
|
+
return (jsx(Fragment, { children: providers.reduceRight((acc, [Provider, props]) => createElement(Provider, props, acc), jsx(OverrideTokenContext.Provider, { value: { overrideToken }, children: jsx(SelectedPluginProvider, { accountId: accountId, children: jsx(StripeFormProvider, { currencyId: currencyId, accountId: accountId, children: jsx(DemoPayFormProvider, { children: jsx(PaymentFormCallbacksProvider, { value: {
|
|
21465
|
+
onPaymentSuccess,
|
|
21466
|
+
onSetDefaultPaymentMethod,
|
|
21467
|
+
onPaymentMethodRemoved,
|
|
21468
|
+
onSavePaymentMethod,
|
|
21469
|
+
onPaymentHoldSuccess,
|
|
21470
|
+
paymentHoldPrecondition,
|
|
21471
|
+
}, children: jsx(PaymentProvider, { quote: quote, invoice: invoice, paymentHold: paymentHold, children: jsx(PaymentFormContent, { children: children }) }) }) }) }) }) })) }));
|
|
21472
|
+
}
|
|
21473
|
+
// Default layout that uses PaymentFormRoot under the hood when no children are provided.
|
|
21474
|
+
function PaymentFormDefault(props) {
|
|
21475
|
+
console.log('PaymentFormDefault', props);
|
|
21476
|
+
return jsx(PaymentFormRoot, { ...props, children: ({ hasPaymentMethods, isPaymentMethodDetailsOpen, isPayableAvailable, amountDue }) => {
|
|
21477
|
+
const showPayButton = amountDue !== undefined && amountDue > 0 && !isPaymentMethodDetailsOpen && hasPaymentMethods;
|
|
21478
|
+
const checkoutNoPaymentButton = amountDue !== undefined && amountDue === 0;
|
|
21479
|
+
console.log('props.disablePayButton', props.disablePayButton);
|
|
21480
|
+
if (checkoutNoPaymentButton) {
|
|
21481
|
+
return jsx(PaymentForm.CheckoutNoPayment, { className: "bunny-px-4", disabled: props.disablePayButton });
|
|
21482
|
+
}
|
|
21483
|
+
return (jsxs(Fragment, { children: [jsx(PaymentForm.StoredPaymentMethods, { className: "bunny-px-4" }), jsx(PaymentForm.PaymentMethodDetails, { footer: jsxs("div", { className: "bunny-flex bunny-w-full bunny-gap-2", children: [jsx(PaymentForm.PaymentMethodDetails.Cancel, {}), isPayableAvailable && jsx(PaymentForm.Pay, { disabled: props.disablePayButton }), !isPayableAvailable && jsx(PaymentForm.PaymentMethodDetails.Save, {})] }) }), showPayButton && (jsx("div", { className: "bunny-px-4", children: jsx(PaymentForm.Pay, { disabled: props.disablePayButton }) }))] }));
|
|
21484
|
+
} });
|
|
21393
21485
|
}
|
|
21394
|
-
function PaymentFormContent({
|
|
21486
|
+
function PaymentFormContent({ children, }) {
|
|
21395
21487
|
// Context
|
|
21396
21488
|
const [showPaymentMethodForm, setShowPaymentMethodForm] = useShowPaymentDetails();
|
|
21397
|
-
const paymentType = usePaymentType();
|
|
21398
|
-
const isPaying = useIsPaying();
|
|
21399
|
-
const formattedAmountDue = useFormattedAmountDue();
|
|
21400
|
-
const selectedPlugin = useSelectedPlugin();
|
|
21401
|
-
const onPaymentFormSubmit = useHandlePaymentFormSubmit();
|
|
21402
21489
|
const accountId = useAccountId();
|
|
21490
|
+
const { quoteId, invoiceId, amountDue } = usePayable();
|
|
21403
21491
|
// Hooks
|
|
21404
|
-
const {
|
|
21405
|
-
const { paymentMethods: maskedPaymentMethods, isLoading: isPaymentMethodLoading } = usePaymentMethod({ accountId });
|
|
21406
|
-
// Read fragments
|
|
21407
|
-
const paymentMethods = useMemo(() => maskedPaymentMethods === null || maskedPaymentMethods === void 0 ? void 0 : maskedPaymentMethods.map(paymentMethod => readFragment(PaymentForm_PaymentMethodsFragment, paymentMethod)), [maskedPaymentMethods]);
|
|
21492
|
+
const { paymentMethods } = usePaymentMethod({ accountId });
|
|
21408
21493
|
// Derived state
|
|
21409
21494
|
const hasPaymentMethods = (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) && (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) > 0;
|
|
21410
|
-
|
|
21411
|
-
const
|
|
21412
|
-
|
|
21413
|
-
|
|
21414
|
-
|
|
21415
|
-
|
|
21416
|
-
|
|
21417
|
-
|
|
21418
|
-
|
|
21419
|
-
|
|
21420
|
-
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
}
|
|
21428
|
-
else {
|
|
21429
|
-
setShowPaymentMethodForm(true);
|
|
21430
|
-
}
|
|
21431
|
-
}
|
|
21432
|
-
// Automatically show the payment method form if there are no payment methods
|
|
21433
|
-
useEffect(() => {
|
|
21434
|
-
if ((paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) === 0) {
|
|
21435
|
-
setShowPaymentMethodForm(true);
|
|
21436
|
-
}
|
|
21437
|
-
}, [paymentMethods]);
|
|
21438
|
-
if (isPaymentMethodLoading) {
|
|
21439
|
-
return jsx(Skeleton, { active: true, className: "bunny-p-4" });
|
|
21495
|
+
const isPayableAvailable = quoteId !== undefined || invoiceId !== undefined;
|
|
21496
|
+
const renderState = {
|
|
21497
|
+
hasPaymentMethods: !!hasPaymentMethods,
|
|
21498
|
+
isPaymentMethodDetailsOpen: showPaymentMethodForm,
|
|
21499
|
+
isPayableAvailable,
|
|
21500
|
+
amountDue,
|
|
21501
|
+
};
|
|
21502
|
+
const renderedChildren = typeof children === 'function' ? children(renderState) : children;
|
|
21503
|
+
return (jsx(PaymentMethodFormVisibilityProvider, { value: {
|
|
21504
|
+
showPaymentMethodForm,
|
|
21505
|
+
setShowPaymentMethodForm,
|
|
21506
|
+
}, children: jsx("div", { className: "bunny-flex bunny-flex-col bunny-w-full", children: renderedChildren }) }));
|
|
21507
|
+
}
|
|
21508
|
+
// Public component: if children are passed, use PaymentFormRoot directly (render-prop / custom layout).
|
|
21509
|
+
// If no children are passed, fall back to PaymentFormDefault which uses PaymentFormRoot under the hood.
|
|
21510
|
+
function PaymentFormInternal(props) {
|
|
21511
|
+
if (props.children != null) {
|
|
21512
|
+
return jsx(PaymentFormRoot, { ...props });
|
|
21440
21513
|
}
|
|
21441
|
-
return
|
|
21442
|
-
{
|
|
21443
|
-
key: '1',
|
|
21444
|
-
showArrow: false,
|
|
21445
|
-
label: !showPaymentMethodForm ? (jsx("div", { className: "bunny-pt-2", children: jsx(Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
|
|
21446
|
-
children: (jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsx(PaymentMethodSelector, {}), selectedPlugin && (jsx("div", { className: "bunny-flex bunny-flex-col", children: jsx(PaymentMethodDetails, {}) }))] })),
|
|
21447
|
-
},
|
|
21448
|
-
] }), formattedAmountDue !== undefined && !showPaymentMethodForm && hasPaymentMethods ? (jsx("div", { className: "bunny-px-4", children: jsx(CheckoutFooter, {}) })) : null] })) : (jsx(Button, { style: { margin: '0 16px' }, loading: isPaying, onClick: () => onPaymentFormSubmit(), type: "primary", children: isPaying ? 'Processing...' : 'Complete Order' })) }));
|
|
21514
|
+
return jsx(PaymentFormDefault, { ...props });
|
|
21449
21515
|
}
|
|
21516
|
+
const PaymentForm = Object.assign(PaymentFormInternal, {
|
|
21517
|
+
StoredPaymentMethods,
|
|
21518
|
+
Pay,
|
|
21519
|
+
CheckoutNoPayment,
|
|
21520
|
+
PaymentMethodDetails,
|
|
21521
|
+
});
|
|
21450
21522
|
|
|
21451
21523
|
const useAjax = (onError) => {
|
|
21452
21524
|
return async (url, method, callback, token, bodyData) => {
|
|
@@ -21940,8 +22012,8 @@ const PaymentHoldModal = ({ visible, setVisible, formattedQuote: maskedFormatted
|
|
|
21940
22012
|
const [form] = Form.useForm();
|
|
21941
22013
|
return (jsx(StyledModal$2, { centered: true, onCancel: () => {
|
|
21942
22014
|
setVisible(false);
|
|
21943
|
-
}, footer: null, open: visible, width:
|
|
21944
|
-
|
|
22015
|
+
}, footer: null, open: visible, width: 900, className: 'bunny-flex bunny-flex-row bunny-gap-4', children: jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-w-1/2", children: [jsxs("div", { className: "bunny-mt-5 bunny-mx-4", children: [jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxs(Text$z, { className: "bunny-bt-2 bunny-text-sm/5 bunny-text-gray-500", children: ["To accept this quote, approve a payment hold for", ' ', formatCurrency(formattedQuote.amount, formattedQuote.currency || 'null'), ". This amount will be charged to your payment method once the quote is signed."] })] }), jsx("div", { className: "bunny-p-4 bunny-pb-6", children: noSigningPlugins ? jsx(NoSigningPluginsForm, { isVisible: visible, formattedQuote: formattedQuote, form: form }) : null })] }), jsx(VerticalDivider, { className: "bunny-m-4" }), jsx("div", { className: "bunny-mb-3 bunny-w-1/2 bunny-pt-6", children: jsx(PaymentForm, { quote: formattedQuote.quote, paymentHold: {
|
|
22016
|
+
quoteId: formattedQuote.quote.id, // TODO: fix hack. We assume the quote id is always present, but may not be the case
|
|
21945
22017
|
amountToHold: formattedQuote.amount,
|
|
21946
22018
|
}, onPaymentSuccess: () => {
|
|
21947
22019
|
setVisible(false);
|
|
@@ -24132,7 +24204,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
24132
24204
|
removeCoupon(couponCode);
|
|
24133
24205
|
}
|
|
24134
24206
|
});
|
|
24135
|
-
}, children: "Remove coupon(s)" }))] })) : (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsx(Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsx(Text$m, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
24207
|
+
}, children: "Remove coupon(s)" }))] })) : (jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsx(Button, { onClick: handleCheckoutNoPayment, type: "primary", disabled: isFinalizingQuote, loading: isSaving || isFinalizingQuote, children: isSaving ? 'Processing...' : 'Complete order' }), jsx(Text$m, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
24136
24208
|
};
|
|
24137
24209
|
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
24138
24210
|
const isMobile = useIsMobile();
|