@bunnyapp/components 1.8.0-beta.4 → 1.8.0-beta.6
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 +501 -400
- package/dist/cjs/types/src/ajax.d.ts +1 -1
- package/dist/cjs/types/src/components/Checkout/QuoteCheckout.d.ts +2 -2
- package/dist/cjs/types/src/components/PandadocPollingModal.d.ts +1 -1
- package/dist/cjs/types/src/components/Quote/Quote.d.ts +28 -1
- package/dist/cjs/types/src/components/Quote/components/PaymentHoldDisplay.d.ts +18 -0
- package/dist/cjs/types/src/components/Quote/components/QuoteButtons.d.ts +12 -4
- package/dist/cjs/types/src/components/Quote/hooks/{useSendAcceptQuote.d.ts → useAcceptQuote.d.ts} +6 -3
- package/dist/cjs/types/src/components/Quote/hooks/useQuotePaymentHold.d.ts +20 -0
- package/dist/{esm/types/src/graphql → cjs/types/src/components/Quote}/queries/getFormattedQuote.d.ts +6 -1
- package/dist/cjs/types/src/components/Quote/queries/quoteAccept.d.ts +14 -0
- package/dist/{esm/types/src/components/Signup → cjs/types/src/components/Signup/components/CheckoutSummary}/CheckoutSummary.d.ts +1 -1
- package/dist/cjs/types/src/components/Signup/components/CheckoutSummary/hooks/sortQuoteChangeCharges.d.ts +14 -0
- package/dist/cjs/types/src/components/Signup/fragments/Signup_QuoteFragment.d.ts +2 -0
- package/dist/cjs/types/src/components/Signup/hooks/useApplyDefaultCoupon.d.ts +21 -0
- package/dist/cjs/types/src/contexts/InvoiceQuoteContext.d.ts +1 -3
- package/dist/cjs/types/src/graphql/queries/getFormattedInvoice.d.ts +1 -1
- package/dist/cjs/types/src/utils/QueryKeyFactory.d.ts +4 -4
- package/dist/cjs/types/src/utils/couponUtils.d.ts +5 -5
- package/dist/esm/index.js +501 -400
- package/dist/esm/types/src/ajax.d.ts +1 -1
- package/dist/esm/types/src/components/Checkout/QuoteCheckout.d.ts +2 -2
- package/dist/esm/types/src/components/PandadocPollingModal.d.ts +1 -1
- package/dist/esm/types/src/components/Quote/Quote.d.ts +28 -1
- package/dist/esm/types/src/components/Quote/components/PaymentHoldDisplay.d.ts +18 -0
- package/dist/esm/types/src/components/Quote/components/QuoteButtons.d.ts +12 -4
- package/dist/esm/types/src/components/Quote/hooks/{useSendAcceptQuote.d.ts → useAcceptQuote.d.ts} +6 -3
- package/dist/esm/types/src/components/Quote/hooks/useQuotePaymentHold.d.ts +20 -0
- package/dist/{cjs/types/src/graphql → esm/types/src/components/Quote}/queries/getFormattedQuote.d.ts +6 -1
- package/dist/esm/types/src/components/Quote/queries/quoteAccept.d.ts +14 -0
- package/dist/{cjs/types/src/components/Signup → esm/types/src/components/Signup/components/CheckoutSummary}/CheckoutSummary.d.ts +1 -1
- package/dist/esm/types/src/components/Signup/components/CheckoutSummary/hooks/sortQuoteChangeCharges.d.ts +14 -0
- package/dist/esm/types/src/components/Signup/fragments/Signup_QuoteFragment.d.ts +2 -0
- package/dist/esm/types/src/components/Signup/hooks/useApplyDefaultCoupon.d.ts +21 -0
- package/dist/esm/types/src/contexts/InvoiceQuoteContext.d.ts +1 -3
- package/dist/esm/types/src/graphql/queries/getFormattedInvoice.d.ts +1 -1
- package/dist/esm/types/src/utils/QueryKeyFactory.d.ts +4 -4
- package/dist/esm/types/src/utils/couponUtils.d.ts +5 -5
- package/dist/index.d.ts +14 -5
- package/package.json +1 -1
package/dist/cjs/index.js
CHANGED
|
@@ -1283,7 +1283,7 @@ const DEFAULT_CONFIG = {
|
|
|
1283
1283
|
};
|
|
1284
1284
|
|
|
1285
1285
|
// This will be replaced at build time by rollup-plugin-replace
|
|
1286
|
-
const PACKAGE_VERSION = '1.8.0-beta.
|
|
1286
|
+
const PACKAGE_VERSION = '1.8.0-beta.5';
|
|
1287
1287
|
const createRequestHeaders = (token) => {
|
|
1288
1288
|
const headers = createClientDevHeaders({ token });
|
|
1289
1289
|
// Add the components version header
|
|
@@ -19899,7 +19899,7 @@ const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
|
19899
19899
|
};
|
|
19900
19900
|
};
|
|
19901
19901
|
|
|
19902
|
-
const mutation$
|
|
19902
|
+
const mutation$i = t(`
|
|
19903
19903
|
query PaymentPlugins($accountId: ID) {
|
|
19904
19904
|
paymentPlugins(accountId: $accountId) {
|
|
19905
19905
|
enabled
|
|
@@ -19927,7 +19927,7 @@ const mutation$h = t(`
|
|
|
19927
19927
|
// }[];
|
|
19928
19928
|
// };
|
|
19929
19929
|
const getPaymentPlugins = async ({ apiHost, token, accountId, }) => {
|
|
19930
|
-
const response = await execute(mutation$
|
|
19930
|
+
const response = await execute(mutation$i, { apiHost, token }, { accountId });
|
|
19931
19931
|
return response === null || response === void 0 ? void 0 : response.paymentPlugins;
|
|
19932
19932
|
};
|
|
19933
19933
|
const usePaymentPlugins = (accountId) => {
|
|
@@ -21698,6 +21698,102 @@ function ActualInvoice({ hidePaymentForm, onSavePaymentMethod, onPaymentMethodRe
|
|
|
21698
21698
|
} }) }))] }) }));
|
|
21699
21699
|
}
|
|
21700
21700
|
|
|
21701
|
+
const trimGraph = (s) => {
|
|
21702
|
+
return s.replace(/\s+/g, ' ');
|
|
21703
|
+
};
|
|
21704
|
+
const useGraphQL = (navigateOnTokenExpired, apiEndpoint, onError) => {
|
|
21705
|
+
return async (callback, bodyData = null, token, callbackParams) => {
|
|
21706
|
+
bodyData = trimGraph(bodyData);
|
|
21707
|
+
const headers = createClientDevHeaders({ token });
|
|
21708
|
+
const response = await fetch(apiEndpoint + '/graphql', {
|
|
21709
|
+
method: 'post',
|
|
21710
|
+
body: bodyData,
|
|
21711
|
+
headers,
|
|
21712
|
+
});
|
|
21713
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
21714
|
+
return response.json().then((data) => {
|
|
21715
|
+
var _a, _b, _c;
|
|
21716
|
+
if (data.errors) {
|
|
21717
|
+
onError(data.errors[0].message);
|
|
21718
|
+
}
|
|
21719
|
+
else if (((_a = data === null || data === void 0 ? void 0 : data[0]) === null || _a === void 0 ? void 0 : _a.description) === 'Token is expired') {
|
|
21720
|
+
navigateOnTokenExpired();
|
|
21721
|
+
}
|
|
21722
|
+
else if ((_b = data === null || data === void 0 ? void 0 : data[0]) === null || _b === void 0 ? void 0 : _b.description) {
|
|
21723
|
+
throw new Error((_c = data === null || data === void 0 ? void 0 : data[0]) === null || _c === void 0 ? void 0 : _c.description);
|
|
21724
|
+
}
|
|
21725
|
+
return;
|
|
21726
|
+
});
|
|
21727
|
+
}
|
|
21728
|
+
return response
|
|
21729
|
+
.json()
|
|
21730
|
+
.then((data) => callback(data, callbackParams))
|
|
21731
|
+
.catch((err) => {
|
|
21732
|
+
console.error(err);
|
|
21733
|
+
onError(err);
|
|
21734
|
+
});
|
|
21735
|
+
};
|
|
21736
|
+
};
|
|
21737
|
+
const useGraphQLmutation = (navigateOnTokenExpired, apiEndpoint, onError) => {
|
|
21738
|
+
const graphQL = useGraphQL(navigateOnTokenExpired, apiEndpoint, onError);
|
|
21739
|
+
return (mutation, variables, callback, token, callbackParams) => {
|
|
21740
|
+
if (typeof variables === 'object')
|
|
21741
|
+
variables = JSON.stringify(variables);
|
|
21742
|
+
return graphQL(callback, `{ "query": "${mutation}", "variables": ${variables} }`, token, callbackParams);
|
|
21743
|
+
};
|
|
21744
|
+
};
|
|
21745
|
+
|
|
21746
|
+
const POLLING_INTERVAL = 2000;
|
|
21747
|
+
const PandadocPollingModal = ({ isVisible, setVisible, id }) => {
|
|
21748
|
+
const { apiHost, onTokenExpired } = react.useContext(BunnyContext);
|
|
21749
|
+
const token = useToken();
|
|
21750
|
+
const graphQLMutation = useGraphQLmutation(() => {
|
|
21751
|
+
console.log('graphQLMutation navigateOnTokenExpired not yet implemented');
|
|
21752
|
+
}, apiHost || '', () => {
|
|
21753
|
+
console.log('graphQLMutation onError not yet implemented');
|
|
21754
|
+
});
|
|
21755
|
+
const handleAllErrorFormats = useAllErrorFormats$1(onTokenExpired);
|
|
21756
|
+
const [numberOfPolls, setNumberOfPolls] = react.useState(0);
|
|
21757
|
+
const [infoMessage, setInfoMessage] = react.useState('');
|
|
21758
|
+
react.useEffect(() => {
|
|
21759
|
+
if (!isVisible)
|
|
21760
|
+
return;
|
|
21761
|
+
const pollPandadocMutation = () => {
|
|
21762
|
+
const mutation = `mutation quotePollSigningUrl($id: ID) {
|
|
21763
|
+
quotePollSigningUrl(quoteId: $id) {
|
|
21764
|
+
redirectUri
|
|
21765
|
+
status
|
|
21766
|
+
errors
|
|
21767
|
+
infoMessage
|
|
21768
|
+
}
|
|
21769
|
+
}`;
|
|
21770
|
+
const variables = {
|
|
21771
|
+
id,
|
|
21772
|
+
};
|
|
21773
|
+
graphQLMutation(mutation, variables, (rsp) => {
|
|
21774
|
+
if (rsp.errors)
|
|
21775
|
+
handleAllErrorFormats(rsp.errors[0].message);
|
|
21776
|
+
else if (rsp.data.quotePollSigningUrl.status === 'document.sent') {
|
|
21777
|
+
setVisible(false);
|
|
21778
|
+
window.location.href = rsp.data.quotePollSigningUrl.redirectUri;
|
|
21779
|
+
}
|
|
21780
|
+
setInfoMessage(rsp.data.quotePollSigningUrl.infoMessage || '');
|
|
21781
|
+
}, token);
|
|
21782
|
+
setNumberOfPolls(numberOfPolls + 1);
|
|
21783
|
+
};
|
|
21784
|
+
const interval = setInterval(pollPandadocMutation, POLLING_INTERVAL);
|
|
21785
|
+
return () => clearInterval(interval);
|
|
21786
|
+
}, [
|
|
21787
|
+
graphQLMutation,
|
|
21788
|
+
// handleAllErrorFormats,
|
|
21789
|
+
numberOfPolls,
|
|
21790
|
+
token,
|
|
21791
|
+
isVisible,
|
|
21792
|
+
setVisible,
|
|
21793
|
+
]);
|
|
21794
|
+
return (jsxRuntime.jsxs(antd.Modal, { title: "Uploading quote to Pandadoc", open: isVisible, closable: false, footer: null, children: [jsxRuntime.jsxs("div", { className: "bunny-py-4 bunny-text-center", children: ["This may take a few seconds", '.'.repeat(numberOfPolls)] }), jsxRuntime.jsx("div", { className: "bunny-text-center", children: infoMessage })] }));
|
|
21795
|
+
};
|
|
21796
|
+
|
|
21701
21797
|
const usePlugins = ({ apiHost, token }) => {
|
|
21702
21798
|
const response = reactQuery.useQuery({
|
|
21703
21799
|
queryKey: QueryKeyFactory.pluginsKey(token),
|
|
@@ -21820,76 +21916,7 @@ const AcceptQuoteModal = ({ acceptBoxVisible, formattedQuote: maskedFormattedQuo
|
|
|
21820
21916
|
}, open: acceptBoxVisible, title: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length) ? 'Start signing' : 'Accept quote', width: 400, children: jsxRuntime.jsx(NoSigningPluginsForm, { isVisible: acceptBoxVisible, formattedQuote: formattedQuote, form: form }) }));
|
|
21821
21917
|
};
|
|
21822
21918
|
|
|
21823
|
-
const
|
|
21824
|
-
blue: { color: 'var(--bunny-blue-500)', background: 'var(--bunny-blue-200)' },
|
|
21825
|
-
green: {
|
|
21826
|
-
color: 'var(--bunny-green-600)',
|
|
21827
|
-
background: 'var(--bunny-green-200)',
|
|
21828
|
-
},
|
|
21829
|
-
red: { color: 'var(--bunny-red-500)', background: 'var(--bunny-red-200)' },
|
|
21830
|
-
orange: {
|
|
21831
|
-
color: 'var(--bunny-orange-500)',
|
|
21832
|
-
background: 'var(--bunny-orange-200)',
|
|
21833
|
-
},
|
|
21834
|
-
yellow: {
|
|
21835
|
-
color: 'var(--bunny-yellow-500)',
|
|
21836
|
-
background: 'var(--bunny-yellow-200)',
|
|
21837
|
-
},
|
|
21838
|
-
purple: {
|
|
21839
|
-
color: 'var(--bunny-purple-500)',
|
|
21840
|
-
background: 'var(--bunny-purple-200)',
|
|
21841
|
-
},
|
|
21842
|
-
black: { color: 'white', background: 'var(--bunny-black)' },
|
|
21843
|
-
};
|
|
21844
|
-
// This component provides custom styling for antd Tag components without using antd overwrites.
|
|
21845
|
-
// Please use this component instead of the antd Tag component directly to maintain consistent styling.
|
|
21846
|
-
const CustomizedTag = ({ children, color, className, style, }) => {
|
|
21847
|
-
return (jsxRuntime.jsx(antd.Tag, { color: color, style: { ...(color ? tagStyleMap[color] : undefined), ...style }, className: `bunny-m-0 bunny-rounded-full bunny-border-none bunny-whitespace-nowrap ${className}`, children: children }));
|
|
21848
|
-
};
|
|
21849
|
-
|
|
21850
|
-
const useIsExpired = (expiresAt) => dayjs(expiresAt).diff(dayjs(dayjs().format("YYYY-MM-DD"))) < 0;
|
|
21851
|
-
|
|
21852
|
-
dayjs.extend(localizedFormat);
|
|
21853
|
-
const formatDate = (date) => dayjs(date).format('ll');
|
|
21854
|
-
|
|
21855
|
-
const { Text: Text$z } = antd.Typography;
|
|
21856
|
-
const QuoteButtons_FormattedQuoteFragment = t(`
|
|
21857
|
-
fragment QuoteButtons_FormattedQuoteFragment on FormattedQuote {
|
|
21858
|
-
acceptedAt
|
|
21859
|
-
acceptedByName
|
|
21860
|
-
currency
|
|
21861
|
-
amount
|
|
21862
|
-
expiresAt
|
|
21863
|
-
}
|
|
21864
|
-
`);
|
|
21865
|
-
function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobile, hideDownloadButton, id, isAccepting, handleClickAccept, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, paymentHold, isSendAcceptPending, }) {
|
|
21866
|
-
// Read fragments
|
|
21867
|
-
const formattedQuote = readFragment(QuoteButtons_FormattedQuoteFragment, maskedFormattedQuote);
|
|
21868
|
-
const { apiHost } = react.useContext(BunnyContext);
|
|
21869
|
-
const token = useToken();
|
|
21870
|
-
const { secondaryColor } = useBrand();
|
|
21871
|
-
const downloadFile = useDownloadFile(id);
|
|
21872
|
-
const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
|
|
21873
|
-
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
21874
|
-
return (jsxRuntime.jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
21875
|
-
color: secondaryColor,
|
|
21876
|
-
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$z, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxRuntime.jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsxRuntime.jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsxRuntime.jsx(antd.Button, { icon: jsxRuntime.jsx(icons.DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !isAccepted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
21877
|
-
? 'Quote is expired'
|
|
21878
|
-
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
21879
|
-
? 'Start signing'
|
|
21880
|
-
: 'Accept quote' })) : null }))] }))] }));
|
|
21881
|
-
}
|
|
21882
|
-
function PaymentHoldDisplay({ paymentHold, currency, amount, }) {
|
|
21883
|
-
var _a, _b, _c, _d;
|
|
21884
|
-
const paymentMethod = ((_b = (_a = paymentHold.paymentMethod) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.identifier)
|
|
21885
|
-
? (_d = (_c = paymentHold.paymentMethod) === null || _c === void 0 ? void 0 : _c.metadata) === null || _d === void 0 ? void 0 : _d.identifier
|
|
21886
|
-
: 'N/A';
|
|
21887
|
-
const formattedAmount = currency ? formatCurrency(amount, currency) : 'N/A';
|
|
21888
|
-
const expirationDate = paymentHold.expiresAt ? formatDate(paymentHold.expiresAt) : 'N/A';
|
|
21889
|
-
return (jsxRuntime.jsx(antd.Tooltip, { title: `${formattedAmount} will be charged to ${paymentMethod} once the quote is accepted. Hold will be released on ${expirationDate} if not accepted.`, children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(CustomizedTag, { color: 'orange', className: "rounded-md", style: { padding: 6 }, children: ["Hold of ", formattedAmount, " on ****", paymentMethod] }) }) }));
|
|
21890
|
-
}
|
|
21891
|
-
|
|
21892
|
-
const { Title: Title$2, Text: Text$y } = antd.Typography;
|
|
21919
|
+
const { Title: Title$2, Text: Text$z } = antd.Typography;
|
|
21893
21920
|
const showSuccessNotification$2 = useSuccessNotification();
|
|
21894
21921
|
const showErrorNotification$5 = useErrorNotification();
|
|
21895
21922
|
const PaymentHoldModal_FormattedQuoteFragment = t(`
|
|
@@ -21915,7 +21942,7 @@ const PaymentHoldModal = ({ visible, setVisible, formattedQuote: maskedFormatted
|
|
|
21915
21942
|
const [form] = antd.Form.useForm();
|
|
21916
21943
|
return (jsxRuntime.jsx(StyledModal$2, { centered: true, onCancel: () => {
|
|
21917
21944
|
setVisible(false);
|
|
21918
|
-
}, footer: null, open: visible, width: 800, className: 'bunny-flex bunny-flex-row bunny-gap-4', children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-w-1/2", children: [jsxRuntime.jsxs("div", { className: "bunny-mt-5 bunny-mx-4", children: [jsxRuntime.jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxRuntime.jsxs(Text$
|
|
21945
|
+
}, footer: null, open: visible, width: 800, className: 'bunny-flex bunny-flex-row bunny-gap-4', children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-w-1/2", children: [jsxRuntime.jsxs("div", { className: "bunny-mt-5 bunny-mx-4", children: [jsxRuntime.jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxRuntime.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."] })] }), jsxRuntime.jsx("div", { className: "bunny-p-4", children: noSigningPlugins ? jsxRuntime.jsx(NoSigningPluginsForm, { isVisible: visible, formattedQuote: formattedQuote, form: form }) : null })] }), jsxRuntime.jsx(VerticalDivider, { className: "bunny-m-4" }), jsxRuntime.jsx("div", { className: "bunny-mb-3 bunny-w-1/2 bunny-pt-6", children: jsxRuntime.jsx(PaymentForm, { quote: formattedQuote.quote, paymentHoldOptions: {
|
|
21919
21946
|
payToAccept: true,
|
|
21920
21947
|
amountToHold: formattedQuote.amount,
|
|
21921
21948
|
}, onPaymentSuccess: () => {
|
|
@@ -21938,13 +21965,15 @@ const PaymentHoldModal = ({ visible, setVisible, formattedQuote: maskedFormatted
|
|
|
21938
21965
|
token,
|
|
21939
21966
|
}),
|
|
21940
21967
|
});
|
|
21941
|
-
// accept quote automatically
|
|
21942
|
-
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21946
|
-
|
|
21947
|
-
|
|
21968
|
+
// accept quote automatically if no signing plugins are present
|
|
21969
|
+
if (noSigningPlugins) {
|
|
21970
|
+
form
|
|
21971
|
+
.validateFields()
|
|
21972
|
+
.then(changedFields => {
|
|
21973
|
+
sendAccept(changedFields);
|
|
21974
|
+
})
|
|
21975
|
+
.catch(() => { });
|
|
21976
|
+
}
|
|
21948
21977
|
}, paymentHoldPrecondition: async () => {
|
|
21949
21978
|
if (!noSigningPlugins)
|
|
21950
21979
|
return true;
|
|
@@ -21990,232 +22019,125 @@ const StyledModal$2 = (props) => {
|
|
|
21990
22019
|
return jsxRuntime.jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
21991
22020
|
};
|
|
21992
22021
|
|
|
21993
|
-
const
|
|
21994
|
-
query formattedQuote($id: ID) {
|
|
21995
|
-
formattedQuote(id: $id) {
|
|
21996
|
-
quote {
|
|
21997
|
-
documentTemplateId
|
|
21998
|
-
documents {
|
|
21999
|
-
id
|
|
22000
|
-
filename
|
|
22001
|
-
size
|
|
22002
|
-
date
|
|
22003
|
-
url
|
|
22004
|
-
}
|
|
22005
|
-
firstInvoice {
|
|
22006
|
-
id
|
|
22007
|
-
state
|
|
22008
|
-
}
|
|
22009
|
-
payableId
|
|
22010
|
-
id
|
|
22011
|
-
payToAccept
|
|
22012
|
-
currentPaymentHold {
|
|
22013
|
-
createdAt
|
|
22014
|
-
expiresAt
|
|
22015
|
-
id
|
|
22016
|
-
updatedAt
|
|
22017
|
-
paymentMethod {
|
|
22018
|
-
accountId
|
|
22019
|
-
createdAt
|
|
22020
|
-
expirationDate
|
|
22021
|
-
failureCode
|
|
22022
|
-
id
|
|
22023
|
-
isDefault
|
|
22024
|
-
lastSuccess
|
|
22025
|
-
paymentType
|
|
22026
|
-
pluginId
|
|
22027
|
-
state
|
|
22028
|
-
updatedAt
|
|
22029
|
-
metadata {
|
|
22030
|
-
description
|
|
22031
|
-
expiration
|
|
22032
|
-
icon
|
|
22033
|
-
identifier
|
|
22034
|
-
issuer
|
|
22035
|
-
kind
|
|
22036
|
-
}
|
|
22037
|
-
}
|
|
22038
|
-
}
|
|
22039
|
-
}
|
|
22040
|
-
payableId
|
|
22041
|
-
acceptedAt
|
|
22042
|
-
acceptedByName
|
|
22043
|
-
amount
|
|
22044
|
-
amountDue
|
|
22045
|
-
amountsByPeriod {
|
|
22046
|
-
id
|
|
22047
|
-
name
|
|
22048
|
-
amount
|
|
22049
|
-
}
|
|
22050
|
-
billingCity
|
|
22051
|
-
billingCountry
|
|
22052
|
-
billingState
|
|
22053
|
-
billingStreet
|
|
22054
|
-
billingZip
|
|
22055
|
-
contactName
|
|
22056
|
-
currency
|
|
22057
|
-
customerBillingCity
|
|
22058
|
-
customerBillingCountry
|
|
22059
|
-
customerBillingState
|
|
22060
|
-
customerBillingStreet
|
|
22061
|
-
customerBillingZip
|
|
22062
|
-
customerName
|
|
22063
|
-
discount
|
|
22064
|
-
discountValue
|
|
22065
|
-
duration
|
|
22066
|
-
endDate
|
|
22067
|
-
expiresAt
|
|
22068
|
-
html
|
|
22069
|
-
formattedLines {
|
|
22070
|
-
amount
|
|
22071
|
-
amountsByPeriod {
|
|
22072
|
-
quantity
|
|
22073
|
-
id
|
|
22074
|
-
name
|
|
22075
|
-
startDate
|
|
22076
|
-
endDate
|
|
22077
|
-
amount
|
|
22078
|
-
amountsByTier {
|
|
22079
|
-
id
|
|
22080
|
-
tier {
|
|
22081
|
-
starts
|
|
22082
|
-
ends
|
|
22083
|
-
price
|
|
22084
|
-
}
|
|
22085
|
-
quantity
|
|
22086
|
-
amount
|
|
22087
|
-
}
|
|
22088
|
-
prorationRate
|
|
22089
|
-
}
|
|
22090
|
-
billingPeriodEnd
|
|
22091
|
-
billingPeriodStart
|
|
22092
|
-
chargeType
|
|
22093
|
-
discount
|
|
22094
|
-
frequency
|
|
22095
|
-
isRamp
|
|
22096
|
-
periods
|
|
22097
|
-
planName
|
|
22098
|
-
position
|
|
22099
|
-
price
|
|
22100
|
-
priceDecimals
|
|
22101
|
-
priceListChargeId
|
|
22102
|
-
priceListChargeName
|
|
22103
|
-
priceListId
|
|
22104
|
-
priceListName
|
|
22105
|
-
priceTiers {
|
|
22106
|
-
price
|
|
22107
|
-
starts
|
|
22108
|
-
}
|
|
22109
|
-
pricingModel
|
|
22110
|
-
productName
|
|
22111
|
-
prorationRate
|
|
22112
|
-
quantity
|
|
22113
|
-
showProductNameOnLineItem
|
|
22114
|
-
taxCode
|
|
22115
|
-
trialEndDate
|
|
22116
|
-
trialStartDate
|
|
22117
|
-
unitOfMeasure
|
|
22118
|
-
vatCode
|
|
22119
|
-
}
|
|
22120
|
-
netPaymentDays
|
|
22121
|
-
notes
|
|
22122
|
-
number
|
|
22123
|
-
poNumberRequired
|
|
22124
|
-
salesContactEmail
|
|
22125
|
-
sharedAt
|
|
22126
|
-
startDate
|
|
22127
|
-
state
|
|
22128
|
-
subtotal
|
|
22129
|
-
taxAmount
|
|
22130
|
-
taxNumberLabel
|
|
22131
|
-
taxNumberRequired
|
|
22132
|
-
vendorName
|
|
22133
|
-
...PaymentHoldModal_FormattedQuoteFragment
|
|
22134
|
-
...AcceptQuoteModal_FormattedQuoteFragment
|
|
22135
|
-
...QuoteButtons_FormattedQuoteFragment
|
|
22136
|
-
}
|
|
22137
|
-
}
|
|
22138
|
-
`, [
|
|
22139
|
-
PaymentHoldModal_FormattedQuoteFragment,
|
|
22140
|
-
AcceptQuoteModal_FormattedQuoteFragment,
|
|
22141
|
-
QuoteButtons_FormattedQuoteFragment,
|
|
22142
|
-
]);
|
|
22143
|
-
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
22144
|
-
const response = await execute(query$7, { apiHost, token }, { id });
|
|
22145
|
-
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
22146
|
-
};
|
|
22022
|
+
const useIsExpired = (expiresAt) => dayjs(expiresAt).diff(dayjs(dayjs().format("YYYY-MM-DD"))) < 0;
|
|
22147
22023
|
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
const
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
}
|
|
22172
|
-
return;
|
|
22173
|
-
});
|
|
22174
|
-
}
|
|
22175
|
-
return response
|
|
22176
|
-
.json()
|
|
22177
|
-
.then((data) => callback(data, callbackParams))
|
|
22178
|
-
.catch((err) => {
|
|
22179
|
-
console.error(err);
|
|
22180
|
-
onError(err);
|
|
22181
|
-
});
|
|
22182
|
-
};
|
|
22024
|
+
dayjs.extend(localizedFormat);
|
|
22025
|
+
const formatDate = (date) => dayjs(date).format('ll');
|
|
22026
|
+
|
|
22027
|
+
const tagStyleMap = {
|
|
22028
|
+
blue: { color: 'var(--bunny-blue-500)', background: 'var(--bunny-blue-200)' },
|
|
22029
|
+
green: {
|
|
22030
|
+
color: 'var(--bunny-green-600)',
|
|
22031
|
+
background: 'var(--bunny-green-200)',
|
|
22032
|
+
},
|
|
22033
|
+
red: { color: 'var(--bunny-red-500)', background: 'var(--bunny-red-200)' },
|
|
22034
|
+
orange: {
|
|
22035
|
+
color: 'var(--bunny-orange-500)',
|
|
22036
|
+
background: 'var(--bunny-orange-200)',
|
|
22037
|
+
},
|
|
22038
|
+
yellow: {
|
|
22039
|
+
color: 'var(--bunny-yellow-500)',
|
|
22040
|
+
background: 'var(--bunny-yellow-200)',
|
|
22041
|
+
},
|
|
22042
|
+
purple: {
|
|
22043
|
+
color: 'var(--bunny-purple-500)',
|
|
22044
|
+
background: 'var(--bunny-purple-200)',
|
|
22045
|
+
},
|
|
22046
|
+
black: { color: 'white', background: 'var(--bunny-black)' },
|
|
22183
22047
|
};
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
|
|
22188
|
-
variables = JSON.stringify(variables);
|
|
22189
|
-
return graphQL(callback, `{ "query": "${mutation}", "variables": ${variables} }`, token, callbackParams);
|
|
22190
|
-
};
|
|
22048
|
+
// This component provides custom styling for antd Tag components without using antd overwrites.
|
|
22049
|
+
// Please use this component instead of the antd Tag component directly to maintain consistent styling.
|
|
22050
|
+
const CustomizedTag = ({ children, color, className, style, }) => {
|
|
22051
|
+
return (jsxRuntime.jsx(antd.Tag, { color: color, style: { ...(color ? tagStyleMap[color] : undefined), ...style }, className: `bunny-m-0 bunny-rounded-full bunny-border-none bunny-whitespace-nowrap ${className}`, children: children }));
|
|
22191
22052
|
};
|
|
22192
22053
|
|
|
22193
|
-
const
|
|
22194
|
-
|
|
22195
|
-
|
|
22196
|
-
|
|
22054
|
+
const PaymentHoldDisplay_PaymentHoldFragment = t(`
|
|
22055
|
+
fragment PaymentHoldDisplay_PaymentHoldFragment on PaymentHold {
|
|
22056
|
+
expiresAt
|
|
22057
|
+
paymentMethod {
|
|
22058
|
+
metadata {
|
|
22059
|
+
identifier
|
|
22060
|
+
}
|
|
22061
|
+
}
|
|
22062
|
+
}
|
|
22063
|
+
`);
|
|
22064
|
+
function PaymentHoldDisplay({ paymentHold: maskedPaymentHold, currency, amount, }) {
|
|
22065
|
+
var _a, _b, _c, _d;
|
|
22066
|
+
const paymentHold = readFragment(PaymentHoldDisplay_PaymentHoldFragment, maskedPaymentHold);
|
|
22067
|
+
const paymentMethod = ((_b = (_a = paymentHold.paymentMethod) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.identifier)
|
|
22068
|
+
? (_d = (_c = paymentHold.paymentMethod) === null || _c === void 0 ? void 0 : _c.metadata) === null || _d === void 0 ? void 0 : _d.identifier
|
|
22069
|
+
: 'N/A';
|
|
22070
|
+
const formattedAmount = currency ? formatCurrency(amount, currency) : 'N/A';
|
|
22071
|
+
const expirationDate = paymentHold.expiresAt ? formatDate(paymentHold.expiresAt) : 'N/A';
|
|
22072
|
+
return (jsxRuntime.jsx(antd.Tooltip, { title: `${formattedAmount} will be charged to ${paymentMethod} once the quote is accepted.Hold will be released on ${expirationDate} if not accepted.`, children: jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(CustomizedTag, { color: 'orange', className: "rounded-md", style: { padding: 6 }, children: ["Hold of ", formattedAmount, " on ****", paymentMethod] }) }) }));
|
|
22073
|
+
}
|
|
22074
|
+
|
|
22075
|
+
const { Text: Text$y } = antd.Typography;
|
|
22076
|
+
const QuoteButtons_FormattedQuoteFragment = t(`
|
|
22077
|
+
fragment QuoteButtons_FormattedQuoteFragment on FormattedQuote {
|
|
22078
|
+
acceptedAt
|
|
22079
|
+
acceptedByName
|
|
22080
|
+
currency
|
|
22081
|
+
amount
|
|
22082
|
+
expiresAt
|
|
22083
|
+
}
|
|
22084
|
+
`);
|
|
22085
|
+
const PaymentHoldDisplay_QuoteButtonsFragment = t(`
|
|
22086
|
+
fragment PaymentHoldDisplay_QuoteButtonsFragment on PaymentHold {
|
|
22087
|
+
...PaymentHoldDisplay_PaymentHoldFragment
|
|
22088
|
+
}
|
|
22089
|
+
`, [PaymentHoldDisplay_PaymentHoldFragment]);
|
|
22090
|
+
function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobile, hideDownloadButton, id, isAccepting, handleClickAccept, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, paymentHold: maskedPaymentHold, isSendAcceptPending, }) {
|
|
22091
|
+
// Read fragments
|
|
22092
|
+
const formattedQuote = readFragment(QuoteButtons_FormattedQuoteFragment, maskedFormattedQuote);
|
|
22093
|
+
const paymentHold = readFragment(PaymentHoldDisplay_QuoteButtonsFragment, maskedPaymentHold);
|
|
22094
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
22095
|
+
const token = useToken();
|
|
22096
|
+
const { secondaryColor } = useBrand();
|
|
22097
|
+
const downloadFile = useDownloadFile(id);
|
|
22098
|
+
const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
|
|
22099
|
+
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
22100
|
+
return (jsxRuntime.jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
22101
|
+
color: secondaryColor,
|
|
22102
|
+
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxRuntime.jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsxRuntime.jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsxRuntime.jsx(antd.Button, { icon: jsxRuntime.jsx(icons.DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !isAccepted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
22103
|
+
? 'Quote is expired'
|
|
22104
|
+
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
22105
|
+
? 'Start signing'
|
|
22106
|
+
: 'Accept quote' })) : null }))] }))] }));
|
|
22107
|
+
}
|
|
22108
|
+
|
|
22109
|
+
const mutation$h = t(`
|
|
22110
|
+
mutation QuoteAccept(
|
|
22111
|
+
$name: String!
|
|
22112
|
+
$title: String!
|
|
22113
|
+
$poNumber: String
|
|
22114
|
+
$taxNumber: String
|
|
22115
|
+
$quoteId: ID
|
|
22116
|
+
) {
|
|
22117
|
+
quoteAccept(
|
|
22118
|
+
name: $name
|
|
22119
|
+
title: $title
|
|
22120
|
+
poNumber: $poNumber
|
|
22121
|
+
taxNumber: $taxNumber
|
|
22122
|
+
quoteId: $quoteId
|
|
22123
|
+
) {
|
|
22197
22124
|
errors
|
|
22198
22125
|
}
|
|
22199
22126
|
}
|
|
22200
|
-
|
|
22201
|
-
const quoteAccept = async ({ quoteId, apiHost, token, changedFormItems
|
|
22127
|
+
`);
|
|
22128
|
+
const quoteAccept = async ({ quoteId, apiHost, token, changedFormItems }) => {
|
|
22202
22129
|
var _a, _b;
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
token,
|
|
22210
|
-
vars,
|
|
22211
|
-
apiHost,
|
|
22130
|
+
return await execute(mutation$h, { apiHost, token }, {
|
|
22131
|
+
name: changedFormItems.name,
|
|
22132
|
+
title: changedFormItems.title,
|
|
22133
|
+
poNumber: (_a = changedFormItems.poNumber) !== null && _a !== void 0 ? _a : null,
|
|
22134
|
+
taxNumber: (_b = changedFormItems.taxNumber) !== null && _b !== void 0 ? _b : null,
|
|
22135
|
+
quoteId: quoteId !== null && quoteId !== void 0 ? quoteId : null,
|
|
22212
22136
|
});
|
|
22213
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAccept) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22214
|
-
if (errors)
|
|
22215
|
-
throw errors;
|
|
22216
|
-
return (_b = response.quoteAccept) === null || _b === void 0 ? void 0 : _b.quote;
|
|
22217
22137
|
};
|
|
22218
|
-
|
|
22138
|
+
|
|
22139
|
+
const handleAllErrorFormats = useAllErrorFormats();
|
|
22140
|
+
const useAcceptQuote = ({ quoteId, apiHost, token, onQuoteAccepted, }) => {
|
|
22219
22141
|
// Hooks
|
|
22220
22142
|
const graphQLMutation = useGraphQLmutation(() => {
|
|
22221
22143
|
console.log('navigate in useGraphQLmutation in useSendAcceptQuote is not yet implemented');
|
|
@@ -22307,6 +22229,33 @@ const useSendAcceptQuote = ({ quoteId, apiHost, token, onQuoteAccepted, }) => {
|
|
|
22307
22229
|
};
|
|
22308
22230
|
};
|
|
22309
22231
|
|
|
22232
|
+
const useQuotePaymentHold_FormattedQuoteFragment = t(`
|
|
22233
|
+
fragment useQuotePaymentHold_FormattedQuoteFragment on FormattedQuote {
|
|
22234
|
+
quote {
|
|
22235
|
+
payToAccept
|
|
22236
|
+
currentPaymentHold {
|
|
22237
|
+
id
|
|
22238
|
+
}
|
|
22239
|
+
}
|
|
22240
|
+
}
|
|
22241
|
+
`);
|
|
22242
|
+
const useQuotePaymentHold = (maskedFormattedQuote) => {
|
|
22243
|
+
var _a, _b;
|
|
22244
|
+
const [paymentHoldModalVisible, setPaymentHoldModalVisible] = react.useState(false);
|
|
22245
|
+
const formattedQuote = maskedFormattedQuote
|
|
22246
|
+
? readFragment(useQuotePaymentHold_FormattedQuoteFragment, maskedFormattedQuote)
|
|
22247
|
+
: undefined;
|
|
22248
|
+
const shouldDoPaymentHold = ((_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.payToAccept) === true;
|
|
22249
|
+
const currentPaymentHold = (_b = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.currentPaymentHold;
|
|
22250
|
+
return {
|
|
22251
|
+
// paymentHold: currentPaymentHold ?? undefined,
|
|
22252
|
+
paymentHoldModalVisible,
|
|
22253
|
+
setPaymentHoldModalVisible,
|
|
22254
|
+
shouldDoPaymentHold,
|
|
22255
|
+
paymentHoldCompleted: currentPaymentHold ? true : false,
|
|
22256
|
+
};
|
|
22257
|
+
};
|
|
22258
|
+
|
|
22310
22259
|
const NavigationContext = react.createContext({});
|
|
22311
22260
|
|
|
22312
22261
|
const useSigningComplete = ({ data, token }) => {
|
|
@@ -22322,63 +22271,186 @@ const useSigningComplete = ({ data, token }) => {
|
|
|
22322
22271
|
}, [data, eventParam, queryClient, token]);
|
|
22323
22272
|
};
|
|
22324
22273
|
|
|
22325
|
-
const
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
|
|
22345
|
-
|
|
22346
|
-
|
|
22274
|
+
const query$7 = t(`
|
|
22275
|
+
query formattedQuote($id: ID) {
|
|
22276
|
+
formattedQuote(id: $id) {
|
|
22277
|
+
quote {
|
|
22278
|
+
documentTemplateId
|
|
22279
|
+
documents {
|
|
22280
|
+
id
|
|
22281
|
+
filename
|
|
22282
|
+
size
|
|
22283
|
+
date
|
|
22284
|
+
url
|
|
22285
|
+
}
|
|
22286
|
+
firstInvoice {
|
|
22287
|
+
id
|
|
22288
|
+
state
|
|
22289
|
+
}
|
|
22290
|
+
payableId
|
|
22291
|
+
id
|
|
22292
|
+
payToAccept
|
|
22293
|
+
currentPaymentHold {
|
|
22294
|
+
createdAt
|
|
22295
|
+
expiresAt
|
|
22296
|
+
id
|
|
22297
|
+
updatedAt
|
|
22298
|
+
paymentMethod {
|
|
22299
|
+
accountId
|
|
22300
|
+
createdAt
|
|
22301
|
+
expirationDate
|
|
22302
|
+
failureCode
|
|
22303
|
+
id
|
|
22304
|
+
isDefault
|
|
22305
|
+
lastSuccess
|
|
22306
|
+
paymentType
|
|
22307
|
+
pluginId
|
|
22308
|
+
state
|
|
22309
|
+
updatedAt
|
|
22310
|
+
metadata {
|
|
22311
|
+
description
|
|
22312
|
+
expiration
|
|
22313
|
+
icon
|
|
22314
|
+
identifier
|
|
22315
|
+
issuer
|
|
22316
|
+
kind
|
|
22317
|
+
}
|
|
22318
|
+
}
|
|
22319
|
+
...PaymentHoldDisplay_QuoteButtonsFragment
|
|
22320
|
+
}
|
|
22347
22321
|
}
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
|
|
22352
|
-
|
|
22353
|
-
|
|
22354
|
-
|
|
22355
|
-
|
|
22356
|
-
|
|
22357
|
-
|
|
22358
|
-
|
|
22359
|
-
|
|
22360
|
-
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
22366
|
-
|
|
22367
|
-
|
|
22368
|
-
|
|
22369
|
-
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
22373
|
-
|
|
22322
|
+
payableId
|
|
22323
|
+
acceptedAt
|
|
22324
|
+
acceptedByName
|
|
22325
|
+
amount
|
|
22326
|
+
amountDue
|
|
22327
|
+
amountsByPeriod {
|
|
22328
|
+
id
|
|
22329
|
+
name
|
|
22330
|
+
amount
|
|
22331
|
+
}
|
|
22332
|
+
billingCity
|
|
22333
|
+
billingCountry
|
|
22334
|
+
billingState
|
|
22335
|
+
billingStreet
|
|
22336
|
+
billingZip
|
|
22337
|
+
contactName
|
|
22338
|
+
currency
|
|
22339
|
+
customerBillingCity
|
|
22340
|
+
customerBillingCountry
|
|
22341
|
+
customerBillingState
|
|
22342
|
+
customerBillingStreet
|
|
22343
|
+
customerBillingZip
|
|
22344
|
+
customerName
|
|
22345
|
+
discount
|
|
22346
|
+
discountValue
|
|
22347
|
+
duration
|
|
22348
|
+
endDate
|
|
22349
|
+
expiresAt
|
|
22350
|
+
html
|
|
22351
|
+
formattedLines {
|
|
22352
|
+
amount
|
|
22353
|
+
amountsByPeriod {
|
|
22354
|
+
quantity
|
|
22355
|
+
id
|
|
22356
|
+
name
|
|
22357
|
+
startDate
|
|
22358
|
+
endDate
|
|
22359
|
+
amount
|
|
22360
|
+
amountsByTier {
|
|
22361
|
+
id
|
|
22362
|
+
tier {
|
|
22363
|
+
starts
|
|
22364
|
+
ends
|
|
22365
|
+
price
|
|
22366
|
+
}
|
|
22367
|
+
quantity
|
|
22368
|
+
amount
|
|
22369
|
+
}
|
|
22370
|
+
prorationRate
|
|
22371
|
+
}
|
|
22372
|
+
billingPeriodEnd
|
|
22373
|
+
billingPeriodStart
|
|
22374
|
+
chargeType
|
|
22375
|
+
discount
|
|
22376
|
+
frequency
|
|
22377
|
+
isRamp
|
|
22378
|
+
periods
|
|
22379
|
+
planName
|
|
22380
|
+
position
|
|
22381
|
+
price
|
|
22382
|
+
priceDecimals
|
|
22383
|
+
priceListChargeId
|
|
22384
|
+
priceListChargeName
|
|
22385
|
+
priceListId
|
|
22386
|
+
priceListName
|
|
22387
|
+
priceTiers {
|
|
22388
|
+
price
|
|
22389
|
+
starts
|
|
22390
|
+
}
|
|
22391
|
+
pricingModel
|
|
22392
|
+
productName
|
|
22393
|
+
prorationRate
|
|
22394
|
+
quantity
|
|
22395
|
+
showProductNameOnLineItem
|
|
22396
|
+
taxCode
|
|
22397
|
+
trialEndDate
|
|
22398
|
+
trialStartDate
|
|
22399
|
+
unitOfMeasure
|
|
22400
|
+
vatCode
|
|
22401
|
+
}
|
|
22402
|
+
netPaymentDays
|
|
22403
|
+
notes
|
|
22404
|
+
number
|
|
22405
|
+
poNumberRequired
|
|
22406
|
+
salesContactEmail
|
|
22407
|
+
sharedAt
|
|
22408
|
+
startDate
|
|
22409
|
+
state
|
|
22410
|
+
subtotal
|
|
22411
|
+
taxAmount
|
|
22412
|
+
taxNumberLabel
|
|
22413
|
+
taxNumberRequired
|
|
22414
|
+
vendorName
|
|
22415
|
+
...useQuotePaymentHold_FormattedQuoteFragment
|
|
22416
|
+
...PaymentHoldModal_FormattedQuoteFragment
|
|
22417
|
+
...AcceptQuoteModal_FormattedQuoteFragment
|
|
22418
|
+
...QuoteButtons_FormattedQuoteFragment
|
|
22419
|
+
}
|
|
22420
|
+
}
|
|
22421
|
+
`, [
|
|
22422
|
+
useQuotePaymentHold_FormattedQuoteFragment,
|
|
22423
|
+
PaymentHoldModal_FormattedQuoteFragment,
|
|
22424
|
+
AcceptQuoteModal_FormattedQuoteFragment,
|
|
22425
|
+
QuoteButtons_FormattedQuoteFragment,
|
|
22426
|
+
PaymentHoldDisplay_QuoteButtonsFragment,
|
|
22427
|
+
]);
|
|
22428
|
+
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
22429
|
+
const response = await execute(query$7, { apiHost, token }, { id });
|
|
22430
|
+
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
22374
22431
|
};
|
|
22375
22432
|
|
|
22376
22433
|
const showErrorNotification$4 = useErrorNotification();
|
|
22377
|
-
|
|
22378
|
-
|
|
22379
|
-
|
|
22380
|
-
|
|
22381
|
-
|
|
22434
|
+
t(`
|
|
22435
|
+
fragment Quote_PaymentHoldFragment on FormattedQuote {
|
|
22436
|
+
quote {
|
|
22437
|
+
currentPaymentHold {
|
|
22438
|
+
...PaymentHoldDisplay_QuoteButtonsFragment
|
|
22439
|
+
}
|
|
22440
|
+
firstInvoice {
|
|
22441
|
+
id
|
|
22442
|
+
}
|
|
22443
|
+
}
|
|
22444
|
+
}
|
|
22445
|
+
`, [PaymentHoldDisplay_QuoteButtonsFragment]);
|
|
22446
|
+
t(`
|
|
22447
|
+
fragment OnQuoteLoadedFragment on FormattedQuote {
|
|
22448
|
+
vendorName
|
|
22449
|
+
quote {
|
|
22450
|
+
id
|
|
22451
|
+
}
|
|
22452
|
+
}
|
|
22453
|
+
`);
|
|
22382
22454
|
function Quote({ id, invoiceQuoteViewComponent, onInvoiceDownloadError, onPaymentSuccess, shadow = 'shadow-md', className, hideDownloadButton = false, onQuoteLoaded, onQuoteAccepted, onQuoteUnavailableError, suppressQuoteUnavailableErrorNotification = false, }) {
|
|
22383
22455
|
return (jsxRuntime.jsx(InvoiceQuoteContext.Provider, { value: {
|
|
22384
22456
|
id,
|
|
@@ -22388,30 +22460,16 @@ function Quote({ id, invoiceQuoteViewComponent, onInvoiceDownloadError, onPaymen
|
|
|
22388
22460
|
shadow,
|
|
22389
22461
|
className,
|
|
22390
22462
|
hideDownloadButton,
|
|
22391
|
-
onQuoteLoaded,
|
|
22392
22463
|
onQuoteUnavailableError,
|
|
22393
22464
|
suppressQuoteUnavailableErrorNotification,
|
|
22394
|
-
}, children: jsxRuntime.jsx(ActualQuote, { onQuoteAccepted: onQuoteAccepted }) }));
|
|
22465
|
+
}, children: jsxRuntime.jsx(ActualQuote, { onQuoteAccepted: onQuoteAccepted, onQuoteLoaded: onQuoteLoaded }) }));
|
|
22395
22466
|
}
|
|
22396
|
-
|
|
22397
|
-
var _a, _b;
|
|
22398
|
-
const [paymentHoldModalVisible, setPaymentHoldModalVisible] = react.useState(false);
|
|
22399
|
-
const shouldDoPaymentHold = ((_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.payToAccept) == true;
|
|
22400
|
-
const currentPaymentHold = (_b = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.currentPaymentHold;
|
|
22401
|
-
return {
|
|
22402
|
-
paymentHold: currentPaymentHold,
|
|
22403
|
-
paymentHoldModalVisible,
|
|
22404
|
-
setPaymentHoldModalVisible,
|
|
22405
|
-
shouldDoPaymentHold,
|
|
22406
|
-
paymentHoldCompleted: currentPaymentHold ? true : false,
|
|
22407
|
-
};
|
|
22408
|
-
};
|
|
22409
|
-
function ActualQuote({ onQuoteAccepted }) {
|
|
22410
|
-
var _a, _b, _c, _d, _e, _f;
|
|
22467
|
+
function ActualQuote({ onQuoteAccepted, onQuoteLoaded }) {
|
|
22468
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
22411
22469
|
// Context
|
|
22412
22470
|
const { apiHost } = react.useContext(BunnyContext);
|
|
22413
22471
|
const token = useToken();
|
|
22414
|
-
const { className, id, hideDownloadButton,
|
|
22472
|
+
const { className, id, hideDownloadButton, onQuoteUnavailableError, suppressQuoteUnavailableErrorNotification } = react.useContext(InvoiceQuoteContext);
|
|
22415
22473
|
// Queries
|
|
22416
22474
|
const { data: formattedQuote, isLoading, error } = reactQuery.useQuery({
|
|
22417
22475
|
queryKey: QueryKeyFactory.createQuoteKey({ id, token }),
|
|
@@ -22421,7 +22479,7 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22421
22479
|
placeholderData: reactQuery.keepPreviousData,
|
|
22422
22480
|
});
|
|
22423
22481
|
// Hooks
|
|
22424
|
-
const { acceptBoxVisible, isAccepting, sendAccept, setAcceptBoxVisible, setIsAccepting, startAcceptance, pandadocPollingModalVisible, setPandadocPollingModalVisible, isSendAcceptPending, } =
|
|
22482
|
+
const { acceptBoxVisible, isAccepting, sendAccept, setAcceptBoxVisible, setIsAccepting, startAcceptance, pandadocPollingModalVisible, setPandadocPollingModalVisible, isSendAcceptPending, } = useAcceptQuote({
|
|
22425
22483
|
token,
|
|
22426
22484
|
apiHost,
|
|
22427
22485
|
quoteId: id,
|
|
@@ -22431,7 +22489,7 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22431
22489
|
const isMobile = useIsMobile();
|
|
22432
22490
|
react.useEffect(() => {
|
|
22433
22491
|
if (formattedQuote) {
|
|
22434
|
-
onQuoteLoaded === null || onQuoteLoaded === void 0 ? void 0 : onQuoteLoaded(formattedQuote);
|
|
22492
|
+
onQuoteLoaded === null || onQuoteLoaded === void 0 ? void 0 : onQuoteLoaded(formattedQuote);
|
|
22435
22493
|
}
|
|
22436
22494
|
}, [formattedQuote]);
|
|
22437
22495
|
react.useEffect(() => {
|
|
@@ -22447,7 +22505,8 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22447
22505
|
}
|
|
22448
22506
|
}, [error]);
|
|
22449
22507
|
// Payment hold stuff here
|
|
22450
|
-
const { paymentHoldModalVisible, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted,
|
|
22508
|
+
const { paymentHoldModalVisible, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, } = useQuotePaymentHold(formattedQuote);
|
|
22509
|
+
const paymentHold = (_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.currentPaymentHold;
|
|
22451
22510
|
const handleClickAccept = () => {
|
|
22452
22511
|
if (shouldDoPaymentHold && !paymentHoldCompleted) {
|
|
22453
22512
|
setPaymentHoldModalVisible(true);
|
|
@@ -22461,12 +22520,12 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22461
22520
|
}
|
|
22462
22521
|
// Derived state
|
|
22463
22522
|
const isAccepted = formattedQuote.state === 'ACCEPTED';
|
|
22464
|
-
const firstInvoice = (
|
|
22523
|
+
const firstInvoice = (_b = formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.firstInvoice;
|
|
22465
22524
|
if ((firstInvoice === null || firstInvoice === void 0 ? void 0 : firstInvoice.state) === 'PAID' && paymentHoldCompleted) {
|
|
22466
22525
|
return jsxRuntime.jsx(Invoice, { id: firstInvoice.id });
|
|
22467
22526
|
}
|
|
22468
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-4 ${isMobile ? 'bunny-w-full bunny-overflow-hidden' : ''} ${className}`, children: [jsxRuntime.jsx(QuoteButtons, { isAccepted: isAccepted, formattedQuote: formattedQuote, isMobile: isMobile, hideDownloadButton: hideDownloadButton, id: id, isAccepting: isAccepting, handleClickAccept: handleClickAccept, setPaymentHoldModalVisible: setPaymentHoldModalVisible, shouldDoPaymentHold: shouldDoPaymentHold, paymentHoldCompleted: paymentHoldCompleted, paymentHold: paymentHold, isSendAcceptPending: isSendAcceptPending }), jsxRuntime.jsx(InvoiceQuoteView, { html: formattedQuote.html, targetUrl: ((
|
|
22469
|
-
((
|
|
22527
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-4 ${isMobile ? 'bunny-w-full bunny-overflow-hidden' : ''} ${className}`, children: [jsxRuntime.jsx(QuoteButtons, { isAccepted: isAccepted, formattedQuote: formattedQuote, isMobile: isMobile, hideDownloadButton: hideDownloadButton, id: id, isAccepting: isAccepting, handleClickAccept: handleClickAccept, setPaymentHoldModalVisible: setPaymentHoldModalVisible, shouldDoPaymentHold: shouldDoPaymentHold, paymentHoldCompleted: paymentHoldCompleted, paymentHold: paymentHold, isSendAcceptPending: isSendAcceptPending }), jsxRuntime.jsx(InvoiceQuoteView, { html: formattedQuote.html, targetUrl: ((_c = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _c === void 0 ? void 0 : _c.documentTemplateId) ? `/pdf/quote` : undefined, children: ((_e = (_d = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _d === void 0 ? void 0 : _d.documents) === null || _e === void 0 ? void 0 : _e.length) &&
|
|
22528
|
+
((_g = (_f = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _f === void 0 ? void 0 : _f.documents) === null || _g === void 0 ? void 0 : _g.length) > 0 ? (jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: formattedQuote.quote.documents.map((doc, index) => {
|
|
22470
22529
|
return (jsxRuntime.jsx(antd.Button, { download: doc.filename, href: doc.url, type: "link", children: doc.filename }, index));
|
|
22471
22530
|
}) })) : null })] }), jsxRuntime.jsx(AcceptQuoteModal, { acceptBoxVisible: acceptBoxVisible, formattedQuote: formattedQuote, setAcceptBoxVisible: setAcceptBoxVisible, setIsAccepting: setIsAccepting, sendAccept: sendAccept, isSendAcceptPending: isSendAcceptPending }), jsxRuntime.jsx(PaymentHoldModal, { visible: paymentHoldModalVisible, setVisible: setPaymentHoldModalVisible, formattedQuote: formattedQuote, sendAccept: sendAccept }), jsxRuntime.jsx(PandadocPollingModal, { isVisible: pandadocPollingModalVisible, setVisible: setPandadocPollingModalVisible, id: id })] }));
|
|
22472
22531
|
}
|
|
@@ -22955,15 +23014,15 @@ function QuotesWrapper() {
|
|
|
22955
23014
|
return (jsxRuntime.jsx(TransactionsDisplay, { transactions: quotesAsTransactions, onSearchValueChanged: setSearch, search: search }));
|
|
22956
23015
|
}
|
|
22957
23016
|
|
|
22958
|
-
const
|
|
22959
|
-
fragment
|
|
23017
|
+
const canApplyCoupons_QuoteFragment = t(`
|
|
23018
|
+
fragment canApplyCoupons_QuoteFragment on Quote {
|
|
22960
23019
|
id
|
|
22961
23020
|
kind
|
|
22962
23021
|
amountDue
|
|
22963
23022
|
}
|
|
22964
23023
|
`, []);
|
|
22965
|
-
const
|
|
22966
|
-
fragment
|
|
23024
|
+
const canApplyCoupons_SubscriptionFragment = t(`
|
|
23025
|
+
fragment canApplyCoupons_SubscriptionFragment on Subscription {
|
|
22967
23026
|
id
|
|
22968
23027
|
state
|
|
22969
23028
|
charges {
|
|
@@ -22971,10 +23030,10 @@ const shouldShowCouponEditor_SubscriptionFragment = t(`
|
|
|
22971
23030
|
}
|
|
22972
23031
|
}
|
|
22973
23032
|
`, []);
|
|
22974
|
-
function
|
|
23033
|
+
function canApplyCoupons(maskedQuote, activeCouponsExist, maskedUpgradingSubscription) {
|
|
22975
23034
|
var _a, _b;
|
|
22976
|
-
const quote = readFragment(
|
|
22977
|
-
const upgradingSubscription = readFragment(
|
|
23035
|
+
const quote = readFragment(canApplyCoupons_QuoteFragment, maskedQuote);
|
|
23036
|
+
const upgradingSubscription = readFragment(canApplyCoupons_SubscriptionFragment, maskedUpgradingSubscription);
|
|
22978
23037
|
const upgradingFromTrial = ((_a = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') ||
|
|
22979
23038
|
((_b = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) ===
|
|
22980
23039
|
t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
@@ -22992,7 +23051,9 @@ function shouldShowCouponEditor(maskedQuote, activeCouponsExist, maskedUpgrading
|
|
|
22992
23051
|
return false;
|
|
22993
23052
|
}
|
|
22994
23053
|
if (quoteKindIsValid) {
|
|
22995
|
-
|
|
23054
|
+
const result = activeCouponsExist &&
|
|
23055
|
+
(upgradingFromTrial || upgradingFromFree() || signingUpForNewSubscription);
|
|
23056
|
+
return result;
|
|
22996
23057
|
}
|
|
22997
23058
|
return false;
|
|
22998
23059
|
}
|
|
@@ -23004,6 +23065,27 @@ function CouponEditor({ className, onAddCoupon, isAddingCoupon, couponCode, setC
|
|
|
23004
23065
|
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 ${className}`, children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2", children: [jsxRuntime.jsx(antd.Input, { value: couponCode, onChange: e => setCouponCode(e.target.value), placeholder: "Coupon code", disabled: isAddingCoupon, size: "small" }), jsxRuntime.jsx(antd.Button, { loading: isAddingCoupon, type: "primary", onClick: handleAddCoupon, disabled: couponCode.length === 0, children: "Apply" })] }) }));
|
|
23005
23066
|
}
|
|
23006
23067
|
|
|
23068
|
+
t(`
|
|
23069
|
+
fragment sortQuoteChangeCharges_QuoteChargeFragment on QuoteCharge {
|
|
23070
|
+
kind
|
|
23071
|
+
}
|
|
23072
|
+
`, []);
|
|
23073
|
+
/**
|
|
23074
|
+
* Sorts quote change charges so that coupon charges appear at the end of the list.
|
|
23075
|
+
* Uses a generic type so the full charge shape is preserved.
|
|
23076
|
+
*/
|
|
23077
|
+
function sortQuoteChangeCharges(charges) {
|
|
23078
|
+
return [...charges].sort((chargeA, chargeB) => {
|
|
23079
|
+
const aIsCoupon = chargeA.kind === 'COUPON';
|
|
23080
|
+
const bIsCoupon = chargeB.kind === 'COUPON';
|
|
23081
|
+
if (aIsCoupon && !bIsCoupon)
|
|
23082
|
+
return 1;
|
|
23083
|
+
if (!aIsCoupon && bIsCoupon)
|
|
23084
|
+
return -1;
|
|
23085
|
+
return 0;
|
|
23086
|
+
});
|
|
23087
|
+
}
|
|
23088
|
+
|
|
23007
23089
|
const { Text: Text$r } = antd.Typography;
|
|
23008
23090
|
const CheckoutSummary_PriceListFragment = t(`
|
|
23009
23091
|
fragment CheckoutSummary_PriceListFragment on PriceList {
|
|
@@ -23033,14 +23115,14 @@ const CheckoutSummary_QuoteFragment = t(`
|
|
|
23033
23115
|
currencyId
|
|
23034
23116
|
}
|
|
23035
23117
|
}
|
|
23036
|
-
...
|
|
23118
|
+
...canApplyCoupons_QuoteFragment
|
|
23037
23119
|
}
|
|
23038
|
-
`, [
|
|
23120
|
+
`, [canApplyCoupons_QuoteFragment]);
|
|
23039
23121
|
function CheckoutSummary({ quote: maskedQuote, className, onAddCoupon, onRemoveCoupon, isRemovingCoupon, priceList: maskedPriceList, isAddingCoupon, couponCode, setCouponCode, activeCouponsExist, }) {
|
|
23040
23122
|
var _a, _b;
|
|
23041
23123
|
const priceList = readFragment(CheckoutSummary_PriceListFragment, maskedPriceList);
|
|
23042
23124
|
const quote = readFragment(CheckoutSummary_QuoteFragment, maskedQuote);
|
|
23043
|
-
return (jsxRuntime.jsxs("div", { className: `${className} bunny-space-y-4`, children: [jsxRuntime.jsxs(Text$r, { children: [jsxRuntime.jsxs("div", { className: "bunny-text-lg bunny-font-medium bunny-mb-4", children: ["Checkout summary - ", (_a = priceList === null || priceList === void 0 ? void 0 : priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList === null || priceList === void 0 ? void 0 : priceList.name] }), jsxRuntime.jsx("div", { className: "bunny-space-y-4", children: (_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.map(quoteChange => quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges.map(charge => {
|
|
23125
|
+
return (jsxRuntime.jsxs("div", { className: `${className} bunny-space-y-4`, children: [jsxRuntime.jsxs(Text$r, { children: [jsxRuntime.jsxs("div", { className: "bunny-text-lg bunny-font-medium bunny-mb-4", children: ["Checkout summary - ", (_a = priceList === null || priceList === void 0 ? void 0 : priceList.product) === null || _a === void 0 ? void 0 : _a.name, " ", priceList === null || priceList === void 0 ? void 0 : priceList.name] }), jsxRuntime.jsx("div", { className: "bunny-space-y-4", children: (_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.map(quoteChange => sortQuoteChangeCharges(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges).map(charge => {
|
|
23044
23126
|
var _a;
|
|
23045
23127
|
const multiplier = charge.kind === 'COUPON' ? -1 : 1;
|
|
23046
23128
|
return (jsxRuntime.jsxs("div", { className: "bunny-grid bunny-grid-cols-3 bunny-gap-4 bunny-items-center", children: [jsxRuntime.jsx("div", { className: "bunny-col-span-1", children: charge.name }), jsxRuntime.jsx("div", { className: "bunny-col-span-1 bunny-text-center", children: ((_a = charge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode) ? (jsxRuntime.jsx("button", { onClick: () => {
|
|
@@ -23053,7 +23135,7 @@ function CheckoutSummary({ quote: maskedQuote, className, onAddCoupon, onRemoveC
|
|
|
23053
23135
|
}
|
|
23054
23136
|
onRemoveCoupon((_b = charge.coupon) === null || _b === void 0 ? void 0 : _b.couponCode);
|
|
23055
23137
|
}, className: "bunny-text-orange-500 hover:bunny-text-orange-400 bunny-cursor-pointer bunny-bg-transparent bunny-border-none", children: "Remove" })) : (jsxRuntime.jsx("div", { children: charge.quantity })) }), jsxRuntime.jsx("div", { className: "bunny-col-span-1 bunny-text-right", children: formatCurrency(multiplier * (charge.subtotal || 0), charge.currencyId) })] }, charge.id));
|
|
23056
|
-
})) }), jsxRuntime.jsx(CheckoutSummaryDivider, {}), jsxRuntime.jsxs("div", { className: "bunny-space-y-4", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Subtotal" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.subtotal, quote.currencyId) })] }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Taxes" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.taxAmount, quote.currencyId) })] })] }), jsxRuntime.jsx(CheckoutSummaryDivider, {}), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Total" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.amountDue, quote.currencyId) })] })] }),
|
|
23138
|
+
})) }), jsxRuntime.jsx(CheckoutSummaryDivider, {}), jsxRuntime.jsxs("div", { className: "bunny-space-y-4", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Subtotal" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.subtotal, quote.currencyId) })] }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Taxes" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.taxAmount, quote.currencyId) })] })] }), jsxRuntime.jsx(CheckoutSummaryDivider, {}), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-justify-between", children: [jsxRuntime.jsx("div", { children: "Total" }), jsxRuntime.jsx("div", { children: formatCurrency(quote.amountDue, quote.currencyId) })] })] }), canApplyCoupons(quote, activeCouponsExist) && (jsxRuntime.jsx(CouponEditor, { className: "bunny-w-full", onAddCoupon: onAddCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode }))] }));
|
|
23057
23139
|
}
|
|
23058
23140
|
const CheckoutSummaryDivider = () => {
|
|
23059
23141
|
return (jsxRuntime.jsx("div", { className: "bunny-my-2", children: jsxRuntime.jsx(antd.Divider, { className: "m-0" }) }));
|
|
@@ -23104,10 +23186,36 @@ function InitialSignupForm({ className, onSubmit, submitting, defaultValues, })
|
|
|
23104
23186
|
} }) }) }) }), jsxRuntime.jsx(antd.Form.Item, { children: jsxRuntime.jsx(antd.Button, { type: "primary", onClick: handleSubmit, loading: submitting, className: "bunny-w-full", children: "Proceed to payment" }) })] }) }));
|
|
23105
23187
|
}
|
|
23106
23188
|
|
|
23189
|
+
const useApplyDefaultCoupon_QuoteFragment = t(`
|
|
23190
|
+
fragment useApplyDefaultCoupon_QuoteFragment on Quote {
|
|
23191
|
+
...canApplyCoupons_QuoteFragment
|
|
23192
|
+
}
|
|
23193
|
+
`, [canApplyCoupons_QuoteFragment]);
|
|
23194
|
+
/**
|
|
23195
|
+
* Applies a default coupon code once when quoteChangeId is available.
|
|
23196
|
+
* Uses a ref to ensure coupon code is only applied once.
|
|
23197
|
+
*/
|
|
23198
|
+
function useApplyDefaultCoupon({ couponCode, quoteChangeId, quote: maskedQuote, activeCouponsExist, addCoupon, }) {
|
|
23199
|
+
const defaultCouponAppliedRef = react.useRef(undefined);
|
|
23200
|
+
// Derived state
|
|
23201
|
+
const quote = readFragment(useApplyDefaultCoupon_QuoteFragment, maskedQuote);
|
|
23202
|
+
const canApplyCouponsResult = canApplyCoupons(quote, activeCouponsExist);
|
|
23203
|
+
react.useEffect(() => {
|
|
23204
|
+
if (couponCode &&
|
|
23205
|
+
quoteChangeId &&
|
|
23206
|
+
defaultCouponAppliedRef.current !== couponCode &&
|
|
23207
|
+
canApplyCouponsResult) {
|
|
23208
|
+
addCoupon(couponCode);
|
|
23209
|
+
defaultCouponAppliedRef.current = couponCode;
|
|
23210
|
+
}
|
|
23211
|
+
}, [couponCode, quoteChangeId, addCoupon, canApplyCouponsResult]);
|
|
23212
|
+
}
|
|
23213
|
+
|
|
23107
23214
|
const Signup_QuoteFragment = t(`
|
|
23108
23215
|
fragment Signup_QuoteFragment on Quote {
|
|
23109
23216
|
...CheckoutSummary_QuoteFragment
|
|
23110
23217
|
...PaymentForms_QuoteFragment
|
|
23218
|
+
...useApplyDefaultCoupon_QuoteFragment
|
|
23111
23219
|
id
|
|
23112
23220
|
currencyId
|
|
23113
23221
|
amountDue
|
|
@@ -23115,7 +23223,7 @@ const Signup_QuoteFragment = t(`
|
|
|
23115
23223
|
id
|
|
23116
23224
|
}
|
|
23117
23225
|
}
|
|
23118
|
-
`, [CheckoutSummary_QuoteFragment, PaymentForms_QuoteFragment]);
|
|
23226
|
+
`, [CheckoutSummary_QuoteFragment, PaymentForms_QuoteFragment, useApplyDefaultCoupon_QuoteFragment]);
|
|
23119
23227
|
|
|
23120
23228
|
const query$6 = t(`
|
|
23121
23229
|
query quote($id: ID) {
|
|
@@ -23571,7 +23679,6 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
23571
23679
|
const [portalSessionToken, setPortalSessionToken] = react.useState(undefined);
|
|
23572
23680
|
const token = portalSessionToken || tokenFromContexts;
|
|
23573
23681
|
const [purchaseSucceeded, setPurchaseSucceeded] = react.useState(false);
|
|
23574
|
-
const defaultCouponAppliedRef = react.useRef(undefined);
|
|
23575
23682
|
const [couponEditorCouponCode, setCouponEditorCouponCode] = react.useState('');
|
|
23576
23683
|
// Read fragment
|
|
23577
23684
|
const initialQuoteId = (_a = readFragment(Signup_QuoteFragment, initialQuote)) === null || _a === void 0 ? void 0 : _a.id;
|
|
@@ -23688,13 +23795,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
23688
23795
|
handleRecalculateTaxes(quote === null || quote === void 0 ? void 0 : quote.id);
|
|
23689
23796
|
},
|
|
23690
23797
|
});
|
|
23691
|
-
|
|
23692
|
-
react.useEffect(() => {
|
|
23693
|
-
if (couponCode && quoteChangeId && defaultCouponAppliedRef.current !== couponCode) {
|
|
23694
|
-
addCoupon(couponCode);
|
|
23695
|
-
defaultCouponAppliedRef.current = couponCode;
|
|
23696
|
-
}
|
|
23697
|
-
}, [couponCode, quoteChangeId]);
|
|
23798
|
+
useApplyDefaultCoupon({ couponCode, quoteChangeId, addCoupon, activeCouponsExist, quote });
|
|
23698
23799
|
async function handleSubmit(formData) {
|
|
23699
23800
|
if (selfServiceBuyEnabled === false) {
|
|
23700
23801
|
handleShowSelfServiceBuyWarning();
|
|
@@ -23924,22 +24025,22 @@ const QuoteCheckout_QuoteFragment = t(`
|
|
|
23924
24025
|
}
|
|
23925
24026
|
}
|
|
23926
24027
|
...QuoteFields_QuoteFragment
|
|
23927
|
-
...
|
|
24028
|
+
...canApplyCoupons_QuoteFragment
|
|
23928
24029
|
...PaymentForm_QuoteFragment
|
|
23929
24030
|
...getQuoteAmountDue_QuoteFragment
|
|
23930
24031
|
}
|
|
23931
24032
|
`, [
|
|
23932
24033
|
QuoteFields_QuoteFragment,
|
|
23933
|
-
|
|
24034
|
+
canApplyCoupons_QuoteFragment,
|
|
23934
24035
|
PaymentForm_QuoteFragment,
|
|
23935
24036
|
getQuoteAmountDue_QuoteFragment,
|
|
23936
24037
|
]);
|
|
23937
24038
|
const QuoteCheckout_SubscriptionFragment = t(`
|
|
23938
24039
|
fragment QuoteCheckout_SubscriptionFragment on Subscription {
|
|
23939
24040
|
id
|
|
23940
|
-
...
|
|
24041
|
+
...canApplyCoupons_SubscriptionFragment
|
|
23941
24042
|
}
|
|
23942
|
-
`, [
|
|
24043
|
+
`, [canApplyCoupons_SubscriptionFragment]);
|
|
23943
24044
|
const showSuccessNotification = useSuccessNotification();
|
|
23944
24045
|
const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxationRequiredAccountFields, isUpdatingQuote, onRecalculateTaxes, isRecalculatingTaxes, }) => {
|
|
23945
24046
|
var _a, _b, _c, _d, _e;
|
|
@@ -24025,7 +24126,7 @@ const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxatio
|
|
|
24025
24126
|
if (taxationRequiredAccountFields)
|
|
24026
24127
|
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsxRuntime.jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
24027
24128
|
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: paymentRequired ? (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote, onSavePaymentMethod: (paymentMethod) => onPaymentMethodSaved === null || onPaymentMethodSaved === void 0 ? void 0 : onPaymentMethodSaved(paymentMethod.savedPaymentMethodResponse.paymentMethodId), onPaymentMethodRemoved: (paymentMethod) => onPaymentMethodRemoved === null || onPaymentMethodRemoved === void 0 ? void 0 : onPaymentMethodRemoved(paymentMethod.id), disablePayButton: isFinalizingQuote }), isFinalizingQuote && jsxRuntime.jsx(QuoteLoadingIndicator, {}), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: upgradingSubscription &&
|
|
24028
|
-
|
|
24129
|
+
canApplyCoupons(quote, activeCouponsExist, upgradingSubscription) && (jsxRuntime.jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsxRuntime.jsx(antd.Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
24029
24130
|
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
24030
24131
|
var _a;
|
|
24031
24132
|
const couponCode = (_a = couponCharge === null || couponCharge === void 0 ? void 0 : couponCharge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode;
|