@bunnyapp/components 1.8.0-beta.5 → 1.8.0-beta.7
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 +435 -381
- package/dist/cjs/types/src/ajax.d.ts +1 -1
- 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/cjs/types/src/{graphql → components/Quote}/queries/getFormattedQuote.d.ts +6 -1
- package/dist/cjs/types/src/components/Quote/queries/quoteAccept.d.ts +14 -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/esm/index.js +435 -381
- package/dist/esm/types/src/ajax.d.ts +1 -1
- 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/esm/types/src/{graphql → components/Quote}/queries/getFormattedQuote.d.ts +6 -1
- package/dist/esm/types/src/components/Quote/queries/quoteAccept.d.ts +14 -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/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.6';
|
|
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
|
}
|
|
@@ -22994,7 +23053,6 @@ function canApplyCoupons(maskedQuote, activeCouponsExist, maskedUpgradingSubscri
|
|
|
22994
23053
|
if (quoteKindIsValid) {
|
|
22995
23054
|
const result = activeCouponsExist &&
|
|
22996
23055
|
(upgradingFromTrial || upgradingFromFree() || signingUpForNewSubscription);
|
|
22997
|
-
console.log('returning result', result);
|
|
22998
23056
|
return result;
|
|
22999
23057
|
}
|
|
23000
23058
|
return false;
|
|
@@ -30187,11 +30245,7 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
30187
30245
|
return countryListFilter ? COUNTRY_LIST.filter(countryListFilter) : COUNTRY_LIST;
|
|
30188
30246
|
}, [countryListFilter]);
|
|
30189
30247
|
const isLoading = isLoadingAccount || isLoadingContacts;
|
|
30190
|
-
return (jsxRuntime.jsxs("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: [jsxRuntime.jsxs("div", { className: "bunny-px-4", children: [jsxRuntime.jsxs(antd.Skeleton, { loading: isLoading || account === undefined, children: [jsxRuntime.jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsxRuntime.jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (account === null || account === void 0 ? void 0 : account.name) || 'No company name' }) }), jsxRuntime.jsxs(antd.Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingAccount, autoComplete: "off",
|
|
30191
|
-
{
|
|
30192
|
-
required: false,
|
|
30193
|
-
},
|
|
30194
|
-
], children: jsxRuntime.jsx(antd.Input, {}) }) }), jsxRuntime.jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsxRuntime.jsx(antd.Form.Item, { label: "Country", name: "billingCountry", rules: [{ required: true, message: 'Country is required' }], children: jsxRuntime.jsx(antd.Select, { className: "bunny-w-full", options: filteredCountryList, placeholder: "Select a country", popupMatchSelectWidth: false, showSearch: true, filterOption: (input, option) => {
|
|
30248
|
+
return (jsxRuntime.jsxs("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: [jsxRuntime.jsxs("div", { className: "bunny-px-4", children: [jsxRuntime.jsxs(antd.Skeleton, { loading: isLoading || account === undefined, children: [jsxRuntime.jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsxRuntime.jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (account === null || account === void 0 ? void 0 : account.name) || 'No company name' }) }), jsxRuntime.jsxs(antd.Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingAccount, autoComplete: "off", children: [jsxRuntime.jsx(antd.Form.Item, { label: "Street address", name: "billingStreet", children: jsxRuntime.jsx(antd.Input, {}) }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-4", children: [jsxRuntime.jsx(antd.Form.Item, { label: "City", name: "billingCity", className: "bunny-flex-1", children: jsxRuntime.jsx(antd.Input, {}) }), jsxRuntime.jsx(antd.Form.Item, { label: "Zipcode", name: "billingZip", className: "bunny-flex-1", children: jsxRuntime.jsx(antd.Input, {}) })] }), jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-row bunny-pb-2' : 'bunny-flex-row'} bunny-gap-4`, children: [jsxRuntime.jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsxRuntime.jsx(antd.Form.Item, { label: "State", name: "billingState", children: jsxRuntime.jsx(antd.Input, {}) }) }), jsxRuntime.jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsxRuntime.jsx(antd.Form.Item, { label: "Country", name: "billingCountry", children: jsxRuntime.jsx(antd.Select, { className: "bunny-w-full", options: filteredCountryList, placeholder: "Select a country", popupMatchSelectWidth: false, showSearch: true, filterOption: (input, option) => {
|
|
30195
30249
|
var _a, _b;
|
|
30196
30250
|
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
30197
30251
|
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
@@ -30216,7 +30270,7 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
30216
30270
|
})) !== null && _c !== void 0 ? _c : [], popupRender: menu => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menu, jsxRuntime.jsx(AddContactButton, { onClick: () => {
|
|
30217
30271
|
setContactFieldType('secondary');
|
|
30218
30272
|
setIsAddContactModalOpen(true);
|
|
30219
|
-
} })] })) }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Tax ID", name: "taxNumber", tooltip: "Tax ID will be printed on quotes and invoices below the account's address",
|
|
30273
|
+
} })] })) }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Tax ID", name: "taxNumber", tooltip: "Tax ID will be printed on quotes and invoices below the account's address", children: jsxRuntime.jsx(antd.Input, {}) })] })] }), jsxRuntime.jsx(antd.Button, { disabled: !isFormEdited || isUpdatingAccount || isLoading, className: "bunny-w-full bunny-mt-4", type: "primary", onClick: saveBillingDetails, children: "Save" })] }), jsxRuntime.jsx(AddContactModal, { open: isAddContactModalOpen, onClose: () => {
|
|
30220
30274
|
setIsAddContactModalOpen(false);
|
|
30221
30275
|
setContactFieldType(null);
|
|
30222
30276
|
}, accountId: accountId, onContactCreated: handleContactCreated })] }));
|