@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/esm/index.js
CHANGED
|
@@ -1281,7 +1281,7 @@ const DEFAULT_CONFIG = {
|
|
|
1281
1281
|
};
|
|
1282
1282
|
|
|
1283
1283
|
// This will be replaced at build time by rollup-plugin-replace
|
|
1284
|
-
const PACKAGE_VERSION = '1.8.0-beta.
|
|
1284
|
+
const PACKAGE_VERSION = '1.8.0-beta.6';
|
|
1285
1285
|
const createRequestHeaders = (token) => {
|
|
1286
1286
|
const headers = createClientDevHeaders({ token });
|
|
1287
1287
|
// Add the components version header
|
|
@@ -19897,7 +19897,7 @@ const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
|
19897
19897
|
};
|
|
19898
19898
|
};
|
|
19899
19899
|
|
|
19900
|
-
const mutation$
|
|
19900
|
+
const mutation$i = t(`
|
|
19901
19901
|
query PaymentPlugins($accountId: ID) {
|
|
19902
19902
|
paymentPlugins(accountId: $accountId) {
|
|
19903
19903
|
enabled
|
|
@@ -19925,7 +19925,7 @@ const mutation$h = t(`
|
|
|
19925
19925
|
// }[];
|
|
19926
19926
|
// };
|
|
19927
19927
|
const getPaymentPlugins = async ({ apiHost, token, accountId, }) => {
|
|
19928
|
-
const response = await execute(mutation$
|
|
19928
|
+
const response = await execute(mutation$i, { apiHost, token }, { accountId });
|
|
19929
19929
|
return response === null || response === void 0 ? void 0 : response.paymentPlugins;
|
|
19930
19930
|
};
|
|
19931
19931
|
const usePaymentPlugins = (accountId) => {
|
|
@@ -21696,6 +21696,102 @@ function ActualInvoice({ hidePaymentForm, onSavePaymentMethod, onPaymentMethodRe
|
|
|
21696
21696
|
} }) }))] }) }));
|
|
21697
21697
|
}
|
|
21698
21698
|
|
|
21699
|
+
const trimGraph = (s) => {
|
|
21700
|
+
return s.replace(/\s+/g, ' ');
|
|
21701
|
+
};
|
|
21702
|
+
const useGraphQL = (navigateOnTokenExpired, apiEndpoint, onError) => {
|
|
21703
|
+
return async (callback, bodyData = null, token, callbackParams) => {
|
|
21704
|
+
bodyData = trimGraph(bodyData);
|
|
21705
|
+
const headers = createClientDevHeaders({ token });
|
|
21706
|
+
const response = await fetch(apiEndpoint + '/graphql', {
|
|
21707
|
+
method: 'post',
|
|
21708
|
+
body: bodyData,
|
|
21709
|
+
headers,
|
|
21710
|
+
});
|
|
21711
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
21712
|
+
return response.json().then((data) => {
|
|
21713
|
+
var _a, _b, _c;
|
|
21714
|
+
if (data.errors) {
|
|
21715
|
+
onError(data.errors[0].message);
|
|
21716
|
+
}
|
|
21717
|
+
else if (((_a = data === null || data === void 0 ? void 0 : data[0]) === null || _a === void 0 ? void 0 : _a.description) === 'Token is expired') {
|
|
21718
|
+
navigateOnTokenExpired();
|
|
21719
|
+
}
|
|
21720
|
+
else if ((_b = data === null || data === void 0 ? void 0 : data[0]) === null || _b === void 0 ? void 0 : _b.description) {
|
|
21721
|
+
throw new Error((_c = data === null || data === void 0 ? void 0 : data[0]) === null || _c === void 0 ? void 0 : _c.description);
|
|
21722
|
+
}
|
|
21723
|
+
return;
|
|
21724
|
+
});
|
|
21725
|
+
}
|
|
21726
|
+
return response
|
|
21727
|
+
.json()
|
|
21728
|
+
.then((data) => callback(data, callbackParams))
|
|
21729
|
+
.catch((err) => {
|
|
21730
|
+
console.error(err);
|
|
21731
|
+
onError(err);
|
|
21732
|
+
});
|
|
21733
|
+
};
|
|
21734
|
+
};
|
|
21735
|
+
const useGraphQLmutation = (navigateOnTokenExpired, apiEndpoint, onError) => {
|
|
21736
|
+
const graphQL = useGraphQL(navigateOnTokenExpired, apiEndpoint, onError);
|
|
21737
|
+
return (mutation, variables, callback, token, callbackParams) => {
|
|
21738
|
+
if (typeof variables === 'object')
|
|
21739
|
+
variables = JSON.stringify(variables);
|
|
21740
|
+
return graphQL(callback, `{ "query": "${mutation}", "variables": ${variables} }`, token, callbackParams);
|
|
21741
|
+
};
|
|
21742
|
+
};
|
|
21743
|
+
|
|
21744
|
+
const POLLING_INTERVAL = 2000;
|
|
21745
|
+
const PandadocPollingModal = ({ isVisible, setVisible, id }) => {
|
|
21746
|
+
const { apiHost, onTokenExpired } = useContext(BunnyContext);
|
|
21747
|
+
const token = useToken();
|
|
21748
|
+
const graphQLMutation = useGraphQLmutation(() => {
|
|
21749
|
+
console.log('graphQLMutation navigateOnTokenExpired not yet implemented');
|
|
21750
|
+
}, apiHost || '', () => {
|
|
21751
|
+
console.log('graphQLMutation onError not yet implemented');
|
|
21752
|
+
});
|
|
21753
|
+
const handleAllErrorFormats = useAllErrorFormats$1(onTokenExpired);
|
|
21754
|
+
const [numberOfPolls, setNumberOfPolls] = useState(0);
|
|
21755
|
+
const [infoMessage, setInfoMessage] = useState('');
|
|
21756
|
+
useEffect(() => {
|
|
21757
|
+
if (!isVisible)
|
|
21758
|
+
return;
|
|
21759
|
+
const pollPandadocMutation = () => {
|
|
21760
|
+
const mutation = `mutation quotePollSigningUrl($id: ID) {
|
|
21761
|
+
quotePollSigningUrl(quoteId: $id) {
|
|
21762
|
+
redirectUri
|
|
21763
|
+
status
|
|
21764
|
+
errors
|
|
21765
|
+
infoMessage
|
|
21766
|
+
}
|
|
21767
|
+
}`;
|
|
21768
|
+
const variables = {
|
|
21769
|
+
id,
|
|
21770
|
+
};
|
|
21771
|
+
graphQLMutation(mutation, variables, (rsp) => {
|
|
21772
|
+
if (rsp.errors)
|
|
21773
|
+
handleAllErrorFormats(rsp.errors[0].message);
|
|
21774
|
+
else if (rsp.data.quotePollSigningUrl.status === 'document.sent') {
|
|
21775
|
+
setVisible(false);
|
|
21776
|
+
window.location.href = rsp.data.quotePollSigningUrl.redirectUri;
|
|
21777
|
+
}
|
|
21778
|
+
setInfoMessage(rsp.data.quotePollSigningUrl.infoMessage || '');
|
|
21779
|
+
}, token);
|
|
21780
|
+
setNumberOfPolls(numberOfPolls + 1);
|
|
21781
|
+
};
|
|
21782
|
+
const interval = setInterval(pollPandadocMutation, POLLING_INTERVAL);
|
|
21783
|
+
return () => clearInterval(interval);
|
|
21784
|
+
}, [
|
|
21785
|
+
graphQLMutation,
|
|
21786
|
+
// handleAllErrorFormats,
|
|
21787
|
+
numberOfPolls,
|
|
21788
|
+
token,
|
|
21789
|
+
isVisible,
|
|
21790
|
+
setVisible,
|
|
21791
|
+
]);
|
|
21792
|
+
return (jsxs(Modal, { title: "Uploading quote to Pandadoc", open: isVisible, closable: false, footer: null, children: [jsxs("div", { className: "bunny-py-4 bunny-text-center", children: ["This may take a few seconds", '.'.repeat(numberOfPolls)] }), jsx("div", { className: "bunny-text-center", children: infoMessage })] }));
|
|
21793
|
+
};
|
|
21794
|
+
|
|
21699
21795
|
const usePlugins = ({ apiHost, token }) => {
|
|
21700
21796
|
const response = useQuery({
|
|
21701
21797
|
queryKey: QueryKeyFactory.pluginsKey(token),
|
|
@@ -21818,76 +21914,7 @@ const AcceptQuoteModal = ({ acceptBoxVisible, formattedQuote: maskedFormattedQuo
|
|
|
21818
21914
|
}, open: acceptBoxVisible, title: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length) ? 'Start signing' : 'Accept quote', width: 400, children: jsx(NoSigningPluginsForm, { isVisible: acceptBoxVisible, formattedQuote: formattedQuote, form: form }) }));
|
|
21819
21915
|
};
|
|
21820
21916
|
|
|
21821
|
-
const
|
|
21822
|
-
blue: { color: 'var(--bunny-blue-500)', background: 'var(--bunny-blue-200)' },
|
|
21823
|
-
green: {
|
|
21824
|
-
color: 'var(--bunny-green-600)',
|
|
21825
|
-
background: 'var(--bunny-green-200)',
|
|
21826
|
-
},
|
|
21827
|
-
red: { color: 'var(--bunny-red-500)', background: 'var(--bunny-red-200)' },
|
|
21828
|
-
orange: {
|
|
21829
|
-
color: 'var(--bunny-orange-500)',
|
|
21830
|
-
background: 'var(--bunny-orange-200)',
|
|
21831
|
-
},
|
|
21832
|
-
yellow: {
|
|
21833
|
-
color: 'var(--bunny-yellow-500)',
|
|
21834
|
-
background: 'var(--bunny-yellow-200)',
|
|
21835
|
-
},
|
|
21836
|
-
purple: {
|
|
21837
|
-
color: 'var(--bunny-purple-500)',
|
|
21838
|
-
background: 'var(--bunny-purple-200)',
|
|
21839
|
-
},
|
|
21840
|
-
black: { color: 'white', background: 'var(--bunny-black)' },
|
|
21841
|
-
};
|
|
21842
|
-
// This component provides custom styling for antd Tag components without using antd overwrites.
|
|
21843
|
-
// Please use this component instead of the antd Tag component directly to maintain consistent styling.
|
|
21844
|
-
const CustomizedTag = ({ children, color, className, style, }) => {
|
|
21845
|
-
return (jsx(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 }));
|
|
21846
|
-
};
|
|
21847
|
-
|
|
21848
|
-
const useIsExpired = (expiresAt) => dayjs(expiresAt).diff(dayjs(dayjs().format("YYYY-MM-DD"))) < 0;
|
|
21849
|
-
|
|
21850
|
-
dayjs.extend(localizedFormat);
|
|
21851
|
-
const formatDate = (date) => dayjs(date).format('ll');
|
|
21852
|
-
|
|
21853
|
-
const { Text: Text$z } = Typography;
|
|
21854
|
-
const QuoteButtons_FormattedQuoteFragment = t(`
|
|
21855
|
-
fragment QuoteButtons_FormattedQuoteFragment on FormattedQuote {
|
|
21856
|
-
acceptedAt
|
|
21857
|
-
acceptedByName
|
|
21858
|
-
currency
|
|
21859
|
-
amount
|
|
21860
|
-
expiresAt
|
|
21861
|
-
}
|
|
21862
|
-
`);
|
|
21863
|
-
function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobile, hideDownloadButton, id, isAccepting, handleClickAccept, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, paymentHold, isSendAcceptPending, }) {
|
|
21864
|
-
// Read fragments
|
|
21865
|
-
const formattedQuote = readFragment(QuoteButtons_FormattedQuoteFragment, maskedFormattedQuote);
|
|
21866
|
-
const { apiHost } = useContext(BunnyContext);
|
|
21867
|
-
const token = useToken();
|
|
21868
|
-
const { secondaryColor } = useBrand();
|
|
21869
|
-
const downloadFile = useDownloadFile(id);
|
|
21870
|
-
const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
|
|
21871
|
-
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
21872
|
-
return (jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
21873
|
-
color: secondaryColor,
|
|
21874
|
-
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$z, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsx(Button, { icon: jsx(DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsx(Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsx(Fragment, { children: !isAccepted ? (jsx(Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
21875
|
-
? 'Quote is expired'
|
|
21876
|
-
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
21877
|
-
? 'Start signing'
|
|
21878
|
-
: 'Accept quote' })) : null }))] }))] }));
|
|
21879
|
-
}
|
|
21880
|
-
function PaymentHoldDisplay({ paymentHold, currency, amount, }) {
|
|
21881
|
-
var _a, _b, _c, _d;
|
|
21882
|
-
const paymentMethod = ((_b = (_a = paymentHold.paymentMethod) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.identifier)
|
|
21883
|
-
? (_d = (_c = paymentHold.paymentMethod) === null || _c === void 0 ? void 0 : _c.metadata) === null || _d === void 0 ? void 0 : _d.identifier
|
|
21884
|
-
: 'N/A';
|
|
21885
|
-
const formattedAmount = currency ? formatCurrency(amount, currency) : 'N/A';
|
|
21886
|
-
const expirationDate = paymentHold.expiresAt ? formatDate(paymentHold.expiresAt) : 'N/A';
|
|
21887
|
-
return (jsx(Tooltip$1, { title: `${formattedAmount} will be charged to ${paymentMethod} once the quote is accepted. Hold will be released on ${expirationDate} if not accepted.`, children: jsx(Fragment, { children: jsxs(CustomizedTag, { color: 'orange', className: "rounded-md", style: { padding: 6 }, children: ["Hold of ", formattedAmount, " on ****", paymentMethod] }) }) }));
|
|
21888
|
-
}
|
|
21889
|
-
|
|
21890
|
-
const { Title: Title$2, Text: Text$y } = Typography;
|
|
21917
|
+
const { Title: Title$2, Text: Text$z } = Typography;
|
|
21891
21918
|
const showSuccessNotification$2 = useSuccessNotification();
|
|
21892
21919
|
const showErrorNotification$5 = useErrorNotification();
|
|
21893
21920
|
const PaymentHoldModal_FormattedQuoteFragment = t(`
|
|
@@ -21913,7 +21940,7 @@ const PaymentHoldModal = ({ visible, setVisible, formattedQuote: maskedFormatted
|
|
|
21913
21940
|
const [form] = Form.useForm();
|
|
21914
21941
|
return (jsx(StyledModal$2, { centered: true, onCancel: () => {
|
|
21915
21942
|
setVisible(false);
|
|
21916
|
-
}, footer: null, open: visible, width: 800, className: 'bunny-flex bunny-flex-row bunny-gap-4', children: jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-w-1/2", children: [jsxs("div", { className: "bunny-mt-5 bunny-mx-4", children: [jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxs(Text$
|
|
21943
|
+
}, footer: null, open: visible, width: 800, className: 'bunny-flex bunny-flex-row bunny-gap-4', children: jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxs("div", { className: "bunny-flex bunny-flex-col bunny-w-1/2", children: [jsxs("div", { className: "bunny-mt-5 bunny-mx-4", children: [jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxs(Text$z, { className: "bunny-bt-2 bunny-text-sm/5 bunny-text-gray-500", children: ["To accept this quote, approve a payment hold for", ' ', formatCurrency(formattedQuote.amount, formattedQuote.currency || 'null'), ". This amount will be charged to your payment method once the quote is signed."] })] }), jsx("div", { className: "bunny-p-4", children: noSigningPlugins ? jsx(NoSigningPluginsForm, { isVisible: visible, formattedQuote: formattedQuote, form: form }) : null })] }), jsx(VerticalDivider, { className: "bunny-m-4" }), jsx("div", { className: "bunny-mb-3 bunny-w-1/2 bunny-pt-6", children: jsx(PaymentForm, { quote: formattedQuote.quote, paymentHoldOptions: {
|
|
21917
21944
|
payToAccept: true,
|
|
21918
21945
|
amountToHold: formattedQuote.amount,
|
|
21919
21946
|
}, onPaymentSuccess: () => {
|
|
@@ -21936,13 +21963,15 @@ const PaymentHoldModal = ({ visible, setVisible, formattedQuote: maskedFormatted
|
|
|
21936
21963
|
token,
|
|
21937
21964
|
}),
|
|
21938
21965
|
});
|
|
21939
|
-
// accept quote automatically
|
|
21940
|
-
|
|
21941
|
-
|
|
21942
|
-
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21966
|
+
// accept quote automatically if no signing plugins are present
|
|
21967
|
+
if (noSigningPlugins) {
|
|
21968
|
+
form
|
|
21969
|
+
.validateFields()
|
|
21970
|
+
.then(changedFields => {
|
|
21971
|
+
sendAccept(changedFields);
|
|
21972
|
+
})
|
|
21973
|
+
.catch(() => { });
|
|
21974
|
+
}
|
|
21946
21975
|
}, paymentHoldPrecondition: async () => {
|
|
21947
21976
|
if (!noSigningPlugins)
|
|
21948
21977
|
return true;
|
|
@@ -21988,232 +22017,125 @@ const StyledModal$2 = (props) => {
|
|
|
21988
22017
|
return jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
21989
22018
|
};
|
|
21990
22019
|
|
|
21991
|
-
const
|
|
21992
|
-
query formattedQuote($id: ID) {
|
|
21993
|
-
formattedQuote(id: $id) {
|
|
21994
|
-
quote {
|
|
21995
|
-
documentTemplateId
|
|
21996
|
-
documents {
|
|
21997
|
-
id
|
|
21998
|
-
filename
|
|
21999
|
-
size
|
|
22000
|
-
date
|
|
22001
|
-
url
|
|
22002
|
-
}
|
|
22003
|
-
firstInvoice {
|
|
22004
|
-
id
|
|
22005
|
-
state
|
|
22006
|
-
}
|
|
22007
|
-
payableId
|
|
22008
|
-
id
|
|
22009
|
-
payToAccept
|
|
22010
|
-
currentPaymentHold {
|
|
22011
|
-
createdAt
|
|
22012
|
-
expiresAt
|
|
22013
|
-
id
|
|
22014
|
-
updatedAt
|
|
22015
|
-
paymentMethod {
|
|
22016
|
-
accountId
|
|
22017
|
-
createdAt
|
|
22018
|
-
expirationDate
|
|
22019
|
-
failureCode
|
|
22020
|
-
id
|
|
22021
|
-
isDefault
|
|
22022
|
-
lastSuccess
|
|
22023
|
-
paymentType
|
|
22024
|
-
pluginId
|
|
22025
|
-
state
|
|
22026
|
-
updatedAt
|
|
22027
|
-
metadata {
|
|
22028
|
-
description
|
|
22029
|
-
expiration
|
|
22030
|
-
icon
|
|
22031
|
-
identifier
|
|
22032
|
-
issuer
|
|
22033
|
-
kind
|
|
22034
|
-
}
|
|
22035
|
-
}
|
|
22036
|
-
}
|
|
22037
|
-
}
|
|
22038
|
-
payableId
|
|
22039
|
-
acceptedAt
|
|
22040
|
-
acceptedByName
|
|
22041
|
-
amount
|
|
22042
|
-
amountDue
|
|
22043
|
-
amountsByPeriod {
|
|
22044
|
-
id
|
|
22045
|
-
name
|
|
22046
|
-
amount
|
|
22047
|
-
}
|
|
22048
|
-
billingCity
|
|
22049
|
-
billingCountry
|
|
22050
|
-
billingState
|
|
22051
|
-
billingStreet
|
|
22052
|
-
billingZip
|
|
22053
|
-
contactName
|
|
22054
|
-
currency
|
|
22055
|
-
customerBillingCity
|
|
22056
|
-
customerBillingCountry
|
|
22057
|
-
customerBillingState
|
|
22058
|
-
customerBillingStreet
|
|
22059
|
-
customerBillingZip
|
|
22060
|
-
customerName
|
|
22061
|
-
discount
|
|
22062
|
-
discountValue
|
|
22063
|
-
duration
|
|
22064
|
-
endDate
|
|
22065
|
-
expiresAt
|
|
22066
|
-
html
|
|
22067
|
-
formattedLines {
|
|
22068
|
-
amount
|
|
22069
|
-
amountsByPeriod {
|
|
22070
|
-
quantity
|
|
22071
|
-
id
|
|
22072
|
-
name
|
|
22073
|
-
startDate
|
|
22074
|
-
endDate
|
|
22075
|
-
amount
|
|
22076
|
-
amountsByTier {
|
|
22077
|
-
id
|
|
22078
|
-
tier {
|
|
22079
|
-
starts
|
|
22080
|
-
ends
|
|
22081
|
-
price
|
|
22082
|
-
}
|
|
22083
|
-
quantity
|
|
22084
|
-
amount
|
|
22085
|
-
}
|
|
22086
|
-
prorationRate
|
|
22087
|
-
}
|
|
22088
|
-
billingPeriodEnd
|
|
22089
|
-
billingPeriodStart
|
|
22090
|
-
chargeType
|
|
22091
|
-
discount
|
|
22092
|
-
frequency
|
|
22093
|
-
isRamp
|
|
22094
|
-
periods
|
|
22095
|
-
planName
|
|
22096
|
-
position
|
|
22097
|
-
price
|
|
22098
|
-
priceDecimals
|
|
22099
|
-
priceListChargeId
|
|
22100
|
-
priceListChargeName
|
|
22101
|
-
priceListId
|
|
22102
|
-
priceListName
|
|
22103
|
-
priceTiers {
|
|
22104
|
-
price
|
|
22105
|
-
starts
|
|
22106
|
-
}
|
|
22107
|
-
pricingModel
|
|
22108
|
-
productName
|
|
22109
|
-
prorationRate
|
|
22110
|
-
quantity
|
|
22111
|
-
showProductNameOnLineItem
|
|
22112
|
-
taxCode
|
|
22113
|
-
trialEndDate
|
|
22114
|
-
trialStartDate
|
|
22115
|
-
unitOfMeasure
|
|
22116
|
-
vatCode
|
|
22117
|
-
}
|
|
22118
|
-
netPaymentDays
|
|
22119
|
-
notes
|
|
22120
|
-
number
|
|
22121
|
-
poNumberRequired
|
|
22122
|
-
salesContactEmail
|
|
22123
|
-
sharedAt
|
|
22124
|
-
startDate
|
|
22125
|
-
state
|
|
22126
|
-
subtotal
|
|
22127
|
-
taxAmount
|
|
22128
|
-
taxNumberLabel
|
|
22129
|
-
taxNumberRequired
|
|
22130
|
-
vendorName
|
|
22131
|
-
...PaymentHoldModal_FormattedQuoteFragment
|
|
22132
|
-
...AcceptQuoteModal_FormattedQuoteFragment
|
|
22133
|
-
...QuoteButtons_FormattedQuoteFragment
|
|
22134
|
-
}
|
|
22135
|
-
}
|
|
22136
|
-
`, [
|
|
22137
|
-
PaymentHoldModal_FormattedQuoteFragment,
|
|
22138
|
-
AcceptQuoteModal_FormattedQuoteFragment,
|
|
22139
|
-
QuoteButtons_FormattedQuoteFragment,
|
|
22140
|
-
]);
|
|
22141
|
-
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
22142
|
-
const response = await execute(query$7, { apiHost, token }, { id });
|
|
22143
|
-
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
22144
|
-
};
|
|
22020
|
+
const useIsExpired = (expiresAt) => dayjs(expiresAt).diff(dayjs(dayjs().format("YYYY-MM-DD"))) < 0;
|
|
22145
22021
|
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
const
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
}
|
|
22170
|
-
return;
|
|
22171
|
-
});
|
|
22172
|
-
}
|
|
22173
|
-
return response
|
|
22174
|
-
.json()
|
|
22175
|
-
.then((data) => callback(data, callbackParams))
|
|
22176
|
-
.catch((err) => {
|
|
22177
|
-
console.error(err);
|
|
22178
|
-
onError(err);
|
|
22179
|
-
});
|
|
22180
|
-
};
|
|
22022
|
+
dayjs.extend(localizedFormat);
|
|
22023
|
+
const formatDate = (date) => dayjs(date).format('ll');
|
|
22024
|
+
|
|
22025
|
+
const tagStyleMap = {
|
|
22026
|
+
blue: { color: 'var(--bunny-blue-500)', background: 'var(--bunny-blue-200)' },
|
|
22027
|
+
green: {
|
|
22028
|
+
color: 'var(--bunny-green-600)',
|
|
22029
|
+
background: 'var(--bunny-green-200)',
|
|
22030
|
+
},
|
|
22031
|
+
red: { color: 'var(--bunny-red-500)', background: 'var(--bunny-red-200)' },
|
|
22032
|
+
orange: {
|
|
22033
|
+
color: 'var(--bunny-orange-500)',
|
|
22034
|
+
background: 'var(--bunny-orange-200)',
|
|
22035
|
+
},
|
|
22036
|
+
yellow: {
|
|
22037
|
+
color: 'var(--bunny-yellow-500)',
|
|
22038
|
+
background: 'var(--bunny-yellow-200)',
|
|
22039
|
+
},
|
|
22040
|
+
purple: {
|
|
22041
|
+
color: 'var(--bunny-purple-500)',
|
|
22042
|
+
background: 'var(--bunny-purple-200)',
|
|
22043
|
+
},
|
|
22044
|
+
black: { color: 'white', background: 'var(--bunny-black)' },
|
|
22181
22045
|
};
|
|
22182
|
-
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
variables = JSON.stringify(variables);
|
|
22187
|
-
return graphQL(callback, `{ "query": "${mutation}", "variables": ${variables} }`, token, callbackParams);
|
|
22188
|
-
};
|
|
22046
|
+
// This component provides custom styling for antd Tag components without using antd overwrites.
|
|
22047
|
+
// Please use this component instead of the antd Tag component directly to maintain consistent styling.
|
|
22048
|
+
const CustomizedTag = ({ children, color, className, style, }) => {
|
|
22049
|
+
return (jsx(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 }));
|
|
22189
22050
|
};
|
|
22190
22051
|
|
|
22191
|
-
const
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22052
|
+
const PaymentHoldDisplay_PaymentHoldFragment = t(`
|
|
22053
|
+
fragment PaymentHoldDisplay_PaymentHoldFragment on PaymentHold {
|
|
22054
|
+
expiresAt
|
|
22055
|
+
paymentMethod {
|
|
22056
|
+
metadata {
|
|
22057
|
+
identifier
|
|
22058
|
+
}
|
|
22059
|
+
}
|
|
22060
|
+
}
|
|
22061
|
+
`);
|
|
22062
|
+
function PaymentHoldDisplay({ paymentHold: maskedPaymentHold, currency, amount, }) {
|
|
22063
|
+
var _a, _b, _c, _d;
|
|
22064
|
+
const paymentHold = readFragment(PaymentHoldDisplay_PaymentHoldFragment, maskedPaymentHold);
|
|
22065
|
+
const paymentMethod = ((_b = (_a = paymentHold.paymentMethod) === null || _a === void 0 ? void 0 : _a.metadata) === null || _b === void 0 ? void 0 : _b.identifier)
|
|
22066
|
+
? (_d = (_c = paymentHold.paymentMethod) === null || _c === void 0 ? void 0 : _c.metadata) === null || _d === void 0 ? void 0 : _d.identifier
|
|
22067
|
+
: 'N/A';
|
|
22068
|
+
const formattedAmount = currency ? formatCurrency(amount, currency) : 'N/A';
|
|
22069
|
+
const expirationDate = paymentHold.expiresAt ? formatDate(paymentHold.expiresAt) : 'N/A';
|
|
22070
|
+
return (jsx(Tooltip$1, { title: `${formattedAmount} will be charged to ${paymentMethod} once the quote is accepted.Hold will be released on ${expirationDate} if not accepted.`, children: jsx(Fragment, { children: jsxs(CustomizedTag, { color: 'orange', className: "rounded-md", style: { padding: 6 }, children: ["Hold of ", formattedAmount, " on ****", paymentMethod] }) }) }));
|
|
22071
|
+
}
|
|
22072
|
+
|
|
22073
|
+
const { Text: Text$y } = Typography;
|
|
22074
|
+
const QuoteButtons_FormattedQuoteFragment = t(`
|
|
22075
|
+
fragment QuoteButtons_FormattedQuoteFragment on FormattedQuote {
|
|
22076
|
+
acceptedAt
|
|
22077
|
+
acceptedByName
|
|
22078
|
+
currency
|
|
22079
|
+
amount
|
|
22080
|
+
expiresAt
|
|
22081
|
+
}
|
|
22082
|
+
`);
|
|
22083
|
+
const PaymentHoldDisplay_QuoteButtonsFragment = t(`
|
|
22084
|
+
fragment PaymentHoldDisplay_QuoteButtonsFragment on PaymentHold {
|
|
22085
|
+
...PaymentHoldDisplay_PaymentHoldFragment
|
|
22086
|
+
}
|
|
22087
|
+
`, [PaymentHoldDisplay_PaymentHoldFragment]);
|
|
22088
|
+
function QuoteButtons({ isAccepted, formattedQuote: maskedFormattedQuote, isMobile, hideDownloadButton, id, isAccepting, handleClickAccept, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, paymentHold: maskedPaymentHold, isSendAcceptPending, }) {
|
|
22089
|
+
// Read fragments
|
|
22090
|
+
const formattedQuote = readFragment(QuoteButtons_FormattedQuoteFragment, maskedFormattedQuote);
|
|
22091
|
+
const paymentHold = readFragment(PaymentHoldDisplay_QuoteButtonsFragment, maskedPaymentHold);
|
|
22092
|
+
const { apiHost } = useContext(BunnyContext);
|
|
22093
|
+
const token = useToken();
|
|
22094
|
+
const { secondaryColor } = useBrand();
|
|
22095
|
+
const downloadFile = useDownloadFile(id);
|
|
22096
|
+
const isExpired = useIsExpired(formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.expiresAt);
|
|
22097
|
+
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
22098
|
+
return (jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
22099
|
+
color: secondaryColor,
|
|
22100
|
+
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsx(Text$y, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${formatDate(formattedQuote.acceptedAt)}` })) : null, (!isMobile || !isAccepted) && (jsxs("div", { className: isMobile ? 'flex w-full justify-end gap-2' : 'flex items-center justify-end gap-2', children: [paymentHold ? (jsx(PaymentHoldDisplay, { paymentHold: paymentHold, currency: formattedQuote.currency, amount: formattedQuote.amount })) : null, !isMobile && !hideDownloadButton ? (jsx(Button, { icon: jsx(DownloadOutlined, {}), onClick: () => downloadFile(apiHost + '/api/pdf/quote', token), children: "Download" })) : null, shouldDoPaymentHold && !paymentHoldCompleted ? (jsx(Button, { disabled: isExpired, onClick: () => setPaymentHoldModalVisible(true), type: "primary", loading: isSendAcceptPending, children: "Pay and sign" })) : (jsx(Fragment, { children: !isAccepted ? (jsx(Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
22101
|
+
? 'Quote is expired'
|
|
22102
|
+
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
22103
|
+
? 'Start signing'
|
|
22104
|
+
: 'Accept quote' })) : null }))] }))] }));
|
|
22105
|
+
}
|
|
22106
|
+
|
|
22107
|
+
const mutation$h = t(`
|
|
22108
|
+
mutation QuoteAccept(
|
|
22109
|
+
$name: String!
|
|
22110
|
+
$title: String!
|
|
22111
|
+
$poNumber: String
|
|
22112
|
+
$taxNumber: String
|
|
22113
|
+
$quoteId: ID
|
|
22114
|
+
) {
|
|
22115
|
+
quoteAccept(
|
|
22116
|
+
name: $name
|
|
22117
|
+
title: $title
|
|
22118
|
+
poNumber: $poNumber
|
|
22119
|
+
taxNumber: $taxNumber
|
|
22120
|
+
quoteId: $quoteId
|
|
22121
|
+
) {
|
|
22195
22122
|
errors
|
|
22196
22123
|
}
|
|
22197
22124
|
}
|
|
22198
|
-
|
|
22199
|
-
const quoteAccept = async ({ quoteId, apiHost, token, changedFormItems
|
|
22125
|
+
`);
|
|
22126
|
+
const quoteAccept = async ({ quoteId, apiHost, token, changedFormItems }) => {
|
|
22200
22127
|
var _a, _b;
|
|
22201
|
-
|
|
22202
|
-
|
|
22203
|
-
|
|
22204
|
-
|
|
22205
|
-
|
|
22206
|
-
|
|
22207
|
-
token,
|
|
22208
|
-
vars,
|
|
22209
|
-
apiHost,
|
|
22128
|
+
return await execute(mutation$h, { apiHost, token }, {
|
|
22129
|
+
name: changedFormItems.name,
|
|
22130
|
+
title: changedFormItems.title,
|
|
22131
|
+
poNumber: (_a = changedFormItems.poNumber) !== null && _a !== void 0 ? _a : null,
|
|
22132
|
+
taxNumber: (_b = changedFormItems.taxNumber) !== null && _b !== void 0 ? _b : null,
|
|
22133
|
+
quoteId: quoteId !== null && quoteId !== void 0 ? quoteId : null,
|
|
22210
22134
|
});
|
|
22211
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAccept) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22212
|
-
if (errors)
|
|
22213
|
-
throw errors;
|
|
22214
|
-
return (_b = response.quoteAccept) === null || _b === void 0 ? void 0 : _b.quote;
|
|
22215
22135
|
};
|
|
22216
|
-
|
|
22136
|
+
|
|
22137
|
+
const handleAllErrorFormats = useAllErrorFormats();
|
|
22138
|
+
const useAcceptQuote = ({ quoteId, apiHost, token, onQuoteAccepted, }) => {
|
|
22217
22139
|
// Hooks
|
|
22218
22140
|
const graphQLMutation = useGraphQLmutation(() => {
|
|
22219
22141
|
console.log('navigate in useGraphQLmutation in useSendAcceptQuote is not yet implemented');
|
|
@@ -22305,6 +22227,33 @@ const useSendAcceptQuote = ({ quoteId, apiHost, token, onQuoteAccepted, }) => {
|
|
|
22305
22227
|
};
|
|
22306
22228
|
};
|
|
22307
22229
|
|
|
22230
|
+
const useQuotePaymentHold_FormattedQuoteFragment = t(`
|
|
22231
|
+
fragment useQuotePaymentHold_FormattedQuoteFragment on FormattedQuote {
|
|
22232
|
+
quote {
|
|
22233
|
+
payToAccept
|
|
22234
|
+
currentPaymentHold {
|
|
22235
|
+
id
|
|
22236
|
+
}
|
|
22237
|
+
}
|
|
22238
|
+
}
|
|
22239
|
+
`);
|
|
22240
|
+
const useQuotePaymentHold = (maskedFormattedQuote) => {
|
|
22241
|
+
var _a, _b;
|
|
22242
|
+
const [paymentHoldModalVisible, setPaymentHoldModalVisible] = useState(false);
|
|
22243
|
+
const formattedQuote = maskedFormattedQuote
|
|
22244
|
+
? readFragment(useQuotePaymentHold_FormattedQuoteFragment, maskedFormattedQuote)
|
|
22245
|
+
: undefined;
|
|
22246
|
+
const shouldDoPaymentHold = ((_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.payToAccept) === true;
|
|
22247
|
+
const currentPaymentHold = (_b = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.currentPaymentHold;
|
|
22248
|
+
return {
|
|
22249
|
+
// paymentHold: currentPaymentHold ?? undefined,
|
|
22250
|
+
paymentHoldModalVisible,
|
|
22251
|
+
setPaymentHoldModalVisible,
|
|
22252
|
+
shouldDoPaymentHold,
|
|
22253
|
+
paymentHoldCompleted: currentPaymentHold ? true : false,
|
|
22254
|
+
};
|
|
22255
|
+
};
|
|
22256
|
+
|
|
22308
22257
|
const NavigationContext = createContext({});
|
|
22309
22258
|
|
|
22310
22259
|
const useSigningComplete = ({ data, token }) => {
|
|
@@ -22320,63 +22269,186 @@ const useSigningComplete = ({ data, token }) => {
|
|
|
22320
22269
|
}, [data, eventParam, queryClient, token]);
|
|
22321
22270
|
};
|
|
22322
22271
|
|
|
22323
|
-
const
|
|
22324
|
-
|
|
22325
|
-
|
|
22326
|
-
|
|
22327
|
-
|
|
22328
|
-
|
|
22329
|
-
|
|
22330
|
-
|
|
22331
|
-
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
|
|
22337
|
-
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
|
|
22343
|
-
|
|
22344
|
-
|
|
22272
|
+
const query$7 = t(`
|
|
22273
|
+
query formattedQuote($id: ID) {
|
|
22274
|
+
formattedQuote(id: $id) {
|
|
22275
|
+
quote {
|
|
22276
|
+
documentTemplateId
|
|
22277
|
+
documents {
|
|
22278
|
+
id
|
|
22279
|
+
filename
|
|
22280
|
+
size
|
|
22281
|
+
date
|
|
22282
|
+
url
|
|
22283
|
+
}
|
|
22284
|
+
firstInvoice {
|
|
22285
|
+
id
|
|
22286
|
+
state
|
|
22287
|
+
}
|
|
22288
|
+
payableId
|
|
22289
|
+
id
|
|
22290
|
+
payToAccept
|
|
22291
|
+
currentPaymentHold {
|
|
22292
|
+
createdAt
|
|
22293
|
+
expiresAt
|
|
22294
|
+
id
|
|
22295
|
+
updatedAt
|
|
22296
|
+
paymentMethod {
|
|
22297
|
+
accountId
|
|
22298
|
+
createdAt
|
|
22299
|
+
expirationDate
|
|
22300
|
+
failureCode
|
|
22301
|
+
id
|
|
22302
|
+
isDefault
|
|
22303
|
+
lastSuccess
|
|
22304
|
+
paymentType
|
|
22305
|
+
pluginId
|
|
22306
|
+
state
|
|
22307
|
+
updatedAt
|
|
22308
|
+
metadata {
|
|
22309
|
+
description
|
|
22310
|
+
expiration
|
|
22311
|
+
icon
|
|
22312
|
+
identifier
|
|
22313
|
+
issuer
|
|
22314
|
+
kind
|
|
22315
|
+
}
|
|
22316
|
+
}
|
|
22317
|
+
...PaymentHoldDisplay_QuoteButtonsFragment
|
|
22318
|
+
}
|
|
22345
22319
|
}
|
|
22346
|
-
|
|
22347
|
-
|
|
22348
|
-
|
|
22349
|
-
|
|
22350
|
-
|
|
22351
|
-
|
|
22352
|
-
|
|
22353
|
-
|
|
22354
|
-
|
|
22355
|
-
|
|
22356
|
-
|
|
22357
|
-
|
|
22358
|
-
|
|
22359
|
-
|
|
22360
|
-
|
|
22361
|
-
|
|
22362
|
-
|
|
22363
|
-
|
|
22364
|
-
|
|
22365
|
-
|
|
22366
|
-
|
|
22367
|
-
|
|
22368
|
-
|
|
22369
|
-
|
|
22370
|
-
|
|
22371
|
-
|
|
22320
|
+
payableId
|
|
22321
|
+
acceptedAt
|
|
22322
|
+
acceptedByName
|
|
22323
|
+
amount
|
|
22324
|
+
amountDue
|
|
22325
|
+
amountsByPeriod {
|
|
22326
|
+
id
|
|
22327
|
+
name
|
|
22328
|
+
amount
|
|
22329
|
+
}
|
|
22330
|
+
billingCity
|
|
22331
|
+
billingCountry
|
|
22332
|
+
billingState
|
|
22333
|
+
billingStreet
|
|
22334
|
+
billingZip
|
|
22335
|
+
contactName
|
|
22336
|
+
currency
|
|
22337
|
+
customerBillingCity
|
|
22338
|
+
customerBillingCountry
|
|
22339
|
+
customerBillingState
|
|
22340
|
+
customerBillingStreet
|
|
22341
|
+
customerBillingZip
|
|
22342
|
+
customerName
|
|
22343
|
+
discount
|
|
22344
|
+
discountValue
|
|
22345
|
+
duration
|
|
22346
|
+
endDate
|
|
22347
|
+
expiresAt
|
|
22348
|
+
html
|
|
22349
|
+
formattedLines {
|
|
22350
|
+
amount
|
|
22351
|
+
amountsByPeriod {
|
|
22352
|
+
quantity
|
|
22353
|
+
id
|
|
22354
|
+
name
|
|
22355
|
+
startDate
|
|
22356
|
+
endDate
|
|
22357
|
+
amount
|
|
22358
|
+
amountsByTier {
|
|
22359
|
+
id
|
|
22360
|
+
tier {
|
|
22361
|
+
starts
|
|
22362
|
+
ends
|
|
22363
|
+
price
|
|
22364
|
+
}
|
|
22365
|
+
quantity
|
|
22366
|
+
amount
|
|
22367
|
+
}
|
|
22368
|
+
prorationRate
|
|
22369
|
+
}
|
|
22370
|
+
billingPeriodEnd
|
|
22371
|
+
billingPeriodStart
|
|
22372
|
+
chargeType
|
|
22373
|
+
discount
|
|
22374
|
+
frequency
|
|
22375
|
+
isRamp
|
|
22376
|
+
periods
|
|
22377
|
+
planName
|
|
22378
|
+
position
|
|
22379
|
+
price
|
|
22380
|
+
priceDecimals
|
|
22381
|
+
priceListChargeId
|
|
22382
|
+
priceListChargeName
|
|
22383
|
+
priceListId
|
|
22384
|
+
priceListName
|
|
22385
|
+
priceTiers {
|
|
22386
|
+
price
|
|
22387
|
+
starts
|
|
22388
|
+
}
|
|
22389
|
+
pricingModel
|
|
22390
|
+
productName
|
|
22391
|
+
prorationRate
|
|
22392
|
+
quantity
|
|
22393
|
+
showProductNameOnLineItem
|
|
22394
|
+
taxCode
|
|
22395
|
+
trialEndDate
|
|
22396
|
+
trialStartDate
|
|
22397
|
+
unitOfMeasure
|
|
22398
|
+
vatCode
|
|
22399
|
+
}
|
|
22400
|
+
netPaymentDays
|
|
22401
|
+
notes
|
|
22402
|
+
number
|
|
22403
|
+
poNumberRequired
|
|
22404
|
+
salesContactEmail
|
|
22405
|
+
sharedAt
|
|
22406
|
+
startDate
|
|
22407
|
+
state
|
|
22408
|
+
subtotal
|
|
22409
|
+
taxAmount
|
|
22410
|
+
taxNumberLabel
|
|
22411
|
+
taxNumberRequired
|
|
22412
|
+
vendorName
|
|
22413
|
+
...useQuotePaymentHold_FormattedQuoteFragment
|
|
22414
|
+
...PaymentHoldModal_FormattedQuoteFragment
|
|
22415
|
+
...AcceptQuoteModal_FormattedQuoteFragment
|
|
22416
|
+
...QuoteButtons_FormattedQuoteFragment
|
|
22417
|
+
}
|
|
22418
|
+
}
|
|
22419
|
+
`, [
|
|
22420
|
+
useQuotePaymentHold_FormattedQuoteFragment,
|
|
22421
|
+
PaymentHoldModal_FormattedQuoteFragment,
|
|
22422
|
+
AcceptQuoteModal_FormattedQuoteFragment,
|
|
22423
|
+
QuoteButtons_FormattedQuoteFragment,
|
|
22424
|
+
PaymentHoldDisplay_QuoteButtonsFragment,
|
|
22425
|
+
]);
|
|
22426
|
+
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
22427
|
+
const response = await execute(query$7, { apiHost, token }, { id });
|
|
22428
|
+
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
22372
22429
|
};
|
|
22373
22430
|
|
|
22374
22431
|
const showErrorNotification$4 = useErrorNotification();
|
|
22375
|
-
|
|
22376
|
-
|
|
22377
|
-
|
|
22378
|
-
|
|
22379
|
-
|
|
22432
|
+
t(`
|
|
22433
|
+
fragment Quote_PaymentHoldFragment on FormattedQuote {
|
|
22434
|
+
quote {
|
|
22435
|
+
currentPaymentHold {
|
|
22436
|
+
...PaymentHoldDisplay_QuoteButtonsFragment
|
|
22437
|
+
}
|
|
22438
|
+
firstInvoice {
|
|
22439
|
+
id
|
|
22440
|
+
}
|
|
22441
|
+
}
|
|
22442
|
+
}
|
|
22443
|
+
`, [PaymentHoldDisplay_QuoteButtonsFragment]);
|
|
22444
|
+
t(`
|
|
22445
|
+
fragment OnQuoteLoadedFragment on FormattedQuote {
|
|
22446
|
+
vendorName
|
|
22447
|
+
quote {
|
|
22448
|
+
id
|
|
22449
|
+
}
|
|
22450
|
+
}
|
|
22451
|
+
`);
|
|
22380
22452
|
function Quote({ id, invoiceQuoteViewComponent, onInvoiceDownloadError, onPaymentSuccess, shadow = 'shadow-md', className, hideDownloadButton = false, onQuoteLoaded, onQuoteAccepted, onQuoteUnavailableError, suppressQuoteUnavailableErrorNotification = false, }) {
|
|
22381
22453
|
return (jsx(InvoiceQuoteContext.Provider, { value: {
|
|
22382
22454
|
id,
|
|
@@ -22386,30 +22458,16 @@ function Quote({ id, invoiceQuoteViewComponent, onInvoiceDownloadError, onPaymen
|
|
|
22386
22458
|
shadow,
|
|
22387
22459
|
className,
|
|
22388
22460
|
hideDownloadButton,
|
|
22389
|
-
onQuoteLoaded,
|
|
22390
22461
|
onQuoteUnavailableError,
|
|
22391
22462
|
suppressQuoteUnavailableErrorNotification,
|
|
22392
|
-
}, children: jsx(ActualQuote, { onQuoteAccepted: onQuoteAccepted }) }));
|
|
22463
|
+
}, children: jsx(ActualQuote, { onQuoteAccepted: onQuoteAccepted, onQuoteLoaded: onQuoteLoaded }) }));
|
|
22393
22464
|
}
|
|
22394
|
-
|
|
22395
|
-
var _a, _b;
|
|
22396
|
-
const [paymentHoldModalVisible, setPaymentHoldModalVisible] = useState(false);
|
|
22397
|
-
const shouldDoPaymentHold = ((_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.payToAccept) == true;
|
|
22398
|
-
const currentPaymentHold = (_b = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.currentPaymentHold;
|
|
22399
|
-
return {
|
|
22400
|
-
paymentHold: currentPaymentHold,
|
|
22401
|
-
paymentHoldModalVisible,
|
|
22402
|
-
setPaymentHoldModalVisible,
|
|
22403
|
-
shouldDoPaymentHold,
|
|
22404
|
-
paymentHoldCompleted: currentPaymentHold ? true : false,
|
|
22405
|
-
};
|
|
22406
|
-
};
|
|
22407
|
-
function ActualQuote({ onQuoteAccepted }) {
|
|
22408
|
-
var _a, _b, _c, _d, _e, _f;
|
|
22465
|
+
function ActualQuote({ onQuoteAccepted, onQuoteLoaded }) {
|
|
22466
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
22409
22467
|
// Context
|
|
22410
22468
|
const { apiHost } = useContext(BunnyContext);
|
|
22411
22469
|
const token = useToken();
|
|
22412
|
-
const { className, id, hideDownloadButton,
|
|
22470
|
+
const { className, id, hideDownloadButton, onQuoteUnavailableError, suppressQuoteUnavailableErrorNotification } = useContext(InvoiceQuoteContext);
|
|
22413
22471
|
// Queries
|
|
22414
22472
|
const { data: formattedQuote, isLoading, error } = useQuery({
|
|
22415
22473
|
queryKey: QueryKeyFactory.createQuoteKey({ id, token }),
|
|
@@ -22419,7 +22477,7 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22419
22477
|
placeholderData: keepPreviousData,
|
|
22420
22478
|
});
|
|
22421
22479
|
// Hooks
|
|
22422
|
-
const { acceptBoxVisible, isAccepting, sendAccept, setAcceptBoxVisible, setIsAccepting, startAcceptance, pandadocPollingModalVisible, setPandadocPollingModalVisible, isSendAcceptPending, } =
|
|
22480
|
+
const { acceptBoxVisible, isAccepting, sendAccept, setAcceptBoxVisible, setIsAccepting, startAcceptance, pandadocPollingModalVisible, setPandadocPollingModalVisible, isSendAcceptPending, } = useAcceptQuote({
|
|
22423
22481
|
token,
|
|
22424
22482
|
apiHost,
|
|
22425
22483
|
quoteId: id,
|
|
@@ -22429,7 +22487,7 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22429
22487
|
const isMobile = useIsMobile();
|
|
22430
22488
|
useEffect(() => {
|
|
22431
22489
|
if (formattedQuote) {
|
|
22432
|
-
onQuoteLoaded === null || onQuoteLoaded === void 0 ? void 0 : onQuoteLoaded(formattedQuote);
|
|
22490
|
+
onQuoteLoaded === null || onQuoteLoaded === void 0 ? void 0 : onQuoteLoaded(formattedQuote);
|
|
22433
22491
|
}
|
|
22434
22492
|
}, [formattedQuote]);
|
|
22435
22493
|
useEffect(() => {
|
|
@@ -22445,7 +22503,8 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22445
22503
|
}
|
|
22446
22504
|
}, [error]);
|
|
22447
22505
|
// Payment hold stuff here
|
|
22448
|
-
const { paymentHoldModalVisible, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted,
|
|
22506
|
+
const { paymentHoldModalVisible, setPaymentHoldModalVisible, shouldDoPaymentHold, paymentHoldCompleted, } = useQuotePaymentHold(formattedQuote);
|
|
22507
|
+
const paymentHold = (_a = formattedQuote === null || formattedQuote === void 0 ? void 0 : formattedQuote.quote) === null || _a === void 0 ? void 0 : _a.currentPaymentHold;
|
|
22449
22508
|
const handleClickAccept = () => {
|
|
22450
22509
|
if (shouldDoPaymentHold && !paymentHoldCompleted) {
|
|
22451
22510
|
setPaymentHoldModalVisible(true);
|
|
@@ -22459,12 +22518,12 @@ function ActualQuote({ onQuoteAccepted }) {
|
|
|
22459
22518
|
}
|
|
22460
22519
|
// Derived state
|
|
22461
22520
|
const isAccepted = formattedQuote.state === 'ACCEPTED';
|
|
22462
|
-
const firstInvoice = (
|
|
22521
|
+
const firstInvoice = (_b = formattedQuote.quote) === null || _b === void 0 ? void 0 : _b.firstInvoice;
|
|
22463
22522
|
if ((firstInvoice === null || firstInvoice === void 0 ? void 0 : firstInvoice.state) === 'PAID' && paymentHoldCompleted) {
|
|
22464
22523
|
return jsx(Invoice, { id: firstInvoice.id });
|
|
22465
22524
|
}
|
|
22466
|
-
return (jsxs(Fragment, { children: [jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-4 ${isMobile ? 'bunny-w-full bunny-overflow-hidden' : ''} ${className}`, children: [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 }), jsx(InvoiceQuoteView, { html: formattedQuote.html, targetUrl: ((
|
|
22467
|
-
((
|
|
22525
|
+
return (jsxs(Fragment, { children: [jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-4 ${isMobile ? 'bunny-w-full bunny-overflow-hidden' : ''} ${className}`, children: [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 }), 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) &&
|
|
22526
|
+
((_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 ? (jsx("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: formattedQuote.quote.documents.map((doc, index) => {
|
|
22468
22527
|
return (jsx(Button, { download: doc.filename, href: doc.url, type: "link", children: doc.filename }, index));
|
|
22469
22528
|
}) })) : null })] }), jsx(AcceptQuoteModal, { acceptBoxVisible: acceptBoxVisible, formattedQuote: formattedQuote, setAcceptBoxVisible: setAcceptBoxVisible, setIsAccepting: setIsAccepting, sendAccept: sendAccept, isSendAcceptPending: isSendAcceptPending }), jsx(PaymentHoldModal, { visible: paymentHoldModalVisible, setVisible: setPaymentHoldModalVisible, formattedQuote: formattedQuote, sendAccept: sendAccept }), jsx(PandadocPollingModal, { isVisible: pandadocPollingModalVisible, setVisible: setPandadocPollingModalVisible, id: id })] }));
|
|
22470
22529
|
}
|
|
@@ -22992,7 +23051,6 @@ function canApplyCoupons(maskedQuote, activeCouponsExist, maskedUpgradingSubscri
|
|
|
22992
23051
|
if (quoteKindIsValid) {
|
|
22993
23052
|
const result = activeCouponsExist &&
|
|
22994
23053
|
(upgradingFromTrial || upgradingFromFree() || signingUpForNewSubscription);
|
|
22995
|
-
console.log('returning result', result);
|
|
22996
23054
|
return result;
|
|
22997
23055
|
}
|
|
22998
23056
|
return false;
|
|
@@ -30185,11 +30243,7 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
30185
30243
|
return countryListFilter ? COUNTRY_LIST.filter(countryListFilter) : COUNTRY_LIST;
|
|
30186
30244
|
}, [countryListFilter]);
|
|
30187
30245
|
const isLoading = isLoadingAccount || isLoadingContacts;
|
|
30188
|
-
return (jsxs("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: [jsxs("div", { className: "bunny-px-4", children: [jsxs(Skeleton, { loading: isLoading || account === undefined, children: [jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (account === null || account === void 0 ? void 0 : account.name) || 'No company name' }) }), jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingAccount, autoComplete: "off",
|
|
30189
|
-
{
|
|
30190
|
-
required: false,
|
|
30191
|
-
},
|
|
30192
|
-
], children: jsx(Input, {}) }) }), jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsx(Form.Item, { label: "Country", name: "billingCountry", rules: [{ required: true, message: 'Country is required' }], children: jsx(Select, { className: "bunny-w-full", options: filteredCountryList, placeholder: "Select a country", popupMatchSelectWidth: false, showSearch: true, filterOption: (input, option) => {
|
|
30246
|
+
return (jsxs("div", { className: `${isMobile || hidePaymentMethodForm ? 'bunny-w-full' : 'bunny-w-1/2'}`, children: [jsxs("div", { className: "bunny-px-4", children: [jsxs(Skeleton, { loading: isLoading || account === undefined, children: [jsx("div", { className: "bunny-mb-2 bunny-pl-1", children: jsx(Text, { className: "bunny-font-medium bunny-text-lg", children: (account === null || account === void 0 ? void 0 : account.name) || 'No company name' }) }), jsxs(Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", disabled: isUpdatingAccount, autoComplete: "off", children: [jsx(Form.Item, { label: "Street address", name: "billingStreet", children: jsx(Input, {}) }), jsxs("div", { className: "bunny-flex bunny-gap-4", children: [jsx(Form.Item, { label: "City", name: "billingCity", className: "bunny-flex-1", children: jsx(Input, {}) }), jsx(Form.Item, { label: "Zipcode", name: "billingZip", className: "bunny-flex-1", children: jsx(Input, {}) })] }), jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-row bunny-pb-2' : 'bunny-flex-row'} bunny-gap-4`, children: [jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsx(Form.Item, { label: "State", name: "billingState", children: jsx(Input, {}) }) }), jsx("div", { className: "bunny-flex-1 bunny-w-1/2", children: jsx(Form.Item, { label: "Country", name: "billingCountry", children: jsx(Select, { className: "bunny-w-full", options: filteredCountryList, placeholder: "Select a country", popupMatchSelectWidth: false, showSearch: true, filterOption: (input, option) => {
|
|
30193
30247
|
var _a, _b;
|
|
30194
30248
|
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
30195
30249
|
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
@@ -30214,7 +30268,7 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
30214
30268
|
})) !== null && _c !== void 0 ? _c : [], popupRender: menu => (jsxs(Fragment, { children: [menu, jsx(AddContactButton, { onClick: () => {
|
|
30215
30269
|
setContactFieldType('secondary');
|
|
30216
30270
|
setIsAddContactModalOpen(true);
|
|
30217
|
-
} })] })) }) }), jsx(Form.Item, { label: "Tax ID", name: "taxNumber", tooltip: "Tax ID will be printed on quotes and invoices below the account's address",
|
|
30271
|
+
} })] })) }) }), jsx(Form.Item, { label: "Tax ID", name: "taxNumber", tooltip: "Tax ID will be printed on quotes and invoices below the account's address", children: jsx(Input, {}) })] })] }), jsx(Button, { disabled: !isFormEdited || isUpdatingAccount || isLoading, className: "bunny-w-full bunny-mt-4", type: "primary", onClick: saveBillingDetails, children: "Save" })] }), jsx(AddContactModal, { open: isAddContactModalOpen, onClose: () => {
|
|
30218
30272
|
setIsAddContactModalOpen(false);
|
|
30219
30273
|
setContactFieldType(null);
|
|
30220
30274
|
}, accountId: accountId, onContactCreated: handleContactCreated })] }));
|