@bunnyapp/components 1.6.0 → 1.7.0-beta.3
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 +1561 -1258
- package/dist/cjs/types/src/components/BillingDetails/BillingDetailsForm.d.ts +0 -1
- package/dist/cjs/types/src/components/BillingDetails/components/AddContactButton.d.ts +3 -0
- package/dist/cjs/types/src/components/BillingDetails/components/AddContactModal.d.ts +8 -0
- package/dist/cjs/types/src/components/BillingDetails/fragments/AccountContactsFragment.d.ts +9 -0
- package/dist/cjs/types/src/components/BillingDetails/fragments/BillingDetailsSection_AccountFragment.d.ts +20 -0
- package/dist/cjs/types/src/components/BillingDetails/hooks/useSetAccountContactsQueryData.d.ts +5 -0
- package/dist/cjs/types/src/components/BillingDetails/mutations/accountUpdate.d.ts +22 -0
- package/dist/cjs/types/src/components/BillingDetails/mutations/contactCreate.d.ts +22 -0
- package/dist/cjs/types/src/components/BillingDetails/queries/getAccount.d.ts +9 -0
- package/dist/cjs/types/src/components/BillingDetails/queries/getAccountContacts.d.ts +9 -0
- package/dist/cjs/types/src/components/Checkout/Checkout.d.ts +2 -1
- package/dist/cjs/types/src/components/QuoteProvider/context/QuoteContext.d.ts +1 -0
- package/dist/cjs/types/src/components/QuoteProvider/fragments/quoteFragment.d.ts +7 -0
- package/dist/cjs/types/src/components/QuoteProvider/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
- package/dist/cjs/types/src/components/QuoteProvider/hooks/useSetQuoteQueryData.d.ts +5 -0
- package/dist/cjs/types/src/components/QuoteProvider/mutations/quoteRecalculateTaxes.d.ts +11 -0
- package/dist/cjs/types/src/components/Subscriptions/AddonSubscriptionCards.d.ts +3 -2
- package/dist/cjs/types/src/components/Subscriptions/SubscriptionsListContainer.d.ts +2 -2
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutBarSummarySection.d.ts +15 -2
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutButton.d.ts +2 -2
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +12 -3
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/FeatureAddonRow_QuoteFragment.d.ts +9 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/useQuoteUpdateFeatureAddon_QuoteFragment.d.ts +8 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/hooks/useQuoteUpdateFeatureAddon.d.ts +9 -0
- package/dist/cjs/types/src/{graphql → components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons}/mutations/quoteChargeCreate.d.ts +12 -2
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/components/AddonPlanRow.d.ts +1 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/AddonPlanRow_QuoteFragment.d.ts +9 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/useToggleAddonPlan_QuoteFragment.d.ts +13 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/hooks/useToggleAddonQuoteChange.d.ts +9 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeCreate.d.ts +18 -0
- package/dist/cjs/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeDelete.d.ts +15 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteIsLoadingContext.d.ts +5 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteRecalculateTaxesContext.d.ts +6 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteDelete.d.ts +12 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteRecalculateTaxes.d.ts +11 -0
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuantityInput.d.ts +10 -1
- package/dist/cjs/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuoteIsLoadingUpdater.d.ts +9 -0
- package/dist/cjs/types/src/components/Subscriptions/subscriptionsList/SubscriptionsList.d.ts +2 -2
- package/dist/cjs/types/src/components/Subscriptions/tieredDisplayDropdown/TieredDisplayDropdown.d.ts +3 -1
- package/dist/cjs/types/src/utils/QueryKeyFactory.d.ts +10 -0
- package/dist/esm/index.js +1562 -1259
- package/dist/esm/types/src/components/BillingDetails/BillingDetailsForm.d.ts +0 -1
- package/dist/esm/types/src/components/BillingDetails/components/AddContactButton.d.ts +3 -0
- package/dist/esm/types/src/components/BillingDetails/components/AddContactModal.d.ts +8 -0
- package/dist/esm/types/src/components/BillingDetails/fragments/AccountContactsFragment.d.ts +9 -0
- package/dist/esm/types/src/components/BillingDetails/fragments/BillingDetailsSection_AccountFragment.d.ts +20 -0
- package/dist/esm/types/src/components/BillingDetails/hooks/useSetAccountContactsQueryData.d.ts +5 -0
- package/dist/esm/types/src/components/BillingDetails/mutations/accountUpdate.d.ts +22 -0
- package/dist/esm/types/src/components/BillingDetails/mutations/contactCreate.d.ts +22 -0
- package/dist/esm/types/src/components/BillingDetails/queries/getAccount.d.ts +9 -0
- package/dist/esm/types/src/components/BillingDetails/queries/getAccountContacts.d.ts +9 -0
- package/dist/esm/types/src/components/Checkout/Checkout.d.ts +2 -1
- package/dist/esm/types/src/components/QuoteProvider/context/QuoteContext.d.ts +1 -0
- package/dist/esm/types/src/components/QuoteProvider/fragments/quoteFragment.d.ts +7 -0
- package/dist/esm/types/src/components/QuoteProvider/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
- package/dist/esm/types/src/components/QuoteProvider/hooks/useSetQuoteQueryData.d.ts +5 -0
- package/dist/esm/types/src/components/QuoteProvider/mutations/quoteRecalculateTaxes.d.ts +11 -0
- package/dist/esm/types/src/components/Subscriptions/AddonSubscriptionCards.d.ts +3 -2
- package/dist/esm/types/src/components/Subscriptions/SubscriptionsListContainer.d.ts +2 -2
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutBarSummarySection.d.ts +15 -2
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutButton.d.ts +2 -2
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/checkoutBar/CheckoutPrice.d.ts +12 -3
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/FeatureAddonRow_QuoteFragment.d.ts +9 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/fragments/useQuoteUpdateFeatureAddon_QuoteFragment.d.ts +8 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons/hooks/useQuoteUpdateFeatureAddon.d.ts +9 -0
- package/dist/esm/types/src/{graphql → components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/featureAddons}/mutations/quoteChargeCreate.d.ts +12 -2
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/components/AddonPlanRow.d.ts +1 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/AddonPlanRow_QuoteFragment.d.ts +9 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/fragments/useToggleAddonPlan_QuoteFragment.d.ts +13 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/hooks/useToggleAddonQuoteChange.d.ts +9 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeCreate.d.ts +18 -0
- package/dist/esm/types/src/components/Subscriptions/Upgrade/PlanPicker/planPickerDesktop/priceListCardDesktop/addonPlans/mutations/quoteChangeDelete.d.ts +15 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteIsLoadingContext.d.ts +5 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/context/quoteRecalculateTaxesContext.d.ts +6 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/hooks/useQuoteRecalculateTaxes.d.ts +11 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteDelete.d.ts +12 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/mutations/quoteRecalculateTaxes.d.ts +11 -0
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuantityInput.d.ts +10 -1
- package/dist/esm/types/src/components/Subscriptions/quantityChangeDrawer/quantityInput/QuoteIsLoadingUpdater.d.ts +9 -0
- package/dist/esm/types/src/components/Subscriptions/subscriptionsList/SubscriptionsList.d.ts +2 -2
- package/dist/esm/types/src/components/Subscriptions/tieredDisplayDropdown/TieredDisplayDropdown.d.ts +3 -1
- package/dist/esm/types/src/utils/QueryKeyFactory.d.ts +10 -0
- package/package.json +2 -2
- package/dist/cjs/types/src/graphql/mutations/billingDetailsUpdate.d.ts +0 -6
- package/dist/cjs/types/src/graphql/mutations/quoteAddonCreate.d.ts +0 -7
- package/dist/cjs/types/src/graphql/mutations/quoteChangeCreate.d.ts +0 -8
- package/dist/cjs/types/src/graphql/mutations/quoteChangeDelete.d.ts +0 -6
- package/dist/cjs/types/src/graphql/queries/getBillingDetails.d.ts +0 -6
- package/dist/cjs/types/src/hooks/quotes/useQuoteUpdateFeatureAddon.d.ts +0 -7
- package/dist/cjs/types/src/hooks/useToggleAddonQuoteChange.d.ts +0 -7
- package/dist/esm/types/src/graphql/mutations/billingDetailsUpdate.d.ts +0 -6
- package/dist/esm/types/src/graphql/mutations/quoteAddonCreate.d.ts +0 -7
- package/dist/esm/types/src/graphql/mutations/quoteChangeCreate.d.ts +0 -8
- package/dist/esm/types/src/graphql/mutations/quoteChangeDelete.d.ts +0 -6
- package/dist/esm/types/src/graphql/queries/getBillingDetails.d.ts +0 -6
- package/dist/esm/types/src/hooks/quotes/useQuoteUpdateFeatureAddon.d.ts +0 -7
- package/dist/esm/types/src/hooks/useToggleAddonQuoteChange.d.ts +0 -7
package/dist/cjs/index.js
CHANGED
|
@@ -48,7 +48,7 @@ function styleInject(css, ref) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
var css_248z = ":root {\n --row-background: #ffffff;\n --row-background-alternate: rgba(100, 116, 139, 0.04);\n --row-background-dark: #121212;\n --row-background-alternate-dark: #1e1e1e;\n --bunny-blue-500: #3b82f6;\n --bunny-blue-200: #bfdbfe;\n --bunny-green-600: #059669;\n --bunny-green-200: #a7f3d0;\n --bunny-red-500: #ef4444;\n --bunny-red-200: #fecaca;\n --bunny-orange-500: #f97316;\n --bunny-orange-200: #fed7aa;\n --bunny-yellow-500: #f59e0b;\n --bunny-yellow-200: #fde68a;\n --bunny-purple-500: #8b5cf6;\n --bunny-purple-200: #ddd6fe;\n --bunny-black: #000000;\n}\n.bunny-component-wrapper {\n box-sizing: border-box;\n}\n.bunny-component-wrapper * {\n box-sizing: border-box;\n}\n.hidden {\n display: none;\n}\n.bunny-show-on-hover {\n opacity: 0;\n}\n.bunny-show-on-hover-container:hover .bunny-show-on-hover {\n opacity: 1;\n}\n.has-tooltip:hover .tooltip {\n visibility: visible;\n z-index: 100;\n}\n.pdf-only {\n display: none !important;\n}\n.notes p {\n margin: 0;\n padding: 0;\n padding-bottom: 0.25rem;\n}\n.bunny-icon-path {\n transition: fill 0.3s;\n}\n.bunny-shadow-padding-x {\n padding-right: 1rem;\n padding-left: 1rem;\n}\n.bunny-shadow-padding-xb {\n padding-right: 1rem;\n padding-left: 1rem;\n padding-bottom: 0.5rem;\n}\n.content-container {\n width: 100%;\n margin: 0 auto;\n}\n@media (min-width: 1220px) {\n .content-container {\n width: 1220px !important;\n margin: 0 auto;\n }\n}\n@media (min-width: 768px) {\n .bunny-shadow-padding-x {\n padding-right: 2rem;\n padding-left: 2rem;\n }\n .bunny-shadow-padding-xb {\n padding-right: 2rem;\n padding-left: 2rem;\n padding-bottom: 0.5rem;\n }\n .sm\\:flex {\n display: flex !important;\n }\n .sm\\:hidden {\n display: none !important;\n }\n}\n.bunny-shadow,\n.bunny-shadow-md {\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n}\n.bunny-fixed {\n position: fixed;\n}\n.bunny-absolute {\n position: absolute;\n}\n.bunny-relative {\n position: relative;\n}\n.bunny-sticky {\n position: sticky;\n}\n.bunny-bottom-0 {\n bottom: 0px;\n}\n.bunny-bottom-4 {\n bottom: 1rem;\n}\n.bunny-left-0 {\n left: 0px;\n}\n.bunny-right-0 {\n right: 0px;\n}\n.bunny-top-0 {\n top: 0px;\n}\n.bunny-col-span-1 {\n grid-column: span 1 / span 1;\n}\n.bunny-col-span-full {\n grid-column: 1 / -1;\n}\n.bunny-m-0 {\n margin: 0px;\n}\n.bunny-mx-0 {\n margin-left: 0px;\n margin-right: 0px;\n}\n.bunny-mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.bunny-mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.bunny-my-0 {\n margin-top: 0px;\n margin-bottom: 0px;\n}\n.bunny-my-2 {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.bunny-my-24 {\n margin-top: 6rem;\n margin-bottom: 6rem;\n}\n.bunny-my-4 {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.bunny-mb-2 {\n margin-bottom: 0.5rem;\n}\n.bunny-mb-3 {\n margin-bottom: 0.75rem;\n}\n.bunny-mb-4 {\n margin-bottom: 1rem;\n}\n.bunny-mb-8 {\n margin-bottom: 2rem;\n}\n.bunny-ml-auto {\n margin-left: auto;\n}\n.bunny-mt-0 {\n margin-top: 0px;\n}\n.bunny-mt-2 {\n margin-top: 0.5rem;\n}\n.bunny-mt-24 {\n margin-top: 6rem;\n}\n.bunny-mt-4 {\n margin-top: 1rem;\n}\n.bunny-mt-5 {\n margin-top: 1.25rem;\n}\n.bunny-box-border {\n box-sizing: border-box;\n}\n.bunny-flex {\n display: flex;\n}\n.bunny-grid {\n display: grid;\n}\n.bunny-contents {\n display: contents;\n}\n.bunny-h-0\\.5 {\n height: 0.125rem;\n}\n.bunny-h-1\\/2 {\n height: 50%;\n}\n.bunny-h-8 {\n height: 2rem;\n}\n.bunny-h-full {\n height: 100%;\n}\n.bunny-h-screen {\n height: 100vh;\n}\n.bunny-max-h-\\[calc\\(100vh-10rem\\)\\] {\n max-height: calc(100vh - 10rem);\n}\n.bunny-min-h-0 {\n min-height: 0px;\n}\n.bunny-w-0\\.5 {\n width: 0.125rem;\n}\n.bunny-w-1\\/2 {\n width: 50%;\n}\n.bunny-w-3\\/5 {\n width: 60%;\n}\n.bunny-w-full {\n width: 100%;\n}\n.bunny-w-screen {\n width: 100vw;\n}\n.bunny-flex-1 {\n flex: 1 1 0%;\n}\n.bunny-shrink {\n flex-shrink: 1;\n}\n.bunny-shrink-0 {\n flex-shrink: 0;\n}\n.bunny-grow {\n flex-grow: 1;\n}\n.bunny-cursor-pointer {\n cursor: pointer;\n}\n.bunny-grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.bunny-flex-row {\n flex-direction: row;\n}\n.bunny-flex-col {\n flex-direction: column;\n}\n.bunny-flex-wrap {\n flex-wrap: wrap;\n}\n.bunny-items-start {\n align-items: flex-start;\n}\n.bunny-items-end {\n align-items: flex-end;\n}\n.bunny-items-center {\n align-items: center;\n}\n.bunny-justify-end {\n justify-content: flex-end;\n}\n.bunny-justify-center {\n justify-content: center;\n}\n.bunny-justify-between {\n justify-content: space-between;\n}\n.bunny-gap-0 {\n gap: 0px;\n}\n.bunny-gap-1 {\n gap: 0.25rem;\n}\n.bunny-gap-2 {\n gap: 0.5rem;\n}\n.bunny-gap-3 {\n gap: 0.75rem;\n}\n.bunny-gap-4 {\n gap: 1rem;\n}\n.bunny-gap-6 {\n gap: 1.5rem;\n}\n.bunny-gap-8 {\n gap: 2rem;\n}\n.bunny-space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.bunny-space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.bunny-space-y-8 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(2rem * var(--tw-space-y-reverse));\n}\n.bunny-overflow-auto {\n overflow: auto;\n}\n.bunny-overflow-hidden {\n overflow: hidden;\n}\n.bunny-overflow-y-auto {\n overflow-y: auto;\n}\n.bunny-whitespace-nowrap {\n white-space: nowrap;\n}\n.bunny-text-nowrap {\n text-wrap: nowrap;\n}\n.bunny-rounded {\n border-radius: 0.25rem;\n}\n.bunny-rounded-full {\n border-radius: 9999px;\n}\n.bunny-rounded-lg {\n border-radius: 0.5rem;\n}\n.bunny-rounded-md {\n border-radius: 0.375rem;\n}\n.bunny-border {\n border-width: 1px;\n}\n.bunny-border-2 {\n border-width: 2px;\n}\n.bunny-border-solid {\n border-style: solid;\n}\n.bunny-border-none {\n border-style: none;\n}\n.bunny-border-slate-200 {\n --tw-border-opacity: 1;\n border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));\n}\n.bunny-bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.bunny-bg-slate-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));\n}\n.bunny-bg-transparent {\n background-color: transparent;\n}\n.bunny-bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.bunny-p-0 {\n padding: 0px;\n}\n.bunny-p-1 {\n padding: 0.25rem;\n}\n.bunny-p-2 {\n padding: 0.5rem;\n}\n.bunny-p-4 {\n padding: 1rem;\n}\n.bunny-px-12 {\n padding-left: 3rem;\n padding-right: 3rem;\n}\n.bunny-px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.bunny-px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.bunny-px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n}\n.bunny-py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.bunny-py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.bunny-py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.bunny-pb-2 {\n padding-bottom: 0.5rem;\n}\n.bunny-pb-4 {\n padding-bottom: 1rem;\n}\n.bunny-pb-6 {\n padding-bottom: 1.5rem;\n}\n.bunny-pb-8 {\n padding-bottom: 2rem;\n}\n.bunny-pl-0 {\n padding-left: 0px;\n}\n.bunny-pl-1 {\n padding-left: 0.25rem;\n}\n.bunny-pl-4 {\n padding-left: 1rem;\n}\n.bunny-pr-4 {\n padding-right: 1rem;\n}\n.bunny-pt-1 {\n padding-top: 0.25rem;\n}\n.bunny-pt-12 {\n padding-top: 3rem;\n}\n.bunny-pt-2 {\n padding-top: 0.5rem;\n}\n.bunny-pt-4 {\n padding-top: 1rem;\n}\n.bunny-pt-5 {\n padding-top: 1.25rem;\n}\n.bunny-pt-\\[25vh\\] {\n padding-top: 25vh;\n}\n.bunny-text-left {\n text-align: left;\n}\n.bunny-text-center {\n text-align: center;\n}\n.bunny-text-right {\n text-align: right;\n}\n.bunny-text-start {\n text-align: start;\n}\n.bunny-text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.bunny-text-3xl {\n font-size: 1.875rem;\n line-height: 2.25rem;\n}\n.bunny-text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.bunny-text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.bunny-text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.bunny-text-sm\\/5 {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.bunny-text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.bunny-text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.bunny-text-xs\\/3 {\n font-size: 0.75rem;\n line-height: 0.75rem;\n}\n.bunny-font-bold {\n font-weight: 700;\n}\n.bunny-font-medium {\n font-weight: 500;\n}\n.bunny-font-normal {\n font-weight: 400;\n}\n.bunny-text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.bunny-text-orange-500 {\n --tw-text-opacity: 1;\n color: rgb(249 115 22 / var(--tw-text-opacity, 1));\n}\n.bunny-text-orange-600 {\n --tw-text-opacity: 1;\n color: rgb(234 88 12 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-400 {\n --tw-text-opacity: 1;\n color: rgb(148 163 184 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-500 {\n --tw-text-opacity: 1;\n color: rgb(100 116 139 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-600 {\n --tw-text-opacity: 1;\n color: rgb(71 85 105 / var(--tw-text-opacity, 1));\n}\n.bunny-text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.bunny-underline {\n text-decoration-line: underline;\n}\n.bunny-shadow {\n --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.bunny-shadow-md {\n --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.bunny-transition-\\[margin\\] {\n transition-property: margin;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.bunny-duration-300 {\n transition-duration: 300ms;\n}\n.rotate-45,\n.transform {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n}\n.shadow,\n.shadow-lg,\n.shadow-md,\n.shadow-none,\n.shadow-sm,\n.shadow-xl {\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n}\n.container {\n width: 100%;\n}\n@media (min-width: 768px) {\n .container {\n max-width: 768px;\n }\n}\n@media (min-width: 1024px) {\n .container {\n max-width: 1024px;\n }\n}\n@media (min-width: 1280px) {\n .container {\n max-width: 1280px;\n }\n}\n@media (min-width: 1536px) {\n .container {\n max-width: 1536px;\n }\n}\n.visible {\n visibility: visible;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.sticky {\n position: sticky;\n}\n.-top-0\\.5 {\n top: -0.125rem;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.bottom-4 {\n bottom: 1rem;\n}\n.left-0 {\n left: 0px;\n}\n.right-0 {\n right: 0px;\n}\n.top-0 {\n top: 0px;\n}\n.z-50 {\n z-index: 50;\n}\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n.col-span-3 {\n grid-column: span 3 / span 3;\n}\n.col-span-full {\n grid-column: 1 / -1;\n}\n.m-0 {\n margin: 0px;\n}\n.mx-0 {\n margin-left: 0px;\n margin-right: 0px;\n}\n.mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.my-12 {\n margin-top: 3rem;\n margin-bottom: 3rem;\n}\n.my-2 {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.my-4 {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.mb-8 {\n margin-bottom: 2rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.mr-8 {\n margin-right: 2rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.mt-6 {\n margin-top: 1.5rem;\n}\n.mt-8 {\n margin-top: 2rem;\n}\n.block {\n display: block;\n}\n.flex {\n display: flex;\n}\n.table {\n display: table;\n}\n.grid {\n display: grid;\n}\n.contents {\n display: contents;\n}\n.hidden {\n display: none;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-full {\n height: 100%;\n}\n.w-1\\/2 {\n width: 50%;\n}\n.w-1\\/3 {\n width: 33.333333%;\n}\n.w-12 {\n width: 3rem;\n}\n.w-2\\/3 {\n width: 66.666667%;\n}\n.w-4 {\n width: 1rem;\n}\n.w-full {\n width: 100%;\n}\n.max-w-32 {\n max-width: 8rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.shrink {\n flex-shrink: 1;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.flex-grow {\n flex-grow: 1;\n}\n.grow {\n flex-grow: 1;\n}\n.border-collapse {\n border-collapse: collapse;\n}\n.rotate-45 {\n --tw-rotate: 45deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.flex-row {\n flex-direction: row;\n}\n.flex-col {\n flex-direction: column;\n}\n.items-end {\n align-items: flex-end;\n}\n.items-center {\n align-items: center;\n}\n.justify-start {\n justify-content: flex-start;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.gap-0 {\n gap: 0px;\n}\n.gap-1 {\n gap: 0.25rem;\n}\n.gap-2 {\n gap: 0.5rem;\n}\n.gap-3 {\n gap: 0.75rem;\n}\n.gap-4 {\n gap: 1rem;\n}\n.gap-6 {\n gap: 1.5rem;\n}\n.gap-8 {\n gap: 2rem;\n}\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.space-y-8 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(2rem * var(--tw-space-y-reverse));\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-visible {\n overflow: visible;\n}\n.whitespace-nowrap {\n white-space: nowrap;\n}\n.text-nowrap {\n text-wrap: nowrap;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: 0.5rem;\n}\n.rounded-md {\n border-radius: 0.375rem;\n}\n.rounded-sm {\n border-radius: 0.125rem;\n}\n.border {\n border-width: 1px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-solid {\n border-style: solid;\n}\n.border-none {\n border-style: none;\n}\n.border-gray-400 {\n --tw-border-opacity: 1;\n border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));\n}\n.border-gray-500 {\n --tw-border-opacity: 1;\n border-color: rgb(107 114 128 / var(--tw-border-opacity, 1));\n}\n.border-slate-200 {\n --tw-border-opacity: 1;\n border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));\n}\n.border-slate-300 {\n --tw-border-opacity: 1;\n border-color: rgb(203 213 225 / var(--tw-border-opacity, 1));\n}\n.border-slate-700 {\n --tw-border-opacity: 1;\n border-color: rgb(51 65 85 / var(--tw-border-opacity, 1));\n}\n.bg-black {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));\n}\n.bg-emerald-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(167 243 208 / var(--tw-bg-opacity, 1));\n}\n.bg-green-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(187 247 208 / var(--tw-bg-opacity, 1));\n}\n.bg-orange-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 215 170 / var(--tw-bg-opacity, 1));\n}\n.bg-red-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));\n}\n.bg-red-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));\n}\n.bg-slate-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.bg-yellow-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 240 138 / var(--tw-bg-opacity, 1));\n}\n.p-0 {\n padding: 0px;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-8 {\n padding: 2rem;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n}\n.px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.pb-2 {\n padding-bottom: 0.5rem;\n}\n.pb-4 {\n padding-bottom: 1rem;\n}\n.pb-6 {\n padding-bottom: 1.5rem;\n}\n.pb-8 {\n padding-bottom: 2rem;\n}\n.pl-0 {\n padding-left: 0px;\n}\n.pl-2 {\n padding-left: 0.5rem;\n}\n.pl-4 {\n padding-left: 1rem;\n}\n.pt-1 {\n padding-top: 0.25rem;\n}\n.pt-12 {\n padding-top: 3rem;\n}\n.pt-2 {\n padding-top: 0.5rem;\n}\n.pt-4 {\n padding-top: 1rem;\n}\n.pt-5 {\n padding-top: 1.25rem;\n}\n.pt-6 {\n padding-top: 1.5rem;\n}\n.pt-8 {\n padding-top: 2rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.text-right {\n text-align: right;\n}\n.align-middle {\n vertical-align: middle;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-normal {\n font-weight: 400;\n}\n.capitalize {\n text-transform: capitalize;\n}\n.text-emerald-600 {\n --tw-text-opacity: 1;\n color: rgb(5 150 105 / var(--tw-text-opacity, 1));\n}\n.text-emerald-700 {\n --tw-text-opacity: 1;\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.text-green-600 {\n --tw-text-opacity: 1;\n color: rgb(22 163 74 / var(--tw-text-opacity, 1));\n}\n.text-orange-500 {\n --tw-text-opacity: 1;\n color: rgb(249 115 22 / var(--tw-text-opacity, 1));\n}\n.text-orange-600 {\n --tw-text-opacity: 1;\n color: rgb(234 88 12 / var(--tw-text-opacity, 1));\n}\n.text-red-500 {\n --tw-text-opacity: 1;\n color: rgb(239 68 68 / var(--tw-text-opacity, 1));\n}\n.text-slate-400 {\n --tw-text-opacity: 1;\n color: rgb(148 163 184 / var(--tw-text-opacity, 1));\n}\n.text-slate-500 {\n --tw-text-opacity: 1;\n color: rgb(100 116 139 / var(--tw-text-opacity, 1));\n}\n.text-slate-600 {\n --tw-text-opacity: 1;\n color: rgb(71 85 105 / var(--tw-text-opacity, 1));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.text-yellow-500 {\n --tw-text-opacity: 1;\n color: rgb(234 179 8 / var(--tw-text-opacity, 1));\n}\n.underline {\n text-decoration-line: underline;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-md {\n --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-none {\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-\\[margin\\] {\n transition-property: margin;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.duration-200 {\n transition-duration: 200ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-slate-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(241 245 249 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-slate-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(226 232 240 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n@media (min-width: 768px) {\n .sm\\:flex {\n display: flex;\n }\n .sm\\:hidden {\n display: none;\n }\n}\n.hover\\:bunny-text-orange-400:hover {\n --tw-text-opacity: 1;\n color: rgb(251 146 60 / var(--tw-text-opacity, 1));\n}\n.bunny-components .ant-upload-select-picture-card {\n margin: 0 !important;\n}\n.bunny-components .ant-upload {\n border-radius: 0.5rem !important;\n}\n.bunny-components .ant-row {\n margin-bottom: 0px;\n}\n.bunny-components .ant-select-disabled .ant-select-selector .ant-select-selection-item {\n color: rgba(0, 0, 0, 0.25) !important;\n}\n.bunny-components .ant-input-number,\n.bunny-components .ant-input,\n.bunny-components .ant-picker,\n.bunny-components .ant-input-affix-wrapper,\n.bunny-components .ant-select-selector {\n font-size: 0.875rem !important;\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n color: #232323 !important;\n}\n.bunny-components .ant-input-affix-wrapper {\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n}\n.bunny-components .ant-input-group-addon,\n.bunny-components .ant-input-number-group-addon {\n color: #475569 !important;\n}\n.bunny-components .ant-input-number-group-wrapper,\n.bunny-components .ant-input-number-affix-wrapper {\n width: 100%;\n}\n.bunny-components .ant-input-affix-wrapper input {\n border: none !important;\n}\n.bunny-components .ant-form-item {\n margin-bottom: 0;\n}\n.bunny-components .ant-form-item-label {\n text-transform: none !important;\n font-size: 0.75rem;\n padding-bottom: 2px !important;\n}\n.bunny-components .ant-form-item-label > label {\n width: 100%;\n color: #4b5563 !important;\n}\n.bunny-components .form .ant-form-item-label label {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n box-sizing: border-box;\n}\n.bunny-components .ant-form-item-explain,\n.bunny-components .ant-form-item-explain-error {\n font-size: 11px;\n min-height: 11px;\n line-height: 11px;\n padding-top: 2px;\n}\n.bunny-components .ant-timeline-item-content {\n font-size: smaller;\n}\n.bunny-components .ant-tree {\n font-size: 0.875rem;\n}\n.bunny-components .ant-tree-treenode {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-draggable-icon {\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-node-content-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-switcher {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-page-header {\n padding-left: 0;\n padding-right: 0;\n padding-top: 0;\n}\n.bunny-components .ant-tag {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 14px;\n font-weight: 500;\n white-space: nowrap;\n padding-inline-start: 0.625rem;\n padding-inline-end: 0.625rem;\n margin: 0;\n}\n.bunny-components .ant-tag-blue {\n color: #3b82f6 !important;\n background: #bfdbfe !important;\n}\n.bunny-components .ant-tag-green {\n color: #059669 !important;\n background: #a7f3d0 !important;\n}\n.bunny-components .ant-tag-red {\n color: #ef4444 !important;\n background: #fecaca !important;\n}\n.bunny-components .ant-tag-orange {\n color: #f97316 !important;\n background: #fed7aa !important;\n}\n.bunny-components .ant-tag-yellow {\n color: #f59e0b !important;\n background: #fde68a !important;\n}\n.bunny-components .ant-tag-purple {\n color: #8b5cf6 !important;\n background: #ddd6fe !important;\n}\n.bunny-components .ant-tag-gray {\n color: #6b7280 !important;\n background: #e5e7eb !important;\n}\n.bunny-components .ant-tag-black {\n color: white !important;\n background: black !important;\n}\n.bunny-components .ant-picker {\n width: 100%;\n}\n.bunny-components .ant-input,\n.bunny-components .ant-select,\n.bunny-components .ant-picker {\n height: 32px !important;\n}\n.bunny-components .ant-slider-dot {\n border: 2px solid #f0f0f0;\n}\n.bunny-components .ant-slider-dot-active {\n border-color: #ff5833;\n}\n.bunny-components .ant-slider-mark :last-child {\n transform: translateX(-75%) !important;\n}\n.bunny-components .ant-drawer-content {\n background: #f3f3f9ff;\n}\n.bunny-components .ant-drawer-body,\n.bunny-components .ant-layout {\n background: #f8fafc;\n}\n.bunny-components .vista-link {\n color: #1890ff;\n}\n.bunny-components .vista-link:hover {\n text-decoration: underline;\n cursor: pointer;\n}\n.bunny-components .ant-popover-inner-content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n max-width: 300px;\n}\n.bunny-components .ant-popconfirm-message-text {\n width: 100% !important;\n}\n.bunny-components .ant-popconfirm-title {\n padding: 0;\n text-align: center;\n font-size: 0.875rem !important;\n width: 100% !important;\n}\n.bunny-components .ant-popconfirm-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n}\n.bunny-components .ant-popconfirm-buttons button {\n margin-inline-start: 0 !important;\n}\n.bunny-components .ant-pagination-item {\n display: flex !important;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-btn-primary:disabled {\n background: #eef0f2 !important;\n color: rgba(0, 0, 0, 0.25) !important;\n border: none;\n}\n.bunny-components .ant-btn {\n box-shadow: none;\n text-shadow: none;\n outline: none !important;\n line-height: 1;\n font-weight: normal;\n}\n.bunny-components .ant-btn-default .ant-btn-icon {\n color: #94a3b8;\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n}\n.bunny-components .ant-btn-default:hover .ant-btn-icon {\n color: #ff7f5c;\n}\n.bunny-components .ant-btn-default:disabled {\n border-color: rgba(113, 125, 148, 0.2) !important;\n}\n.bunny-components .ant-btn-primary:disabled {\n background-color: rgba(113, 125, 148, 0.1) !important;\n border-color: rgba(113, 125, 148, 0.1) !important;\n}\n.bunny-components .ant-btn-primary:hover:disabled,\n.bunny-components .ant-btn-primary:disabled {\n background-clip: padding-box;\n}\n.bunny-components .ant-select-selection-item-content {\n display: flex !important;\n align-items: center;\n}\n.bunny-components .ant-select-item {\n font-size: 0.875rem;\n}\n.bunny-components .ant-select-item-option-content {\n display: flex;\n align-items: center;\n white-space: nowrap !important;\n overflow: visible !important;\n text-overflow: default !important;\n font-size: 0.875rem;\n}\n.bunny-components .ant-select-arrow .anticon:not(.ant-select-suffix) {\n pointer-events: none;\n}\n.bunny-components .select-dropdown-blue-gray .ant-select-item-option {\n background-color: #fff !important;\n}\n.bunny-components .select-dropdown-blue-gray .ant-select-item-option-active {\n color: #ff5833;\n}\n.bunny-components .ant-dropdown-menu-items {\n padding-left: 0 !important;\n}\n.bunny-components .ant-dropdown-menu-item-active {\n background-color: transparent !important;\n}\n.bunny-components .ant-input-affix-wrapper.searchfield {\n background: white !important;\n}\n.bunny-components .ant-input-affix-wrapper.searchfield input {\n background: white !important;\n}\n.bunny-components .ant-input-affix-wrapper-focused {\n background: white !important;\n}\n.bunny-components .panel .ant-input-affix-wrapper.searchfield {\n background: #f8f8f8 !important;\n}\n.bunny-components .panel .ant-input-affix-wrapper.searchfield input {\n background: #f8f8f8 !important;\n}\n.bunny-components .ant-input-steps-hidden .ant-input-number-handler-wrap {\n display: none;\n}\n.bunny-components .ant-layout-header {\n height: 48px;\n}\n.bunny-components .ant-layout-sider-children {\n width: inherit;\n position: fixed;\n}\n.bunny-components .ant-menu-item-group-list {\n display: flex !important;\n flex-direction: column !important;\n align-items: flex-start !important;\n gap: 4px !important;\n}\n.bunny-components .group {\n display: flex;\n flex-direction: row;\n flex-flow: row wrap;\n box-sizing: border-box;\n}\n.bunny-components .select-datepicker {\n animation-duration: 0.35s !important;\n}\n.bunny-components .header-datepicker {\n top: 96px !important;\n animation-duration: 0s !important;\n}\n.bunny-components .ant-picker-header {\n border-bottom: none !important;\n}\n.bunny-components .ant-picker-content thead tr th {\n font-weight: 500;\n}\n.bunny-components .ant-picker-panel-container {\n border-radius: 0.375rem;\n}\n.bunny-components .ant-picker-cell-selected .custom-date-display {\n color: #ffffff;\n background-color: #ff5833;\n}\n.bunny-components .ant-picker-cell-today .custom-date-display {\n border: 1px solid #ff5833;\n}\n.bunny-components .ant-select:hover,\n.bunny-components * .cardElement:hover {\n border-color: #ff5833;\n}\n.bunny-components .ant-input-number {\n width: 100%;\n}\n.bunny-components .ant-input-number-focused {\n border-color: #ff5833 !important;\n background-color: #ffffff !important;\n}\n.bunny-components .ant-input-affix-wrapper-focused,\n.bunny-components .ant-input-number-focused,\n.bunny-components .ant-picker,\n.bunny-components .ant-input,\n.bunny-components .ant-select-focused .ant-select-selector,\n.bunny-components .ant-select-selector:focus,\n.bunny-components .ant-select-selector:active,\n.bunny-components .ant-select-open .ant-select-selector {\n box-shadow: none !important;\n}\n.bunny-components .ant-select-item-option-selected .ant-select-item-option-state {\n display: none !important;\n}\n.bunny-components .ant-form * input[type='text'].ant-input:not(:disabled),\n.bunny-components .ant-select-selection-item:not(:disabled) {\n color: #232323;\n}\n.bunny-components .ant-tabs-ink-bar {\n display: none !important;\n}\n.bunny-components .ant-tabs-tab.ant-tabs-tab-active {\n border-bottom: 2px solid #ff5833 !important;\n}\n.bunny-components .ant-tabs-tab {\n border-bottom: 2px solid transparent !important;\n padding-bottom: 14px !important;\n}\n.bunny-components .ant-upload-wrapper {\n display: flex;\n}\n.bunny-components .ant-form-item-label > label::after {\n display: none !important;\n}\n.bunny-components .ant-menu-item {\n display: flex !important;\n align-items: center !important;\n}\n.ant-notification {\n width: min-content;\n}\n.ant-notification-topRight {\n right: 0 !important;\n left: 0 !important;\n margin-left: auto !important;\n margin-right: auto !important;\n}\n.ant-notification-notice-wrapper {\n width: 350px !important;\n overflow: hidden !important;\n}\n.ant-notification-notice {\n padding: 16px !important;\n width: 350px !important;\n border-radius: 8px !important;\n display: flex !important;\n box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.08), 0px 1px 18px rgba(0, 0, 0, 0.08), 0px 3px 5px rgba(0, 0, 0, 0.16) !important;\n}\n.ant-notification-notice-description {\n padding: 0 14px 0 0 !important;\n font-size: 14px !important;\n overflow-wrap: break-word;\n}\n.ant-notification-notice-success {\n background-color: #edfffa !important;\n}\n.ant-notification-notice-error {\n background-color: #fff8f4 !important;\n}\n.ant-notification-notice-error .ant-notification-notice-message {\n color: #ff5833 !important;\n font-weight: 500 !important;\n}\n.ant-notification-notice-error .ant-notification-notice-icon {\n color: #ff5833;\n}\n.ant-notification-notice-success .ant-notification-notice-message {\n color: #00b76a !important;\n font-weight: 500 !important;\n}\n.ant-notification-notice-success .ant-notification-notice-icon {\n color: #00b76a !important;\n}\n.ant-notification-notice-message {\n margin-bottom: 0 !important;\n}\n.ant-notification-notice-close {\n top: 16px !important;\n right: 16px !important;\n}\n.bunny-invoice-container {\n padding: 0;\n box-sizing: border-box !important;\n line-height: 1.15;\n}\n@media only screen and (max-width: 768px) {\n select,\n textarea,\n input[type='text'],\n input[type='password'],\n input[type='datetime'],\n input[type='datetime-local'],\n input[type='date'],\n input[type='month'],\n input[type='time'],\n input[type='week'],\n input[type='number'],\n input[type='email'],\n input[type='url'],\n input[type='search'],\n input[type='tel'],\n input[type='color'] {\n font-size: 16px !important;\n }\n}\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n";
|
|
51
|
+
var css_248z = ":root {\n --row-background: #ffffff;\n --row-background-alternate: rgba(100, 116, 139, 0.04);\n --row-background-dark: #121212;\n --row-background-alternate-dark: #1e1e1e;\n --bunny-blue-500: #3b82f6;\n --bunny-blue-200: #bfdbfe;\n --bunny-green-600: #059669;\n --bunny-green-200: #a7f3d0;\n --bunny-red-500: #ef4444;\n --bunny-red-200: #fecaca;\n --bunny-orange-500: #f97316;\n --bunny-orange-200: #fed7aa;\n --bunny-yellow-500: #f59e0b;\n --bunny-yellow-200: #fde68a;\n --bunny-purple-500: #8b5cf6;\n --bunny-purple-200: #ddd6fe;\n --bunny-black: #000000;\n}\n.bunny-component-wrapper {\n box-sizing: border-box;\n}\n.bunny-component-wrapper * {\n box-sizing: border-box;\n}\n.hidden {\n display: none;\n}\n.bunny-show-on-hover {\n opacity: 0;\n}\n.bunny-show-on-hover-container:hover .bunny-show-on-hover {\n opacity: 1;\n}\n.has-tooltip:hover .tooltip {\n visibility: visible;\n z-index: 100;\n}\n.pdf-only {\n display: none !important;\n}\n.notes p {\n margin: 0;\n padding: 0;\n padding-bottom: 0.25rem;\n}\n.bunny-icon-path {\n transition: fill 0.3s;\n}\n.bunny-shadow-padding-x {\n padding-right: 1rem;\n padding-left: 1rem;\n}\n.bunny-shadow-padding-xb {\n padding-right: 1rem;\n padding-left: 1rem;\n padding-bottom: 0.5rem;\n}\n.content-container {\n width: 100%;\n margin: 0 auto;\n}\n@media (min-width: 1220px) {\n .content-container {\n width: 1220px !important;\n margin: 0 auto;\n }\n}\n@media (min-width: 768px) {\n .bunny-shadow-padding-x {\n padding-right: 2rem;\n padding-left: 2rem;\n }\n .bunny-shadow-padding-xb {\n padding-right: 2rem;\n padding-left: 2rem;\n padding-bottom: 0.5rem;\n }\n .sm\\:flex {\n display: flex !important;\n }\n .sm\\:hidden {\n display: none !important;\n }\n}\n.bunny-shadow,\n.bunny-shadow-md {\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n}\n.bunny-fixed {\n position: fixed;\n}\n.bunny-absolute {\n position: absolute;\n}\n.bunny-relative {\n position: relative;\n}\n.bunny-sticky {\n position: sticky;\n}\n.bunny-bottom-0 {\n bottom: 0px;\n}\n.bunny-bottom-4 {\n bottom: 1rem;\n}\n.bunny-left-0 {\n left: 0px;\n}\n.bunny-right-0 {\n right: 0px;\n}\n.bunny-top-0 {\n top: 0px;\n}\n.bunny-col-span-1 {\n grid-column: span 1 / span 1;\n}\n.bunny-col-span-full {\n grid-column: 1 / -1;\n}\n.bunny-m-0 {\n margin: 0px;\n}\n.bunny-mx-0 {\n margin-left: 0px;\n margin-right: 0px;\n}\n.bunny-mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.bunny-mx-auto {\n margin-left: auto;\n margin-right: auto;\n}\n.bunny-my-0 {\n margin-top: 0px;\n margin-bottom: 0px;\n}\n.bunny-my-2 {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.bunny-my-24 {\n margin-top: 6rem;\n margin-bottom: 6rem;\n}\n.bunny-my-4 {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.bunny-mb-2 {\n margin-bottom: 0.5rem;\n}\n.bunny-mb-3 {\n margin-bottom: 0.75rem;\n}\n.bunny-mb-4 {\n margin-bottom: 1rem;\n}\n.bunny-mb-8 {\n margin-bottom: 2rem;\n}\n.bunny-ml-auto {\n margin-left: auto;\n}\n.bunny-mt-0 {\n margin-top: 0px;\n}\n.bunny-mt-2 {\n margin-top: 0.5rem;\n}\n.bunny-mt-24 {\n margin-top: 6rem;\n}\n.bunny-mt-4 {\n margin-top: 1rem;\n}\n.bunny-mt-5 {\n margin-top: 1.25rem;\n}\n.bunny-box-border {\n box-sizing: border-box;\n}\n.bunny-flex {\n display: flex;\n}\n.bunny-grid {\n display: grid;\n}\n.bunny-contents {\n display: contents;\n}\n.bunny-h-0\\.5 {\n height: 0.125rem;\n}\n.bunny-h-1\\/2 {\n height: 50%;\n}\n.bunny-h-8 {\n height: 2rem;\n}\n.bunny-h-full {\n height: 100%;\n}\n.bunny-h-screen {\n height: 100vh;\n}\n.bunny-max-h-\\[calc\\(100vh-10rem\\)\\] {\n max-height: calc(100vh - 10rem);\n}\n.bunny-min-h-0 {\n min-height: 0px;\n}\n.bunny-w-0\\.5 {\n width: 0.125rem;\n}\n.bunny-w-1\\/2 {\n width: 50%;\n}\n.bunny-w-3\\/5 {\n width: 60%;\n}\n.bunny-w-full {\n width: 100%;\n}\n.bunny-w-screen {\n width: 100vw;\n}\n.bunny-flex-1 {\n flex: 1 1 0%;\n}\n.bunny-shrink {\n flex-shrink: 1;\n}\n.bunny-shrink-0 {\n flex-shrink: 0;\n}\n.bunny-grow {\n flex-grow: 1;\n}\n.bunny-cursor-pointer {\n cursor: pointer;\n}\n.bunny-grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.bunny-flex-row {\n flex-direction: row;\n}\n.bunny-flex-col {\n flex-direction: column;\n}\n.bunny-flex-wrap {\n flex-wrap: wrap;\n}\n.bunny-items-start {\n align-items: flex-start;\n}\n.bunny-items-end {\n align-items: flex-end;\n}\n.bunny-items-center {\n align-items: center;\n}\n.bunny-justify-end {\n justify-content: flex-end;\n}\n.bunny-justify-center {\n justify-content: center;\n}\n.bunny-justify-between {\n justify-content: space-between;\n}\n.bunny-gap-0 {\n gap: 0px;\n}\n.bunny-gap-1 {\n gap: 0.25rem;\n}\n.bunny-gap-2 {\n gap: 0.5rem;\n}\n.bunny-gap-3 {\n gap: 0.75rem;\n}\n.bunny-gap-4 {\n gap: 1rem;\n}\n.bunny-gap-6 {\n gap: 1.5rem;\n}\n.bunny-gap-8 {\n gap: 2rem;\n}\n.bunny-space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.bunny-space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.bunny-space-y-8 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(2rem * var(--tw-space-y-reverse));\n}\n.bunny-overflow-auto {\n overflow: auto;\n}\n.bunny-overflow-hidden {\n overflow: hidden;\n}\n.bunny-overflow-y-auto {\n overflow-y: auto;\n}\n.bunny-whitespace-nowrap {\n white-space: nowrap;\n}\n.bunny-text-nowrap {\n text-wrap: nowrap;\n}\n.bunny-rounded {\n border-radius: 0.25rem;\n}\n.bunny-rounded-full {\n border-radius: 9999px;\n}\n.bunny-rounded-lg {\n border-radius: 0.5rem;\n}\n.bunny-rounded-md {\n border-radius: 0.375rem;\n}\n.bunny-border {\n border-width: 1px;\n}\n.bunny-border-2 {\n border-width: 2px;\n}\n.bunny-border-t {\n border-top-width: 1px;\n}\n.bunny-border-solid {\n border-style: solid;\n}\n.bunny-border-none {\n border-style: none;\n}\n.bunny-border-gray-200 {\n --tw-border-opacity: 1;\n border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));\n}\n.bunny-border-slate-200 {\n --tw-border-opacity: 1;\n border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));\n}\n.bunny-bg-gray-300 {\n --tw-bg-opacity: 1;\n background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));\n}\n.bunny-bg-slate-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));\n}\n.bunny-bg-transparent {\n background-color: transparent;\n}\n.bunny-bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.bunny-p-0 {\n padding: 0px;\n}\n.bunny-p-1 {\n padding: 0.25rem;\n}\n.bunny-p-2 {\n padding: 0.5rem;\n}\n.bunny-p-4 {\n padding: 1rem;\n}\n.bunny-px-12 {\n padding-left: 3rem;\n padding-right: 3rem;\n}\n.bunny-px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.bunny-px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.bunny-px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n}\n.bunny-py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.bunny-py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.bunny-py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.bunny-pb-2 {\n padding-bottom: 0.5rem;\n}\n.bunny-pb-4 {\n padding-bottom: 1rem;\n}\n.bunny-pb-6 {\n padding-bottom: 1.5rem;\n}\n.bunny-pb-8 {\n padding-bottom: 2rem;\n}\n.bunny-pl-0 {\n padding-left: 0px;\n}\n.bunny-pl-1 {\n padding-left: 0.25rem;\n}\n.bunny-pl-4 {\n padding-left: 1rem;\n}\n.bunny-pr-4 {\n padding-right: 1rem;\n}\n.bunny-pt-1 {\n padding-top: 0.25rem;\n}\n.bunny-pt-12 {\n padding-top: 3rem;\n}\n.bunny-pt-2 {\n padding-top: 0.5rem;\n}\n.bunny-pt-4 {\n padding-top: 1rem;\n}\n.bunny-pt-5 {\n padding-top: 1.25rem;\n}\n.bunny-pt-\\[25vh\\] {\n padding-top: 25vh;\n}\n.bunny-text-left {\n text-align: left;\n}\n.bunny-text-center {\n text-align: center;\n}\n.bunny-text-right {\n text-align: right;\n}\n.bunny-text-start {\n text-align: start;\n}\n.bunny-text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.bunny-text-3xl {\n font-size: 1.875rem;\n line-height: 2.25rem;\n}\n.bunny-text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.bunny-text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.bunny-text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.bunny-text-sm\\/5 {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.bunny-text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.bunny-text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.bunny-text-xs\\/3 {\n font-size: 0.75rem;\n line-height: 0.75rem;\n}\n.bunny-font-bold {\n font-weight: 700;\n}\n.bunny-font-medium {\n font-weight: 500;\n}\n.bunny-font-normal {\n font-weight: 400;\n}\n.bunny-text-gray-400 {\n --tw-text-opacity: 1;\n color: rgb(156 163 175 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-500 {\n --tw-text-opacity: 1;\n color: rgb(107 114 128 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.bunny-text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.bunny-text-orange-500 {\n --tw-text-opacity: 1;\n color: rgb(249 115 22 / var(--tw-text-opacity, 1));\n}\n.bunny-text-orange-600 {\n --tw-text-opacity: 1;\n color: rgb(234 88 12 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-400 {\n --tw-text-opacity: 1;\n color: rgb(148 163 184 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-500 {\n --tw-text-opacity: 1;\n color: rgb(100 116 139 / var(--tw-text-opacity, 1));\n}\n.bunny-text-slate-600 {\n --tw-text-opacity: 1;\n color: rgb(71 85 105 / var(--tw-text-opacity, 1));\n}\n.bunny-text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.bunny-underline {\n text-decoration-line: underline;\n}\n.bunny-shadow {\n --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.bunny-shadow-md {\n --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.bunny-transition-\\[margin\\] {\n transition-property: margin;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.bunny-duration-300 {\n transition-duration: 300ms;\n}\n.rotate-45,\n.transform {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-rotate: 0;\n --tw-skew-x: 0;\n --tw-skew-y: 0;\n --tw-scale-x: 1;\n --tw-scale-y: 1;\n}\n.shadow,\n.shadow-lg,\n.shadow-md,\n.shadow-none,\n.shadow-sm,\n.shadow-xl {\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n}\n.container {\n width: 100%;\n}\n@media (min-width: 768px) {\n .container {\n max-width: 768px;\n }\n}\n@media (min-width: 1024px) {\n .container {\n max-width: 1024px;\n }\n}\n@media (min-width: 1280px) {\n .container {\n max-width: 1280px;\n }\n}\n@media (min-width: 1536px) {\n .container {\n max-width: 1536px;\n }\n}\n.visible {\n visibility: visible;\n}\n.fixed {\n position: fixed;\n}\n.absolute {\n position: absolute;\n}\n.relative {\n position: relative;\n}\n.sticky {\n position: sticky;\n}\n.-top-0\\.5 {\n top: -0.125rem;\n}\n.bottom-0 {\n bottom: 0px;\n}\n.bottom-4 {\n bottom: 1rem;\n}\n.left-0 {\n left: 0px;\n}\n.right-0 {\n right: 0px;\n}\n.top-0 {\n top: 0px;\n}\n.z-50 {\n z-index: 50;\n}\n.col-span-2 {\n grid-column: span 2 / span 2;\n}\n.col-span-3 {\n grid-column: span 3 / span 3;\n}\n.col-span-full {\n grid-column: 1 / -1;\n}\n.m-0 {\n margin: 0px;\n}\n.mx-0 {\n margin-left: 0px;\n margin-right: 0px;\n}\n.mx-4 {\n margin-left: 1rem;\n margin-right: 1rem;\n}\n.my-12 {\n margin-top: 3rem;\n margin-bottom: 3rem;\n}\n.my-2 {\n margin-top: 0.5rem;\n margin-bottom: 0.5rem;\n}\n.my-4 {\n margin-top: 1rem;\n margin-bottom: 1rem;\n}\n.mb-2 {\n margin-bottom: 0.5rem;\n}\n.mb-4 {\n margin-bottom: 1rem;\n}\n.mb-8 {\n margin-bottom: 2rem;\n}\n.ml-2 {\n margin-left: 0.5rem;\n}\n.mr-8 {\n margin-right: 2rem;\n}\n.mt-1 {\n margin-top: 0.25rem;\n}\n.mt-2 {\n margin-top: 0.5rem;\n}\n.mt-4 {\n margin-top: 1rem;\n}\n.mt-6 {\n margin-top: 1.5rem;\n}\n.mt-8 {\n margin-top: 2rem;\n}\n.block {\n display: block;\n}\n.flex {\n display: flex;\n}\n.table {\n display: table;\n}\n.grid {\n display: grid;\n}\n.contents {\n display: contents;\n}\n.hidden {\n display: none;\n}\n.h-4 {\n height: 1rem;\n}\n.h-5 {\n height: 1.25rem;\n}\n.h-8 {\n height: 2rem;\n}\n.h-full {\n height: 100%;\n}\n.w-1\\/2 {\n width: 50%;\n}\n.w-1\\/3 {\n width: 33.333333%;\n}\n.w-12 {\n width: 3rem;\n}\n.w-2\\/3 {\n width: 66.666667%;\n}\n.w-4 {\n width: 1rem;\n}\n.w-full {\n width: 100%;\n}\n.max-w-32 {\n max-width: 8rem;\n}\n.flex-1 {\n flex: 1 1 0%;\n}\n.shrink {\n flex-shrink: 1;\n}\n.shrink-0 {\n flex-shrink: 0;\n}\n.flex-grow {\n flex-grow: 1;\n}\n.grow {\n flex-grow: 1;\n}\n.border-collapse {\n border-collapse: collapse;\n}\n.rotate-45 {\n --tw-rotate: 45deg;\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.transform {\n transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));\n}\n.cursor-pointer {\n cursor: pointer;\n}\n.grid-cols-2 {\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n.grid-cols-3 {\n grid-template-columns: repeat(3, minmax(0, 1fr));\n}\n.flex-row {\n flex-direction: row;\n}\n.flex-col {\n flex-direction: column;\n}\n.items-end {\n align-items: flex-end;\n}\n.items-center {\n align-items: center;\n}\n.justify-start {\n justify-content: flex-start;\n}\n.justify-end {\n justify-content: flex-end;\n}\n.justify-center {\n justify-content: center;\n}\n.justify-between {\n justify-content: space-between;\n}\n.gap-0 {\n gap: 0px;\n}\n.gap-1 {\n gap: 0.25rem;\n}\n.gap-2 {\n gap: 0.5rem;\n}\n.gap-3 {\n gap: 0.75rem;\n}\n.gap-4 {\n gap: 1rem;\n}\n.gap-6 {\n gap: 1.5rem;\n}\n.gap-8 {\n gap: 2rem;\n}\n.space-y-2 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));\n}\n.space-y-4 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(1rem * var(--tw-space-y-reverse));\n}\n.space-y-8 > :not([hidden]) ~ :not([hidden]) {\n --tw-space-y-reverse: 0;\n margin-top: calc(2rem * calc(1 - var(--tw-space-y-reverse)));\n margin-bottom: calc(2rem * var(--tw-space-y-reverse));\n}\n.overflow-auto {\n overflow: auto;\n}\n.overflow-hidden {\n overflow: hidden;\n}\n.overflow-visible {\n overflow: visible;\n}\n.whitespace-nowrap {\n white-space: nowrap;\n}\n.text-nowrap {\n text-wrap: nowrap;\n}\n.rounded {\n border-radius: 0.25rem;\n}\n.rounded-full {\n border-radius: 9999px;\n}\n.rounded-lg {\n border-radius: 0.5rem;\n}\n.rounded-md {\n border-radius: 0.375rem;\n}\n.rounded-sm {\n border-radius: 0.125rem;\n}\n.border {\n border-width: 1px;\n}\n.border-2 {\n border-width: 2px;\n}\n.border-b {\n border-bottom-width: 1px;\n}\n.border-t {\n border-top-width: 1px;\n}\n.border-solid {\n border-style: solid;\n}\n.border-none {\n border-style: none;\n}\n.border-gray-400 {\n --tw-border-opacity: 1;\n border-color: rgb(156 163 175 / var(--tw-border-opacity, 1));\n}\n.border-gray-500 {\n --tw-border-opacity: 1;\n border-color: rgb(107 114 128 / var(--tw-border-opacity, 1));\n}\n.border-slate-200 {\n --tw-border-opacity: 1;\n border-color: rgb(226 232 240 / var(--tw-border-opacity, 1));\n}\n.border-slate-300 {\n --tw-border-opacity: 1;\n border-color: rgb(203 213 225 / var(--tw-border-opacity, 1));\n}\n.border-slate-700 {\n --tw-border-opacity: 1;\n border-color: rgb(51 65 85 / var(--tw-border-opacity, 1));\n}\n.bg-black {\n --tw-bg-opacity: 1;\n background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));\n}\n.bg-emerald-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(167 243 208 / var(--tw-bg-opacity, 1));\n}\n.bg-green-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(187 247 208 / var(--tw-bg-opacity, 1));\n}\n.bg-orange-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 215 170 / var(--tw-bg-opacity, 1));\n}\n.bg-red-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 202 202 / var(--tw-bg-opacity, 1));\n}\n.bg-red-500 {\n --tw-bg-opacity: 1;\n background-color: rgb(239 68 68 / var(--tw-bg-opacity, 1));\n}\n.bg-slate-50 {\n --tw-bg-opacity: 1;\n background-color: rgb(248 250 252 / var(--tw-bg-opacity, 1));\n}\n.bg-transparent {\n background-color: transparent;\n}\n.bg-white {\n --tw-bg-opacity: 1;\n background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));\n}\n.bg-yellow-200 {\n --tw-bg-opacity: 1;\n background-color: rgb(254 240 138 / var(--tw-bg-opacity, 1));\n}\n.p-0 {\n padding: 0px;\n}\n.p-1 {\n padding: 0.25rem;\n}\n.p-2 {\n padding: 0.5rem;\n}\n.p-4 {\n padding: 1rem;\n}\n.p-8 {\n padding: 2rem;\n}\n.px-2 {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n}\n.px-3 {\n padding-left: 0.75rem;\n padding-right: 0.75rem;\n}\n.px-4 {\n padding-left: 1rem;\n padding-right: 1rem;\n}\n.px-6 {\n padding-left: 1.5rem;\n padding-right: 1.5rem;\n}\n.px-8 {\n padding-left: 2rem;\n padding-right: 2rem;\n}\n.py-1 {\n padding-top: 0.25rem;\n padding-bottom: 0.25rem;\n}\n.py-2 {\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n.py-4 {\n padding-top: 1rem;\n padding-bottom: 1rem;\n}\n.py-6 {\n padding-top: 1.5rem;\n padding-bottom: 1.5rem;\n}\n.pb-2 {\n padding-bottom: 0.5rem;\n}\n.pb-4 {\n padding-bottom: 1rem;\n}\n.pb-6 {\n padding-bottom: 1.5rem;\n}\n.pb-8 {\n padding-bottom: 2rem;\n}\n.pl-0 {\n padding-left: 0px;\n}\n.pl-2 {\n padding-left: 0.5rem;\n}\n.pl-4 {\n padding-left: 1rem;\n}\n.pt-1 {\n padding-top: 0.25rem;\n}\n.pt-12 {\n padding-top: 3rem;\n}\n.pt-2 {\n padding-top: 0.5rem;\n}\n.pt-4 {\n padding-top: 1rem;\n}\n.pt-5 {\n padding-top: 1.25rem;\n}\n.pt-6 {\n padding-top: 1.5rem;\n}\n.pt-8 {\n padding-top: 2rem;\n}\n.text-left {\n text-align: left;\n}\n.text-center {\n text-align: center;\n}\n.text-right {\n text-align: right;\n}\n.align-middle {\n vertical-align: middle;\n}\n.text-2xl {\n font-size: 1.5rem;\n line-height: 2rem;\n}\n.text-base {\n font-size: 1rem;\n line-height: 1.5rem;\n}\n.text-lg {\n font-size: 1.125rem;\n line-height: 1.75rem;\n}\n.text-sm {\n font-size: 0.875rem;\n line-height: 1.25rem;\n}\n.text-xl {\n font-size: 1.25rem;\n line-height: 1.75rem;\n}\n.text-xs {\n font-size: 0.75rem;\n line-height: 1rem;\n}\n.font-bold {\n font-weight: 700;\n}\n.font-medium {\n font-weight: 500;\n}\n.font-normal {\n font-weight: 400;\n}\n.capitalize {\n text-transform: capitalize;\n}\n.text-emerald-600 {\n --tw-text-opacity: 1;\n color: rgb(5 150 105 / var(--tw-text-opacity, 1));\n}\n.text-emerald-700 {\n --tw-text-opacity: 1;\n color: rgb(4 120 87 / var(--tw-text-opacity, 1));\n}\n.text-gray-600 {\n --tw-text-opacity: 1;\n color: rgb(75 85 99 / var(--tw-text-opacity, 1));\n}\n.text-gray-900 {\n --tw-text-opacity: 1;\n color: rgb(17 24 39 / var(--tw-text-opacity, 1));\n}\n.text-green-600 {\n --tw-text-opacity: 1;\n color: rgb(22 163 74 / var(--tw-text-opacity, 1));\n}\n.text-orange-500 {\n --tw-text-opacity: 1;\n color: rgb(249 115 22 / var(--tw-text-opacity, 1));\n}\n.text-orange-600 {\n --tw-text-opacity: 1;\n color: rgb(234 88 12 / var(--tw-text-opacity, 1));\n}\n.text-red-500 {\n --tw-text-opacity: 1;\n color: rgb(239 68 68 / var(--tw-text-opacity, 1));\n}\n.text-slate-400 {\n --tw-text-opacity: 1;\n color: rgb(148 163 184 / var(--tw-text-opacity, 1));\n}\n.text-slate-500 {\n --tw-text-opacity: 1;\n color: rgb(100 116 139 / var(--tw-text-opacity, 1));\n}\n.text-slate-600 {\n --tw-text-opacity: 1;\n color: rgb(71 85 105 / var(--tw-text-opacity, 1));\n}\n.text-white {\n --tw-text-opacity: 1;\n color: rgb(255 255 255 / var(--tw-text-opacity, 1));\n}\n.text-yellow-500 {\n --tw-text-opacity: 1;\n color: rgb(234 179 8 / var(--tw-text-opacity, 1));\n}\n.underline {\n text-decoration-line: underline;\n}\n.shadow {\n --tw-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-lg {\n --tw-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-md {\n --tw-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-none {\n --tw-shadow: 0 0 #0000;\n --tw-shadow-colored: 0 0 #0000;\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-sm {\n --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.shadow-xl {\n --tw-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);\n --tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);\n box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);\n}\n.transition {\n transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-\\[margin\\] {\n transition-property: margin;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.transition-all {\n transition-property: all;\n transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n transition-duration: 150ms;\n}\n.duration-200 {\n transition-duration: 200ms;\n}\n.duration-300 {\n transition-duration: 300ms;\n}\n.hover\\:bg-gray-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-slate-100:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(241 245 249 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-slate-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(226 232 240 / var(--tw-bg-opacity, 1));\n}\n.hover\\:bg-gray-200:hover {\n --tw-bg-opacity: 1;\n background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));\n}\n@media (min-width: 768px) {\n .sm\\:flex {\n display: flex;\n }\n .sm\\:hidden {\n display: none;\n }\n}\n.hover\\:bunny-text-orange-400:hover {\n --tw-text-opacity: 1;\n color: rgb(251 146 60 / var(--tw-text-opacity, 1));\n}\n.bunny-components .ant-upload-select-picture-card {\n margin: 0 !important;\n}\n.bunny-components .ant-upload {\n border-radius: 0.5rem !important;\n}\n.bunny-components .ant-row {\n margin-bottom: 0px;\n}\n.bunny-components .ant-select-disabled .ant-select-selector .ant-select-selection-item {\n color: rgba(0, 0, 0, 0.25) !important;\n}\n.bunny-components .ant-input-number,\n.bunny-components .ant-input,\n.bunny-components .ant-picker,\n.bunny-components .ant-input-affix-wrapper,\n.bunny-components .ant-select-selector {\n font-size: 0.875rem !important;\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n color: #232323 !important;\n}\n.bunny-components .ant-input-affix-wrapper {\n padding-top: 0 !important;\n padding-bottom: 0 !important;\n}\n.bunny-components .ant-input-group-addon,\n.bunny-components .ant-input-number-group-addon {\n color: #475569 !important;\n}\n.bunny-components .ant-input-number-group-wrapper,\n.bunny-components .ant-input-number-affix-wrapper {\n width: 100%;\n}\n.bunny-components .ant-input-affix-wrapper input {\n border: none !important;\n}\n.bunny-components .ant-form-item {\n margin-bottom: 0;\n}\n.bunny-components .ant-form-item-label {\n text-transform: none !important;\n font-size: 0.75rem;\n padding-bottom: 2px !important;\n}\n.bunny-components .ant-form-item-label > label {\n width: 100%;\n color: #4b5563 !important;\n}\n.bunny-components .form .ant-form-item-label label {\n text-overflow: ellipsis;\n white-space: nowrap;\n overflow: hidden;\n box-sizing: border-box;\n}\n.bunny-components .ant-form-item-explain,\n.bunny-components .ant-form-item-explain-error {\n font-size: 11px;\n min-height: 11px;\n line-height: 11px;\n padding-top: 2px;\n}\n.bunny-components .ant-timeline-item-content {\n font-size: smaller;\n}\n.bunny-components .ant-tree {\n font-size: 0.875rem;\n}\n.bunny-components .ant-tree-treenode {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-draggable-icon {\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-node-content-wrapper {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-tree-switcher {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-page-header {\n padding-left: 0;\n padding-right: 0;\n padding-top: 0;\n}\n.bunny-components .ant-tag {\n display: flex;\n align-items: center;\n justify-content: center;\n border: none;\n border-radius: 14px;\n font-weight: 500;\n white-space: nowrap;\n padding-inline-start: 0.625rem;\n padding-inline-end: 0.625rem;\n margin: 0;\n}\n.bunny-components .ant-tag-blue {\n color: #3b82f6 !important;\n background: #bfdbfe !important;\n}\n.bunny-components .ant-tag-green {\n color: #059669 !important;\n background: #a7f3d0 !important;\n}\n.bunny-components .ant-tag-red {\n color: #ef4444 !important;\n background: #fecaca !important;\n}\n.bunny-components .ant-tag-orange {\n color: #f97316 !important;\n background: #fed7aa !important;\n}\n.bunny-components .ant-tag-yellow {\n color: #f59e0b !important;\n background: #fde68a !important;\n}\n.bunny-components .ant-tag-purple {\n color: #8b5cf6 !important;\n background: #ddd6fe !important;\n}\n.bunny-components .ant-tag-gray {\n color: #6b7280 !important;\n background: #e5e7eb !important;\n}\n.bunny-components .ant-tag-black {\n color: white !important;\n background: black !important;\n}\n.bunny-components .ant-picker {\n width: 100%;\n}\n.bunny-components .ant-input,\n.bunny-components .ant-select,\n.bunny-components .ant-picker {\n height: 32px !important;\n}\n.bunny-components .ant-slider-dot {\n border: 2px solid #f0f0f0;\n}\n.bunny-components .ant-slider-dot-active {\n border-color: #ff5833;\n}\n.bunny-components .ant-slider-mark :last-child {\n transform: translateX(-75%) !important;\n}\n.bunny-components .ant-drawer-content {\n background: #f3f3f9ff;\n}\n.bunny-components .ant-drawer-body,\n.bunny-components .ant-layout {\n background: #f8fafc;\n}\n.bunny-components .vista-link {\n color: #1890ff;\n}\n.bunny-components .vista-link:hover {\n text-decoration: underline;\n cursor: pointer;\n}\n.bunny-components .ant-popover-inner-content {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n max-width: 300px;\n}\n.bunny-components .ant-popconfirm-message-text {\n width: 100% !important;\n}\n.bunny-components .ant-popconfirm-title {\n padding: 0;\n text-align: center;\n font-size: 0.875rem !important;\n width: 100% !important;\n}\n.bunny-components .ant-popconfirm-buttons {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n}\n.bunny-components .ant-popconfirm-buttons button {\n margin-inline-start: 0 !important;\n}\n.bunny-components .ant-pagination-item {\n display: flex !important;\n align-items: center;\n justify-content: center;\n}\n.bunny-components .ant-btn-primary:disabled {\n background: #eef0f2 !important;\n color: rgba(0, 0, 0, 0.25) !important;\n border: none;\n}\n.bunny-components .ant-btn {\n box-shadow: none;\n text-shadow: none;\n outline: none !important;\n line-height: 1;\n font-weight: normal;\n}\n.bunny-components .ant-btn-default .ant-btn-icon {\n color: #94a3b8;\n transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);\n}\n.bunny-components .ant-btn-default:hover .ant-btn-icon {\n color: #ff7f5c;\n}\n.bunny-components .ant-btn-default:disabled {\n border-color: rgba(113, 125, 148, 0.2) !important;\n}\n.bunny-components .ant-btn-primary:disabled {\n background-color: rgba(113, 125, 148, 0.1) !important;\n border-color: rgba(113, 125, 148, 0.1) !important;\n}\n.bunny-components .ant-btn-primary:hover:disabled,\n.bunny-components .ant-btn-primary:disabled {\n background-clip: padding-box;\n}\n.bunny-components .ant-select-selection-item-content {\n display: flex !important;\n align-items: center;\n}\n.bunny-components .ant-select-item {\n font-size: 0.875rem;\n}\n.bunny-components .ant-select-item-option-content {\n display: flex;\n align-items: center;\n white-space: nowrap !important;\n overflow: visible !important;\n text-overflow: default !important;\n font-size: 0.875rem;\n}\n.bunny-components .ant-select-arrow .anticon:not(.ant-select-suffix) {\n pointer-events: none;\n}\n.bunny-components .select-dropdown-blue-gray .ant-select-item-option {\n background-color: #fff !important;\n}\n.bunny-components .select-dropdown-blue-gray .ant-select-item-option-active {\n color: #ff5833;\n}\n.bunny-components .ant-dropdown-menu-items {\n padding-left: 0 !important;\n}\n.bunny-components .ant-dropdown-menu-item-active {\n background-color: transparent !important;\n}\n.bunny-components .ant-input-affix-wrapper.searchfield {\n background: white !important;\n}\n.bunny-components .ant-input-affix-wrapper.searchfield input {\n background: white !important;\n}\n.bunny-components .ant-input-affix-wrapper-focused {\n background: white !important;\n}\n.bunny-components .panel .ant-input-affix-wrapper.searchfield {\n background: #f8f8f8 !important;\n}\n.bunny-components .panel .ant-input-affix-wrapper.searchfield input {\n background: #f8f8f8 !important;\n}\n.bunny-components .ant-input-steps-hidden .ant-input-number-handler-wrap {\n display: none;\n}\n.bunny-components .ant-layout-header {\n height: 48px;\n}\n.bunny-components .ant-layout-sider-children {\n width: inherit;\n position: fixed;\n}\n.bunny-components .ant-menu-item-group-list {\n display: flex !important;\n flex-direction: column !important;\n align-items: flex-start !important;\n gap: 4px !important;\n}\n.bunny-components .group {\n display: flex;\n flex-direction: row;\n flex-flow: row wrap;\n box-sizing: border-box;\n}\n.bunny-components .select-datepicker {\n animation-duration: 0.35s !important;\n}\n.bunny-components .header-datepicker {\n top: 96px !important;\n animation-duration: 0s !important;\n}\n.bunny-components .ant-picker-header {\n border-bottom: none !important;\n}\n.bunny-components .ant-picker-content thead tr th {\n font-weight: 500;\n}\n.bunny-components .ant-picker-panel-container {\n border-radius: 0.375rem;\n}\n.bunny-components .ant-picker-cell-selected .custom-date-display {\n color: #ffffff;\n background-color: #ff5833;\n}\n.bunny-components .ant-picker-cell-today .custom-date-display {\n border: 1px solid #ff5833;\n}\n.bunny-components .ant-select:hover,\n.bunny-components * .cardElement:hover {\n border-color: #ff5833;\n}\n.bunny-components .ant-input-number {\n width: 100%;\n}\n.bunny-components .ant-input-number-focused {\n border-color: #ff5833 !important;\n background-color: #ffffff !important;\n}\n.bunny-components .ant-input-affix-wrapper-focused,\n.bunny-components .ant-input-number-focused,\n.bunny-components .ant-picker,\n.bunny-components .ant-input,\n.bunny-components .ant-select-focused .ant-select-selector,\n.bunny-components .ant-select-selector:focus,\n.bunny-components .ant-select-selector:active,\n.bunny-components .ant-select-open .ant-select-selector {\n box-shadow: none !important;\n}\n.bunny-components .ant-select-item-option-selected .ant-select-item-option-state {\n display: none !important;\n}\n.bunny-components .ant-form * input[type='text'].ant-input:not(:disabled),\n.bunny-components .ant-select-selection-item:not(:disabled) {\n color: #232323;\n}\n.bunny-components .ant-tabs-ink-bar {\n display: none !important;\n}\n.bunny-components .ant-tabs-tab.ant-tabs-tab-active {\n border-bottom: 2px solid #ff5833 !important;\n}\n.bunny-components .ant-tabs-tab {\n border-bottom: 2px solid transparent !important;\n padding-bottom: 14px !important;\n}\n.bunny-components .ant-upload-wrapper {\n display: flex;\n}\n.bunny-components .ant-form-item-label > label::after {\n display: none !important;\n}\n.bunny-components .ant-menu-item {\n display: flex !important;\n align-items: center !important;\n}\n.ant-notification {\n width: min-content;\n}\n.ant-notification-topRight {\n right: 0 !important;\n left: 0 !important;\n margin-left: auto !important;\n margin-right: auto !important;\n}\n.ant-notification-notice-wrapper {\n width: 350px !important;\n overflow: hidden !important;\n}\n.ant-notification-notice {\n padding: 16px !important;\n width: 350px !important;\n border-radius: 8px !important;\n display: flex !important;\n box-shadow: 0px 6px 10px rgba(0, 0, 0, 0.08), 0px 1px 18px rgba(0, 0, 0, 0.08), 0px 3px 5px rgba(0, 0, 0, 0.16) !important;\n}\n.ant-notification-notice-description {\n padding: 0 14px 0 0 !important;\n font-size: 14px !important;\n overflow-wrap: break-word;\n}\n.ant-notification-notice-success {\n background-color: #edfffa !important;\n}\n.ant-notification-notice-error {\n background-color: #fff8f4 !important;\n}\n.ant-notification-notice-error .ant-notification-notice-message {\n color: #ff5833 !important;\n font-weight: 500 !important;\n}\n.ant-notification-notice-error .ant-notification-notice-icon {\n color: #ff5833;\n}\n.ant-notification-notice-success .ant-notification-notice-message {\n color: #00b76a !important;\n font-weight: 500 !important;\n}\n.ant-notification-notice-success .ant-notification-notice-icon {\n color: #00b76a !important;\n}\n.ant-notification-notice-message {\n margin-bottom: 0 !important;\n}\n.ant-notification-notice-close {\n top: 16px !important;\n right: 16px !important;\n}\n.bunny-invoice-container {\n padding: 0;\n box-sizing: border-box !important;\n line-height: 1.15;\n}\n@media only screen and (max-width: 768px) {\n select,\n textarea,\n input[type='text'],\n input[type='password'],\n input[type='datetime'],\n input[type='datetime-local'],\n input[type='date'],\n input[type='month'],\n input[type='time'],\n input[type='week'],\n input[type='number'],\n input[type='email'],\n input[type='url'],\n input[type='search'],\n input[type='tel'],\n input[type='color'] {\n font-size: 16px !important;\n }\n}\n@keyframes App-logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n";
|
|
52
52
|
styleInject(css_248z);
|
|
53
53
|
|
|
54
54
|
const IGNORE_ERRORS = ['Invalid or missing authorization', '["Not found"]'];
|
|
@@ -143,7 +143,7 @@ const useAllErrorFormats = () => {
|
|
|
143
143
|
};
|
|
144
144
|
|
|
145
145
|
// This will be replaced at build time by rollup-plugin-replace
|
|
146
|
-
const PACKAGE_VERSION = '1.
|
|
146
|
+
const PACKAGE_VERSION = '1.7.0-beta.2';
|
|
147
147
|
const createRequestHeaders = (token) => {
|
|
148
148
|
const headers = createClientDevHeaders({ token });
|
|
149
149
|
// Add the components version header
|
|
@@ -929,7 +929,7 @@ function readFragment(...r) {
|
|
|
929
929
|
|
|
930
930
|
var t = initGraphQLTada();
|
|
931
931
|
|
|
932
|
-
const query$
|
|
932
|
+
const query$9 = t(`
|
|
933
933
|
query entityBranding {
|
|
934
934
|
entityBranding {
|
|
935
935
|
accentColor
|
|
@@ -939,7 +939,7 @@ const query$7 = t(`
|
|
|
939
939
|
}
|
|
940
940
|
`);
|
|
941
941
|
const getBranding = async ({ token, apiHost }) => {
|
|
942
|
-
return await execute(query$
|
|
942
|
+
return await execute(query$9, { apiHost, token }, {});
|
|
943
943
|
};
|
|
944
944
|
|
|
945
945
|
const BunnyContext = react.createContext({});
|
|
@@ -1143,10 +1143,10 @@ const DocumentTemplatePreview = ({ targetUrl }) => {
|
|
|
1143
1143
|
}, children: jsxRuntime.jsx(react$1.RPPages, {}) }))] }) }) }));
|
|
1144
1144
|
};
|
|
1145
1145
|
|
|
1146
|
-
const { Text: Text$
|
|
1146
|
+
const { Text: Text$B } = antd.Typography;
|
|
1147
1147
|
function BackButton({ onClick, title }) {
|
|
1148
1148
|
const { brandColor } = useBrand();
|
|
1149
|
-
return (jsxRuntime.jsxs(StyledBackButton, { brandColor: brandColor, className: "bunny-flex bunny-items-center bunny-gap-2 bunny-p-0 bunny-text-gray-400", onClick: onClick, children: [jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, { className: "pt-0.5", icon: freeSolidSvgIcons.faArrowLeft }), jsxRuntime.jsx(Text$
|
|
1149
|
+
return (jsxRuntime.jsxs(StyledBackButton, { brandColor: brandColor, className: "bunny-flex bunny-items-center bunny-gap-2 bunny-p-0 bunny-text-gray-400", onClick: onClick, children: [jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, { className: "pt-0.5", icon: freeSolidSvgIcons.faArrowLeft }), jsxRuntime.jsx(Text$B, { className: "bunny-text-sm bunny-text-gray-400 bunny-text-nowrap", children: title || 'back' })] }));
|
|
1150
1150
|
}
|
|
1151
1151
|
const StyledBackButton = styled.button.withConfig({
|
|
1152
1152
|
shouldForwardProp: prop => !['brandColor'].includes(prop),
|
|
@@ -1182,7 +1182,7 @@ const InvoiceQuoteView = ({ children, formattedInvoice, html, backButtonName, on
|
|
|
1182
1182
|
}, children: [targetUrl ? (jsxRuntime.jsx(DocumentTemplatePreview, { targetUrl: targetUrl })) : (jsxRuntime.jsx(interweave.Markup, { content: html })), children] }))] }));
|
|
1183
1183
|
};
|
|
1184
1184
|
|
|
1185
|
-
const MUTATION$
|
|
1185
|
+
const MUTATION$8 = `
|
|
1186
1186
|
query FormattedInvoice($id: ID) {
|
|
1187
1187
|
formattedInvoice(id: $id) {
|
|
1188
1188
|
amount
|
|
@@ -1250,7 +1250,7 @@ query FormattedInvoice($id: ID) {
|
|
|
1250
1250
|
const getFormattedInvoice = async ({ id, token, apiHost, }) => {
|
|
1251
1251
|
const vars = { id };
|
|
1252
1252
|
const response = await gqlRequest({
|
|
1253
|
-
query: MUTATION$
|
|
1253
|
+
query: MUTATION$8,
|
|
1254
1254
|
token,
|
|
1255
1255
|
vars,
|
|
1256
1256
|
apiHost,
|
|
@@ -18616,7 +18616,7 @@ function CardImage({ paymentMethod: maskedPaymentMethod, }) {
|
|
|
18616
18616
|
}
|
|
18617
18617
|
}
|
|
18618
18618
|
|
|
18619
|
-
const { Text: Text$
|
|
18619
|
+
const { Text: Text$A } = antd.Typography;
|
|
18620
18620
|
const MiniCreditCard_PaymentMethodFragment = t(`
|
|
18621
18621
|
fragment MiniCreditCard_PaymentMethodFragment on PaymentMethod {
|
|
18622
18622
|
...CardImage_PaymentMethodFragment
|
|
@@ -18642,22 +18642,22 @@ function MiniCreditCard({ className, buttons, hideDropdownMenu = false, hideDefa
|
|
|
18642
18642
|
return darkMode ? 'var(--row-background-alternate)' : 'bg-slate-50';
|
|
18643
18643
|
}, [darkMode]);
|
|
18644
18644
|
const isDefault = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.isDefault;
|
|
18645
|
-
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-flex-row bunny-justify-between bunny-items-center bunny-p-1 bunny-px-3 bunny-border-solid ${backgroundColor} bunny-${borderColor} bunny-rounded-md bunny-border ${className}`, id: id, children: paymentMethod ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-row bunny-gap-4", children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2 bunny-space-between bunny-w-full", children: [jsxRuntime.jsx(CardImage, { paymentMethod: paymentMethod }), jsxRuntime.jsx(Issuer, { issuer: (_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.issuer }), jsxRuntime.jsx(Identifier, { type: (_b = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _b === void 0 ? void 0 : _b.type, identifier: (_c = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _c === void 0 ? void 0 : _c.identifier }), !hideDefaultTag && (jsxRuntime.jsx("div", { children: isDefault ? (jsxRuntime.jsx(antd.Tag, { bordered: false, style: { color: brandColor, backgroundColor: `${brandColor}30` }, children: "Default" })) : null }))] }) }), buttons ? (buttons) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !hideDropdownMenu && (jsxRuntime.jsx(DropdownMenu, { setDefault: onClickSetDefault, remove: onClickRemove, isDefault: isDefault !== null && isDefault !== void 0 ? isDefault : false, id: `credit-card-dropdown-${paymentMethod.id}` })) }))] })) : (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-items-center justify-between w-full", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsxRuntime.jsx(icons.CreditCardOutlined, {}), jsxRuntime.jsx(Text$
|
|
18645
|
+
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-flex-row bunny-justify-between bunny-items-center bunny-p-1 bunny-px-3 bunny-border-solid ${backgroundColor} bunny-${borderColor} bunny-rounded-md bunny-border ${className}`, id: id, children: paymentMethod ? (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-row bunny-gap-4", children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2 bunny-space-between bunny-w-full", children: [jsxRuntime.jsx(CardImage, { paymentMethod: paymentMethod }), jsxRuntime.jsx(Issuer, { issuer: (_a = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _a === void 0 ? void 0 : _a.issuer }), jsxRuntime.jsx(Identifier, { type: (_b = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _b === void 0 ? void 0 : _b.type, identifier: (_c = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.metadata) === null || _c === void 0 ? void 0 : _c.identifier }), !hideDefaultTag && (jsxRuntime.jsx("div", { children: isDefault ? (jsxRuntime.jsx(antd.Tag, { bordered: false, style: { color: brandColor, backgroundColor: `${brandColor}30` }, children: "Default" })) : null }))] }) }), buttons ? (buttons) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !hideDropdownMenu && (jsxRuntime.jsx(DropdownMenu, { setDefault: onClickSetDefault, remove: onClickRemove, isDefault: isDefault !== null && isDefault !== void 0 ? isDefault : false, id: `credit-card-dropdown-${paymentMethod.id}` })) }))] })) : (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-items-center justify-between w-full", children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsxRuntime.jsx(icons.CreditCardOutlined, {}), jsxRuntime.jsx(Text$A, { className: "bunny-text-slate-400 bunny-text-sm", children: "No payment methods" })] }), jsxRuntime.jsx(antd.Button, { disabled: true, type: "link" }), buttons] })) }));
|
|
18646
18646
|
}
|
|
18647
18647
|
const Identifier = ({ type, identifier, }) => {
|
|
18648
18648
|
if (type === 'link') {
|
|
18649
18649
|
return null;
|
|
18650
18650
|
}
|
|
18651
18651
|
if (type === 'cashapp') {
|
|
18652
|
-
return jsxRuntime.jsx(Text$
|
|
18652
|
+
return jsxRuntime.jsx(Text$A, { children: "Cashapp" });
|
|
18653
18653
|
}
|
|
18654
|
-
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(Text$
|
|
18654
|
+
return (jsxRuntime.jsxs("div", { children: [jsxRuntime.jsx(Text$A, { className: "relative -top-0.5", children: "****" }), jsxRuntime.jsx(Text$A, { children: identifier })] }));
|
|
18655
18655
|
};
|
|
18656
18656
|
const Issuer = ({ issuer }) => {
|
|
18657
18657
|
const list = ['visa', 'link', 'jcb', 'discover', 'sepa'];
|
|
18658
18658
|
if (!issuer || issuer.length == 0 || list.includes(issuer === null || issuer === void 0 ? void 0 : issuer.toLowerCase()))
|
|
18659
18659
|
return null;
|
|
18660
|
-
return jsxRuntime.jsx(Text$
|
|
18660
|
+
return jsxRuntime.jsx(Text$A, { children: lodashExports.capitalize(issuer) });
|
|
18661
18661
|
};
|
|
18662
18662
|
const DropdownMenu = ({ setDefault, remove, isDefault, id, }) => {
|
|
18663
18663
|
const { brandColor } = useBrand();
|
|
@@ -18702,6 +18702,16 @@ const QueryKeyFactory = {
|
|
|
18702
18702
|
...(entityId ? [entityId] : []),
|
|
18703
18703
|
...(token ? [token] : []),
|
|
18704
18704
|
],
|
|
18705
|
+
accountBillingDetailsKey: ({ accountId, token }) => [
|
|
18706
|
+
'accountBillingDetails',
|
|
18707
|
+
...(accountId ? [accountId] : []),
|
|
18708
|
+
...(token ? [token] : []),
|
|
18709
|
+
],
|
|
18710
|
+
accountContactsKey: ({ accountId, token }) => [
|
|
18711
|
+
'accountContacts',
|
|
18712
|
+
...(accountId ? [accountId] : []),
|
|
18713
|
+
...(token ? [token] : []),
|
|
18714
|
+
],
|
|
18705
18715
|
brandingKey: (token) => ['branding', ...(token ? [token] : [])],
|
|
18706
18716
|
calculatedPricesKey: ({ priceListId, quantity, token }) => [
|
|
18707
18717
|
'calculatedPrices',
|
|
@@ -18768,7 +18778,7 @@ const QueryKeyFactory = {
|
|
|
18768
18778
|
paymentPluginsKey: (token) => ['paymentPlugins', ...(token ? [token] : [])],
|
|
18769
18779
|
};
|
|
18770
18780
|
|
|
18771
|
-
const query$
|
|
18781
|
+
const query$8 = t(`
|
|
18772
18782
|
query PaymentMethods($accountId: ID) {
|
|
18773
18783
|
paymentMethods(accountId: $accountId) {
|
|
18774
18784
|
nodes {
|
|
@@ -18797,7 +18807,7 @@ const query$6 = t(`
|
|
|
18797
18807
|
`, [PaymentForm_PaymentMethodsFragment]);
|
|
18798
18808
|
const getPaymentMethods = async ({ apiHost, token, accountId, }) => {
|
|
18799
18809
|
var _a, _b, _c;
|
|
18800
|
-
const response = await execute(query$
|
|
18810
|
+
const response = await execute(query$8, { apiHost, token }, { accountId });
|
|
18801
18811
|
// Filter out null values that are technically possible due to api schema
|
|
18802
18812
|
return (_c = (_b = (_a = response === null || response === void 0 ? void 0 : response.paymentMethods) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b.filter(paymentMethod => paymentMethod !== null)) !== null && _c !== void 0 ? _c : [];
|
|
18803
18813
|
};
|
|
@@ -18822,7 +18832,7 @@ const usePaymentMethod = ({ accountId, enabled = true, }) => {
|
|
|
18822
18832
|
};
|
|
18823
18833
|
};
|
|
18824
18834
|
|
|
18825
|
-
const mutation$
|
|
18835
|
+
const mutation$d = t(`
|
|
18826
18836
|
query PaymentPlugins($accountId: ID) {
|
|
18827
18837
|
paymentPlugins(accountId: $accountId) {
|
|
18828
18838
|
enabled
|
|
@@ -18850,7 +18860,7 @@ const mutation$5 = t(`
|
|
|
18850
18860
|
// }[];
|
|
18851
18861
|
// };
|
|
18852
18862
|
const getPaymentPlugins = async ({ apiHost, token, accountId, }) => {
|
|
18853
|
-
const response = await execute(mutation$
|
|
18863
|
+
const response = await execute(mutation$d, { apiHost, token }, { accountId });
|
|
18854
18864
|
return response === null || response === void 0 ? void 0 : response.paymentPlugins;
|
|
18855
18865
|
};
|
|
18856
18866
|
const usePaymentPlugins = (accountId) => {
|
|
@@ -19074,7 +19084,7 @@ function useSave$1({ onSaveSuccess, onSaveError, accountId, }) {
|
|
|
19074
19084
|
return { save, isSaving };
|
|
19075
19085
|
}
|
|
19076
19086
|
|
|
19077
|
-
const MUTATION$
|
|
19087
|
+
const MUTATION$7 = `
|
|
19078
19088
|
mutation checkout(
|
|
19079
19089
|
$invoiceId: ID,
|
|
19080
19090
|
$quoteId: ID,
|
|
@@ -19123,7 +19133,7 @@ const checkout = async ({ quoteId, invoiceId, paymentMethodId, paymentMethodData
|
|
|
19123
19133
|
};
|
|
19124
19134
|
}
|
|
19125
19135
|
const response = await gqlRequest({
|
|
19126
|
-
query: MUTATION$
|
|
19136
|
+
query: MUTATION$7,
|
|
19127
19137
|
token,
|
|
19128
19138
|
vars: mutationVars,
|
|
19129
19139
|
apiHost: apiHost,
|
|
@@ -19404,7 +19414,7 @@ var PaymentType;
|
|
|
19404
19414
|
PaymentType["CHECKOUT_NO_PAYMENT"] = "CHECKOUT_NO_PAYMENT";
|
|
19405
19415
|
})(PaymentType || (PaymentType = {}));
|
|
19406
19416
|
|
|
19407
|
-
const handleAllErrorFormats$
|
|
19417
|
+
const handleAllErrorFormats$3 = common.useAllErrorFormats();
|
|
19408
19418
|
const showErrorNotification$6 = common.useErrorNotification();
|
|
19409
19419
|
const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSuccess, plugin, paymentHoldOptions, accountId, }) => {
|
|
19410
19420
|
// Context
|
|
@@ -19426,7 +19436,7 @@ const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSucce
|
|
|
19426
19436
|
const { pay: payDemoPay, isPaying: isPayingDemoPay } = usePay$1({
|
|
19427
19437
|
onPaymentSuccess: handlePaymentSuccess,
|
|
19428
19438
|
onPaymentError: error => {
|
|
19429
|
-
handleAllErrorFormats$
|
|
19439
|
+
handleAllErrorFormats$3(error);
|
|
19430
19440
|
},
|
|
19431
19441
|
quote: quote,
|
|
19432
19442
|
invoice: invoice,
|
|
@@ -19435,7 +19445,7 @@ const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSucce
|
|
|
19435
19445
|
const { pay: payStripe, isPaying: isPayingStripe } = usePay({
|
|
19436
19446
|
onPaymentSuccess: handlePaymentSuccess,
|
|
19437
19447
|
onPaymentError: error => {
|
|
19438
|
-
handleAllErrorFormats$
|
|
19448
|
+
handleAllErrorFormats$3(error);
|
|
19439
19449
|
},
|
|
19440
19450
|
quote: quote,
|
|
19441
19451
|
invoice: invoice,
|
|
@@ -19447,7 +19457,7 @@ const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSucce
|
|
|
19447
19457
|
onPaymentHoldSuccess === null || onPaymentHoldSuccess === void 0 ? void 0 : onPaymentHoldSuccess(response);
|
|
19448
19458
|
},
|
|
19449
19459
|
onApproveHoldError: error => {
|
|
19450
|
-
handleAllErrorFormats$
|
|
19460
|
+
handleAllErrorFormats$3(error);
|
|
19451
19461
|
},
|
|
19452
19462
|
});
|
|
19453
19463
|
const { approveHold: approveHoldDemoPay, isApprovingHold: isApprovingHoldDemoPay } = useApproveHold$1({
|
|
@@ -19455,7 +19465,7 @@ const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSucce
|
|
|
19455
19465
|
onPaymentHoldSuccess === null || onPaymentHoldSuccess === void 0 ? void 0 : onPaymentHoldSuccess(response);
|
|
19456
19466
|
},
|
|
19457
19467
|
onApproveHoldError: error => {
|
|
19458
|
-
handleAllErrorFormats$
|
|
19468
|
+
handleAllErrorFormats$3(error);
|
|
19459
19469
|
},
|
|
19460
19470
|
});
|
|
19461
19471
|
// Mutations
|
|
@@ -19473,7 +19483,7 @@ const useHandlePayment = ({ quote, invoice, onPaymentSuccess, onPaymentHoldSucce
|
|
|
19473
19483
|
onPaymentSuccess === null || onPaymentSuccess === void 0 ? void 0 : onPaymentSuccess({});
|
|
19474
19484
|
},
|
|
19475
19485
|
onError: error => {
|
|
19476
|
-
handleAllErrorFormats$
|
|
19486
|
+
handleAllErrorFormats$3(error);
|
|
19477
19487
|
},
|
|
19478
19488
|
});
|
|
19479
19489
|
const handleApproveHold = async (overridePaymentMethodId) => {
|
|
@@ -19616,7 +19626,7 @@ function useSave({ onSaveSuccess, onSaveError, accountId, }) {
|
|
|
19616
19626
|
const useShowPaymentDetailsState = (isOpen = false) => react.useState(isOpen);
|
|
19617
19627
|
const [ShowPaymentDetailsProvider, useShowPaymentDetails] = createStateContext(useShowPaymentDetailsState);
|
|
19618
19628
|
|
|
19619
|
-
const handleAllErrorFormats$
|
|
19629
|
+
const handleAllErrorFormats$2 = common.useAllErrorFormats();
|
|
19620
19630
|
const showErrorNotification$5 = common.useErrorNotification();
|
|
19621
19631
|
// Contexts
|
|
19622
19632
|
const [FormattedAmountDueProvider, useFormattedAmountDue] = createValueContext();
|
|
@@ -19662,7 +19672,7 @@ function PaymentProvider({ children, accountId, quote, invoice, onPaymentSuccess
|
|
|
19662
19672
|
});
|
|
19663
19673
|
setShowPaymentMethodForm(false);
|
|
19664
19674
|
},
|
|
19665
|
-
onSaveError: handleAllErrorFormats$
|
|
19675
|
+
onSaveError: handleAllErrorFormats$2,
|
|
19666
19676
|
accountId,
|
|
19667
19677
|
});
|
|
19668
19678
|
const { save: saveStripe, isSaving: isSavingStripe } = useSave({
|
|
@@ -19676,7 +19686,7 @@ function PaymentProvider({ children, accountId, quote, invoice, onPaymentSuccess
|
|
|
19676
19686
|
});
|
|
19677
19687
|
setShowPaymentMethodForm(false);
|
|
19678
19688
|
},
|
|
19679
|
-
onSaveError: handleAllErrorFormats$
|
|
19689
|
+
onSaveError: handleAllErrorFormats$2,
|
|
19680
19690
|
accountId,
|
|
19681
19691
|
});
|
|
19682
19692
|
const pluginName = (_c = (_b = (_a = selectedPlugin === null || selectedPlugin === void 0 ? void 0 : selectedPlugin.components) === null || _a === void 0 ? void 0 : _a.frontend) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.name;
|
|
@@ -19840,8 +19850,8 @@ const DemoPayExpiry = ({ autoFocus, onChange, placeholder, value, }) => {
|
|
|
19840
19850
|
return (jsxRuntime.jsx("div", { className: "bunny-grow", children: jsxRuntime.jsx(antd.Input, { name: "expiry", autoFocus: autoFocus, onKeyDown: onKeyPress, onKeyUp: onKeyPress, onChange: onNumberChange, value: formatCardExpiry(value), maxLength: 5, placeholder: placeholder || "MM/YY" }) }));
|
|
19841
19851
|
};
|
|
19842
19852
|
|
|
19843
|
-
const { Text: Text$
|
|
19844
|
-
const handleAllErrorFormats = common.useAllErrorFormats();
|
|
19853
|
+
const { Text: Text$z } = antd.Typography;
|
|
19854
|
+
const handleAllErrorFormats$1 = common.useAllErrorFormats();
|
|
19845
19855
|
const TEST_CARD = '4242424242424242';
|
|
19846
19856
|
const DemoPayForm = () => {
|
|
19847
19857
|
// Context
|
|
@@ -19858,7 +19868,7 @@ const DemoPayForm = () => {
|
|
|
19858
19868
|
onPaymentFormSubmit(cardDetails);
|
|
19859
19869
|
}
|
|
19860
19870
|
catch (error) {
|
|
19861
|
-
handleAllErrorFormats(error);
|
|
19871
|
+
handleAllErrorFormats$1(error);
|
|
19862
19872
|
}
|
|
19863
19873
|
}
|
|
19864
19874
|
function validateCardDetails() {
|
|
@@ -19880,7 +19890,7 @@ const DemoPayForm = () => {
|
|
|
19880
19890
|
const onCardCvcChange = (cvc) => {
|
|
19881
19891
|
setCardDetails({ ...cardDetails, cvc });
|
|
19882
19892
|
};
|
|
19883
|
-
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxRuntime.jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsxRuntime.jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsxRuntime.jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsxRuntime.jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsxRuntime.jsx(Text$
|
|
19893
|
+
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxRuntime.jsxs(StyledInputs, { className: "bunny-flex bunny-flex-col bunny-gap-2", darkMode: darkMode !== null && darkMode !== void 0 ? darkMode : false, children: [jsxRuntime.jsx(DemoPayCardNumber, { onChange: onCardNumberChange, value: cardDetails.number }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-2", children: [jsxRuntime.jsx(DemoPayExpiry, { onChange: onCardExpiryChange, value: cardDetails.expiry }), jsxRuntime.jsx(DemoPayCardCvc, { onChange: onCardCvcChange, value: cardDetails.cvc })] })] }), jsxRuntime.jsx(Text$z, { children: "DemoPay is for testing only." }), jsxRuntime.jsx(PaymentMethodFooter, { onSubmit: onSubmit })] }));
|
|
19884
19894
|
};
|
|
19885
19895
|
const StyledInputs = defaultStyled.div `
|
|
19886
19896
|
.ant-input {
|
|
@@ -19929,7 +19939,7 @@ const CardIcon = ({ className }) => {
|
|
|
19929
19939
|
return (jsxRuntime.jsxs("svg", { className: className, width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsx("path", { d: "M15 3.75H3C2.17157 3.75 1.5 4.42157 1.5 5.25V12.75C1.5 13.5784 2.17157 14.25 3 14.25H15C15.8284 14.25 16.5 13.5784 16.5 12.75V5.25C16.5 4.42157 15.8284 3.75 15 3.75Z", stroke: common.SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), jsxRuntime.jsx("path", { d: "M1.5 7.5H16.5", stroke: common.SLATE_400, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }));
|
|
19930
19940
|
};
|
|
19931
19941
|
|
|
19932
|
-
const { Text: Text$
|
|
19942
|
+
const { Text: Text$y } = antd.Typography;
|
|
19933
19943
|
const PaymentMethodSelector = () => {
|
|
19934
19944
|
const accountId = useAccountId();
|
|
19935
19945
|
const { paymentPlugins } = usePaymentPlugins(accountId);
|
|
@@ -19943,7 +19953,7 @@ const PaymentOption = ({ selected, paymentPluginId, onClick, name, }) => {
|
|
|
19943
19953
|
const isCard = name === null || name === void 0 ? void 0 : name.toLowerCase().includes('card');
|
|
19944
19954
|
return (jsxRuntime.jsxs(PaymentOptionContainer, { "$brandColor": brandColor, "$selected": selected, className: `bunny-flex bunny-justify-between bunny-items-center bunny-cursor-pointer bunny-py-2 bunny-rounded bunny-border-solid ${darkMode
|
|
19945
19955
|
? `var(--row-background-dark) border-gray-500`
|
|
19946
|
-
: 'bunny-bg-slate-50 bunny-border-slate-200'} bunny-border`, onClick: () => onClick(paymentPluginId), children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-2 bunny-items-center bunny-pl-4", children: [jsxRuntime.jsx(antd.Checkbox, { checked: selected, className: darkMode ? 'border-gray-400' : '' }), jsxRuntime.jsx(Text$
|
|
19956
|
+
: 'bunny-bg-slate-50 bunny-border-slate-200'} bunny-border`, onClick: () => onClick(paymentPluginId), children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-2 bunny-items-center bunny-pl-4", children: [jsxRuntime.jsx(antd.Checkbox, { checked: selected, className: darkMode ? 'border-gray-400' : '' }), jsxRuntime.jsx(Text$y, { children: name })] }), isAch ? (jsxRuntime.jsx(icons.BankOutlined, { className: "bunny-pr-4" })) : isCard ? (jsxRuntime.jsx(CardIcon, { className: "bunny-pr-4" })) : (jsxRuntime.jsx(CardIcon, { className: "bunny-pr-4" }))] }));
|
|
19947
19957
|
};
|
|
19948
19958
|
const PaymentOptionContainer = defaultStyled.div `
|
|
19949
19959
|
transition: border 0.3s ease;
|
|
@@ -20001,7 +20011,7 @@ const useAutoSetDefaultPaymentMethod = ({ handleSetDefault, setDefaultPaymentMet
|
|
|
20001
20011
|
]);
|
|
20002
20012
|
};
|
|
20003
20013
|
|
|
20004
|
-
const query$
|
|
20014
|
+
const query$7 = t(`
|
|
20005
20015
|
query GetCurrentUserData {
|
|
20006
20016
|
company {
|
|
20007
20017
|
name
|
|
@@ -20024,7 +20034,7 @@ const query$5 = t(`
|
|
|
20024
20034
|
`);
|
|
20025
20035
|
const getCurrentUserData = async ({ token, apiHost }) => {
|
|
20026
20036
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
20027
|
-
const response = await execute(query$
|
|
20037
|
+
const response = await execute(query$7, { apiHost, token }, {});
|
|
20028
20038
|
return {
|
|
20029
20039
|
authObjectName: (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.authObjectName,
|
|
20030
20040
|
account: (_b = response === null || response === void 0 ? void 0 : response.currentUser) === null || _b === void 0 ? void 0 : _b.account,
|
|
@@ -20192,6 +20202,8 @@ function PaymentFormContent({ onRemovePaymentMethod, onSetDefaultPaymentMethod,
|
|
|
20192
20202
|
const { paymentMethods: maskedPaymentMethods, isLoading: isPaymentMethodLoading } = usePaymentMethod({ accountId });
|
|
20193
20203
|
// Read fragments
|
|
20194
20204
|
const paymentMethods = react.useMemo(() => maskedPaymentMethods === null || maskedPaymentMethods === void 0 ? void 0 : maskedPaymentMethods.map(paymentMethod => readFragment(PaymentForm_PaymentMethodsFragment, paymentMethod)), [maskedPaymentMethods]);
|
|
20205
|
+
// Derived state
|
|
20206
|
+
const hasPaymentMethods = (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) && (paymentMethods === null || paymentMethods === void 0 ? void 0 : paymentMethods.length) > 0;
|
|
20195
20207
|
// Custom hooks
|
|
20196
20208
|
const { setDefaultPaymentMethod: handleSetDefault, loading: setDefaultPaymentMethodLoading } = useSetDefaultPaymentMethod(message => {
|
|
20197
20209
|
showErrorNotification$4(message, 'Error setting default payment method');
|
|
@@ -20230,7 +20242,7 @@ function PaymentFormContent({ onRemovePaymentMethod, onSetDefaultPaymentMethod,
|
|
|
20230
20242
|
label: !showPaymentMethodForm ? (jsxRuntime.jsx("div", { className: "bunny-pt-2", children: jsxRuntime.jsx(antd.Button, { onClick: handleClickAddPaymentMethod, type: "default", className: "bunny-w-full", id: "addPaymentMethod", children: "Add payment method" }) })) : null,
|
|
20231
20243
|
children: (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-mt-2", children: [jsxRuntime.jsx(PaymentMethodSelector, {}), selectedPlugin && (jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-col", children: jsxRuntime.jsx(PaymentMethodDetails, {}) }))] })),
|
|
20232
20244
|
},
|
|
20233
|
-
] }), formattedAmountDue !== undefined && !showPaymentMethodForm && (jsxRuntime.jsx("div", { className: "bunny-px-4", children: jsxRuntime.jsx(CheckoutFooter, {}) }))] })) : (jsxRuntime.jsx(antd.Button, { style: { margin: '0 16px' }, loading: isPaying, onClick: () => onPaymentFormSubmit(), type: "primary", children: isPaying ? 'Processing...' : 'Complete Order' })) }));
|
|
20245
|
+
] }), formattedAmountDue !== undefined && !showPaymentMethodForm && hasPaymentMethods ? (jsxRuntime.jsx("div", { className: "bunny-px-4", children: jsxRuntime.jsx(CheckoutFooter, {}) })) : null] })) : (jsxRuntime.jsx(antd.Button, { style: { margin: '0 16px' }, loading: isPaying, onClick: () => onPaymentFormSubmit(), type: "primary", children: isPaying ? 'Processing...' : 'Complete Order' })) }));
|
|
20234
20246
|
}
|
|
20235
20247
|
|
|
20236
20248
|
function Invoice({ id, invoiceQuoteViewComponent, backButtonName, onBackButtonClick, onInvoiceDownloadError, onPaymentSuccess, shadow = 'shadow-md', className, hideDownloadButton = false, hidePaymentForm = false, onInvoiceLoaded, }) {
|
|
@@ -20288,7 +20300,7 @@ function ActualInvoice({ hidePaymentForm }) {
|
|
|
20288
20300
|
return (jsxRuntime.jsx("div", { className: "bunny-invoice-container", children: jsxRuntime.jsxs("div", { className: `bunny-flex bunny-gap-6 ${isMobile ? 'bunny-flex-col bunny-w-full' : ''} ${className}`, children: [formattedInvoice.isLegacy ? (jsxRuntime.jsx("div", { className: "bunny-flex bunny-justify-center bunny-w-full", children: jsxRuntime.jsx(LegacyDocument, { documentUuid: formattedInvoice.uuid, documentType: "invoice" }) })) : (invoiceQuoteViewComponent || (jsxRuntime.jsx(InvoiceQuoteView, { html: formattedInvoice.html, formattedInvoice: formattedInvoice, backButtonName: backButtonName, onBackButtonClick: onBackButtonClick }))), isInvoicePayable && !hidePaymentForm && (jsxRuntime.jsx("div", { className: `bunny-w-full ${hideDownloadButton || formattedInvoice.isLegacy ? '' : 'pt-12'}`, children: jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: handlePaymentSuccess, invoice: formattedInvoice }) }))] }) }));
|
|
20289
20301
|
}
|
|
20290
20302
|
|
|
20291
|
-
const query$
|
|
20303
|
+
const query$6 = t(`
|
|
20292
20304
|
query formattedQuote($id: ID) {
|
|
20293
20305
|
formattedQuote(id: $id) {
|
|
20294
20306
|
quote {
|
|
@@ -20432,7 +20444,7 @@ const query$4 = t(`
|
|
|
20432
20444
|
}
|
|
20433
20445
|
`);
|
|
20434
20446
|
const getFormattedQuote = async ({ token, apiHost, id, }) => {
|
|
20435
|
-
const response = await execute(query$
|
|
20447
|
+
const response = await execute(query$6, { apiHost, token }, { id });
|
|
20436
20448
|
return response === null || response === void 0 ? void 0 : response.formattedQuote;
|
|
20437
20449
|
};
|
|
20438
20450
|
|
|
@@ -20481,6 +20493,7 @@ const useSigningPlugins = ({ apiHost, token, }) => {
|
|
|
20481
20493
|
return filterSigningPlugins(plugins.data);
|
|
20482
20494
|
};
|
|
20483
20495
|
|
|
20496
|
+
const handleAllErrorFormats = common.useAllErrorFormats();
|
|
20484
20497
|
const QUOTE_ACCEPT = `
|
|
20485
20498
|
mutation quoteAccept($name: String!, $title: String!, $poNumber: String, $taxNumber: String, $quoteId: ID) {
|
|
20486
20499
|
quoteAccept(name: $name, title: $title, poNumber: $poNumber, taxNumber: $taxNumber, quoteId: $quoteId) {
|
|
@@ -20534,8 +20547,10 @@ const useSendAcceptQuote = ({ quoteId, apiHost, token, onQuoteAccepted, }) => {
|
|
|
20534
20547
|
quoteId,
|
|
20535
20548
|
};
|
|
20536
20549
|
graphQLMutation(mutation, variables, (rsp) => {
|
|
20537
|
-
if (rsp.errors)
|
|
20538
|
-
|
|
20550
|
+
if (rsp.errors) {
|
|
20551
|
+
handleAllErrorFormats(rsp.errors[0].message);
|
|
20552
|
+
setIsAccepting(false);
|
|
20553
|
+
}
|
|
20539
20554
|
else {
|
|
20540
20555
|
const { redirectUri, message, pluginShortName } = rsp.data.quoteSigningUrlCreate;
|
|
20541
20556
|
if (redirectUri) {
|
|
@@ -20686,7 +20701,7 @@ const PandadocPollingModal = ({ isVisible, setVisible, id }) => {
|
|
|
20686
20701
|
};
|
|
20687
20702
|
graphQLMutation(mutation, variables, (rsp) => {
|
|
20688
20703
|
if (rsp.errors)
|
|
20689
|
-
handleAllErrorFormats(rsp.errors);
|
|
20704
|
+
handleAllErrorFormats(rsp.errors[0].message);
|
|
20690
20705
|
else if (rsp.data.quotePollSigningUrl.status === 'document.sent') {
|
|
20691
20706
|
setVisible(false);
|
|
20692
20707
|
window.location.href = rsp.data.quotePollSigningUrl.redirectUri;
|
|
@@ -20768,14 +20783,14 @@ const AcceptQuoteModal = ({ acceptBoxVisible, formattedQuote, sendAccept, setAcc
|
|
|
20768
20783
|
}, open: acceptBoxVisible, title: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length) ? 'Start signing' : 'Accept quote', width: 400, children: jsxRuntime.jsxs(antd.Form, { className: "bunny-flex bunny-flex-col bunny-gap-2", form: form, layout: "vertical", children: [jsxRuntime.jsx(antd.Form.Item, { label: "Your name", name: "name", rules: createRules(true, 'Your name'), children: jsxRuntime.jsx(antd.Input, { autoFocus: true, ref: firstInputRef }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Your job title", name: "title", rules: createRules(true, 'Your job title'), children: jsxRuntime.jsx(antd.Input, {}) }), jsxRuntime.jsx(antd.Form.Item, { label: "Purchase order number", name: "poNumber", rules: createRules(poNumberRequired, 'Purchase order number'), children: jsxRuntime.jsx(antd.Input, {}) }), taxNumberRequired && (jsxRuntime.jsx(antd.Form.Item, { name: "taxNumber", label: taxNumberLabel, rules: createRules(taxNumberRequired, taxNumberLabel), children: jsxRuntime.jsx(antd.Input, {}) }))] }) }));
|
|
20769
20784
|
};
|
|
20770
20785
|
|
|
20771
|
-
const { Title: Title$2, Text: Text$
|
|
20786
|
+
const { Title: Title$2, Text: Text$x } = antd.Typography;
|
|
20772
20787
|
const showSuccessNotification$2 = common.useSuccessNotification();
|
|
20773
20788
|
const PaymentHoldModal = ({ visible, setVisible, quote, }) => {
|
|
20774
20789
|
const queryClient = reactQuery.useQueryClient();
|
|
20775
20790
|
const token = useToken();
|
|
20776
20791
|
return (jsxRuntime.jsxs(StyledModal$2, { centered: true, onCancel: () => {
|
|
20777
20792
|
setVisible(false);
|
|
20778
|
-
}, footer: null, open: visible, width: 600, children: [jsxRuntime.jsxs("div", { className: "bunny-mt-5 bunny-pb-4 bunny-mx-4", children: [jsxRuntime.jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxRuntime.jsxs(Text$
|
|
20793
|
+
}, footer: null, open: visible, width: 600, children: [jsxRuntime.jsxs("div", { className: "bunny-mt-5 bunny-pb-4 bunny-mx-4", children: [jsxRuntime.jsx(Title$2, { className: "bunny-mt-0", level: 5, children: "Pay and sign" }), jsxRuntime.jsxs(Text$x, { className: "bunny-bt-2 bunny-text-sm/5 bunny-text-gray-500", children: ["To accept this quote, approve a payment hold for", ' ', common.formatCurrency(quote.amount, quote.currency), ". This amount will be charged to your payment method once the quote is signed."] })] }), jsxRuntime.jsx("div", { className: "bunny-mb-3", children: jsxRuntime.jsx(PaymentForm, { quote: {
|
|
20779
20794
|
amount: quote.amount,
|
|
20780
20795
|
currencyId: quote.currency,
|
|
20781
20796
|
id: quote.quote.id,
|
|
@@ -20825,7 +20840,7 @@ const StyledModal$2 = (props) => {
|
|
|
20825
20840
|
return jsxRuntime.jsx(ModalOverrideBrandStylings, { closable: false, ...props });
|
|
20826
20841
|
};
|
|
20827
20842
|
|
|
20828
|
-
const { Text: Text$
|
|
20843
|
+
const { Text: Text$w } = antd.Typography;
|
|
20829
20844
|
defaultStyled.div `
|
|
20830
20845
|
Text {
|
|
20831
20846
|
width: 100%;
|
|
@@ -20917,7 +20932,7 @@ function QuoteButtons({ isAccepted, formattedQuote, isMobile, hideDownloadButton
|
|
|
20917
20932
|
const signingPlugins = useSigningPlugins({ apiHost, token });
|
|
20918
20933
|
return (jsxRuntime.jsxs("div", { className: "flex flex-row justify-end items-center gap-4", id: "acceptance", style: {
|
|
20919
20934
|
color: secondaryColor,
|
|
20920
|
-
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$
|
|
20935
|
+
}, children: [isAccepted && formattedQuote.acceptedAt ? (jsxRuntime.jsx(Text$w, { children: `Quote was accepted by ${formattedQuote.acceptedByName} on ${common.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", children: "Pay and sign" })) : (jsxRuntime.jsx(jsxRuntime.Fragment, { children: !isAccepted ? (jsxRuntime.jsx(antd.Button, { disabled: isExpired || isAccepting, onClick: handleClickAccept, type: "primary", children: isExpired
|
|
20921
20936
|
? 'Quote is expired'
|
|
20922
20937
|
: (signingPlugins === null || signingPlugins === void 0 ? void 0 : signingPlugins.length)
|
|
20923
20938
|
? 'Start signing'
|
|
@@ -21038,9 +21053,9 @@ const getColor = (state) => {
|
|
|
21038
21053
|
}
|
|
21039
21054
|
};
|
|
21040
21055
|
|
|
21041
|
-
const { Text: Text$
|
|
21056
|
+
const { Text: Text$v } = antd.Typography;
|
|
21042
21057
|
const TransactionDate = ({ date }) => {
|
|
21043
|
-
return jsxRuntime.jsx(Text$
|
|
21058
|
+
return jsxRuntime.jsx(Text$v, { className: "bunny-text-sm", children: common.formatDate(date) });
|
|
21044
21059
|
};
|
|
21045
21060
|
|
|
21046
21061
|
const ArrowDownToLine = ({ className, color = common.SLATE_600, }) => {
|
|
@@ -21084,13 +21099,13 @@ const TransactionGridCell = defaultStyled.div.withConfig({
|
|
|
21084
21099
|
min-width: 48px;
|
|
21085
21100
|
`;
|
|
21086
21101
|
|
|
21087
|
-
const { Text: Text$
|
|
21102
|
+
const { Text: Text$u } = antd.Typography;
|
|
21088
21103
|
const TransactionsEmptyState = () => {
|
|
21089
21104
|
const { noTransactionsMessage } = react.useContext(TransactionsListContext);
|
|
21090
|
-
return (jsxRuntime.jsx(Text$
|
|
21105
|
+
return (jsxRuntime.jsx(Text$u, { className: "bunny-flex bunny-justify-center bunny-p-4 bunny-text-base", children: noTransactionsMessage || 'There are no transactions' }));
|
|
21091
21106
|
};
|
|
21092
21107
|
|
|
21093
|
-
const { Text: Text$
|
|
21108
|
+
const { Text: Text$t } = antd.Typography;
|
|
21094
21109
|
const isInvoice = (transaction) => {
|
|
21095
21110
|
return transaction.kind === 'INVOICE';
|
|
21096
21111
|
};
|
|
@@ -21098,7 +21113,7 @@ const TransactionRowTitle = ({ transaction }) => {
|
|
|
21098
21113
|
if (!isInvoice(transaction)) {
|
|
21099
21114
|
return jsxRuntime.jsx(jsxRuntime.Fragment, {});
|
|
21100
21115
|
}
|
|
21101
|
-
return (jsxRuntime.jsx(Text$
|
|
21116
|
+
return (jsxRuntime.jsx(Text$t, { className: "bunny-text-slate-400", style: { fontSize: '11px' }, children: transaction.transactionable.number }));
|
|
21102
21117
|
};
|
|
21103
21118
|
|
|
21104
21119
|
function transactionDateToDisplay(transaction, transactionDateType) {
|
|
@@ -21116,7 +21131,7 @@ function transactionDateToDisplay(transaction, transactionDateType) {
|
|
|
21116
21131
|
}
|
|
21117
21132
|
}
|
|
21118
21133
|
|
|
21119
|
-
const { Text: Text$
|
|
21134
|
+
const { Text: Text$s } = antd.Typography;
|
|
21120
21135
|
const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
21121
21136
|
const { columns, transactionDateType } = react.useContext(TransactionsListContext);
|
|
21122
21137
|
const { apiHost, darkMode } = react.useContext(BunnyContext);
|
|
@@ -21144,11 +21159,11 @@ const TransactionsListDesktop = ({ transactions, onTransactionClick, }) => {
|
|
|
21144
21159
|
!showState &&
|
|
21145
21160
|
!showAmount &&
|
|
21146
21161
|
!showDownload &&
|
|
21147
|
-
!showAccountName && (jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsx(Text$
|
|
21162
|
+
!showAccountName && (jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsx(Text$s, { children: "No columns selected" }) })), showDate && (jsxRuntime.jsx(TransactionGridCell, { right: false, children: jsxRuntime.jsx(TransactionDate, { date: transactionDateToDisplay(transaction, transactionDateType) }) })), showTitle && (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(TransactionGridCell, { right: false, className: "bunny-flex bunny-items-center bunny-gap-2", children: [jsxRuntime.jsx(Text$s, { children: lodashExports.capitalize(transaction.kind.toLowerCase()) }), jsxRuntime.jsx(TransactionRowTitle, { transaction: transaction })] }) })), showAccountName && (jsxRuntime.jsx(TransactionGridCell, { right: false, children: jsxRuntime.jsx(Text$s, { children: (_a = transaction.account) === null || _a === void 0 ? void 0 : _a.name }) })), !showDate && !showTitle && !showAccountName && jsxRuntime.jsx(TransactionGridCell, { right: false }), showDownload && (jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsx(TransactionDownload, { transaction: transaction, token: token, apiHost: apiHost }) })), showState ? (jsxRuntime.jsx(TransactionGridCell, { right: false, children: jsxRuntime.jsx(StateTag, { state: transaction.state }) })) : null, showAmount && (jsxRuntime.jsx(TransactionGridCell, { right: true, children: jsxRuntime.jsx(Text$s, { children: common.formatCurrency(((_b = transaction === null || transaction === void 0 ? void 0 : transaction.transactionable) === null || _b === void 0 ? void 0 : _b.amount) || transaction.amount, transaction.currencyId) }) }))] }, index));
|
|
21148
21163
|
}) }));
|
|
21149
21164
|
};
|
|
21150
21165
|
|
|
21151
|
-
const { Text: Text$
|
|
21166
|
+
const { Text: Text$r } = antd.Typography;
|
|
21152
21167
|
const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
21153
21168
|
const { columns, transactionDateType } = react.useContext(TransactionsListContext);
|
|
21154
21169
|
const { apiHost, darkMode } = react.useContext(BunnyContext);
|
|
@@ -21170,11 +21185,11 @@ const TransactionsListMobile = ({ transactions, onTransactionClick, }) => {
|
|
|
21170
21185
|
backgroundColor: index % 2 === 0
|
|
21171
21186
|
? `var(--row-background${darkMode ? '-dark' : ''})`
|
|
21172
21187
|
: `var(--row-background-alternate${darkMode ? '-dark' : ''})`,
|
|
21173
|
-
}, children: [jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [(showTitle || showState) && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showTitle && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Text$
|
|
21188
|
+
}, children: [jsxRuntime.jsx(TransactionGridCell, { children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2", children: [(showTitle || showState) && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showTitle && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Text$r, { children: lodashExports.capitalize(transaction.kind.toLowerCase()) }), jsxRuntime.jsx(TransactionRowTitle, { transaction: transaction })] })), showState && jsxRuntime.jsx(StateTag, { state: transaction.state })] })), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-2", children: [showAccountName && jsxRuntime.jsx(Text$r, { children: (_a = transaction.account) === null || _a === void 0 ? void 0 : _a.name }), showAccountName && showDate && jsxRuntime.jsx(Text$r, { children: "\u00B7" }), showDate && (jsxRuntime.jsx(TransactionDate, { date: transactionDateToDisplay(transaction, transactionDateType) })), showDate && showAmount && jsxRuntime.jsx(Text$r, { children: "\u00B7" }), showAmount && (jsxRuntime.jsx(Text$r, { children: common.formatCurrency(transaction.transactionable.amount || transaction.amount, transaction.currencyId) }))] })] }) }), showDownload && (jsxRuntime.jsx(TransactionGridCell, { right: true, children: jsxRuntime.jsx(TransactionDownload, { transaction: transaction, token: token, apiHost: apiHost }) }))] }, index));
|
|
21174
21189
|
}) }));
|
|
21175
21190
|
};
|
|
21176
21191
|
|
|
21177
|
-
const { Text: Text$
|
|
21192
|
+
const { Text: Text$q } = antd.Typography;
|
|
21178
21193
|
const DISPLAY_WIDTH = 1200;
|
|
21179
21194
|
function Transactions({ transactionComponent, showSearchBar = true, showTitle = true, title = 'Past transactions', columns = ['date', 'title', 'state', 'amount', 'download'], className, shadow = 'shadow-md', searchBarClassName, useModal = false, onTransactionClick, suppressTransactionDisplay = false, kindsToShow = [
|
|
21180
21195
|
common.TransactionKind.INVOICE,
|
|
@@ -21278,7 +21293,7 @@ function TransactionsDisplay({ transactions, onSearchValueChanged, search, }) {
|
|
|
21278
21293
|
onTransactionDisplayClose === null || onTransactionDisplayClose === void 0 ? void 0 : onTransactionDisplayClose(selectedTransaction);
|
|
21279
21294
|
setDrawerOpen(false);
|
|
21280
21295
|
}
|
|
21281
|
-
return (jsxRuntime.jsxs("div", { style: style, children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-shadow-padding-xb bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsxRuntime.jsx(Text$
|
|
21296
|
+
return (jsxRuntime.jsxs("div", { style: style, children: [jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-w-full bunny-shadow-padding-xb bunny-gap-2 ${isMobile ? 'bunny-overflow-hidden' : ''} ${className}`, children: [showTitle || showSearchBar ? (jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'bunny-flex-col bunny-gap-1' : 'bunny-flex-row bunny-items-center'} bunny-justify-between`, children: [showTitle ? (jsxRuntime.jsx(Text$q, { className: "bunny-shrink-0 bunny-font-medium", style: { color: darkMode ? undefined : secondaryColor }, children: title })) : (jsxRuntime.jsx("div", {}) // Empty div so justify-between works
|
|
21282
21297
|
), showSearchBar && (jsxRuntime.jsx("div", { className: `${isMobile ? 'bunny-w-full' : ''}`, children: jsxRuntime.jsx(antd.Input, { className: searchBarClassName ? searchBarClassName : '', onChange: e => {
|
|
21283
21298
|
const value = e.target.value;
|
|
21284
21299
|
// Allow empty string, numbers, and decimal point
|
|
@@ -21401,7 +21416,7 @@ const useHasTaxPlugin = ({ apiHost, token, }) => {
|
|
|
21401
21416
|
return Boolean(plugins === null || plugins === void 0 ? void 0 : plugins.some((plugin) => plugin.type === "taxation"));
|
|
21402
21417
|
};
|
|
21403
21418
|
|
|
21404
|
-
const MUTATION$
|
|
21419
|
+
const MUTATION$6 = () => `
|
|
21405
21420
|
mutation AccountSignup (
|
|
21406
21421
|
$pluginId: String!,
|
|
21407
21422
|
$paymentMethodId: String,
|
|
@@ -21475,7 +21490,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21475
21490
|
priceListCode,
|
|
21476
21491
|
};
|
|
21477
21492
|
const response = await gqlRequest({
|
|
21478
|
-
query: MUTATION$
|
|
21493
|
+
query: MUTATION$6(),
|
|
21479
21494
|
token,
|
|
21480
21495
|
vars,
|
|
21481
21496
|
apiHost,
|
|
@@ -21486,7 +21501,7 @@ const accountSignup = async ({ token, apiHost, accountId, quoteId, paymentToken,
|
|
|
21486
21501
|
return response === null || response === void 0 ? void 0 : response.accountSignup;
|
|
21487
21502
|
};
|
|
21488
21503
|
|
|
21489
|
-
const MUTATION$
|
|
21504
|
+
const MUTATION$5 = () => `
|
|
21490
21505
|
mutation QuoteAccountSignup (
|
|
21491
21506
|
$accountName: String!,
|
|
21492
21507
|
$billingContact: ContactAttributes!,
|
|
@@ -21563,7 +21578,7 @@ const quoteAccountSignup = async ({ token, apiHost, priceListCode, accountName,
|
|
|
21563
21578
|
billingDetails,
|
|
21564
21579
|
};
|
|
21565
21580
|
const response = await gqlRequest({
|
|
21566
|
-
query: MUTATION$
|
|
21581
|
+
query: MUTATION$5(),
|
|
21567
21582
|
token,
|
|
21568
21583
|
vars,
|
|
21569
21584
|
apiHost,
|
|
@@ -21641,7 +21656,7 @@ const QUOTE_RECALCULATE_TAXES = `
|
|
|
21641
21656
|
}
|
|
21642
21657
|
}
|
|
21643
21658
|
`;
|
|
21644
|
-
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
21659
|
+
const quoteRecalculateTaxes$2 = async ({ quoteId, apiHost, token, }) => {
|
|
21645
21660
|
var _a, _b;
|
|
21646
21661
|
const vars = { id: quoteId };
|
|
21647
21662
|
const response = await gqlRequest({
|
|
@@ -21656,7 +21671,7 @@ const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
|
21656
21671
|
return (_b = response.quoteRecalculateTaxes) === null || _b === void 0 ? void 0 : _b.quote;
|
|
21657
21672
|
};
|
|
21658
21673
|
|
|
21659
|
-
const MUTATION$
|
|
21674
|
+
const MUTATION$4 = () => `
|
|
21660
21675
|
query PriceList($code: String!) {
|
|
21661
21676
|
priceList (code: $code) {
|
|
21662
21677
|
basePrice
|
|
@@ -21681,7 +21696,7 @@ query PriceList($code: String!) {
|
|
|
21681
21696
|
}`;
|
|
21682
21697
|
const getPriceList = async ({ token, code, apiHost, }) => {
|
|
21683
21698
|
const response = await gqlRequest({
|
|
21684
|
-
query: MUTATION$
|
|
21699
|
+
query: MUTATION$4(),
|
|
21685
21700
|
token,
|
|
21686
21701
|
vars: { code },
|
|
21687
21702
|
apiHost,
|
|
@@ -21691,16 +21706,60 @@ const getPriceList = async ({ token, code, apiHost, }) => {
|
|
|
21691
21706
|
|
|
21692
21707
|
const SubscriptionsContext = react.createContext({});
|
|
21693
21708
|
|
|
21709
|
+
const QuoteContext = react.createContext({});
|
|
21710
|
+
|
|
21694
21711
|
const graphql = initGraphQLTada();
|
|
21695
21712
|
|
|
21696
|
-
|
|
21697
|
-
if (
|
|
21698
|
-
return
|
|
21699
|
-
if (
|
|
21700
|
-
return
|
|
21701
|
-
if (
|
|
21702
|
-
return
|
|
21703
|
-
|
|
21713
|
+
const periodMonthsConverter = (period) => {
|
|
21714
|
+
if (period === 0)
|
|
21715
|
+
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
21716
|
+
else if (period === 1)
|
|
21717
|
+
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
21718
|
+
else if (period === 3)
|
|
21719
|
+
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
21720
|
+
else if (period === 6)
|
|
21721
|
+
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
21722
|
+
else if (period === 12)
|
|
21723
|
+
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
21724
|
+
else
|
|
21725
|
+
return null;
|
|
21726
|
+
};
|
|
21727
|
+
const billingPeriodConverter = (period) => {
|
|
21728
|
+
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
21729
|
+
return 0;
|
|
21730
|
+
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
21731
|
+
return 1;
|
|
21732
|
+
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
21733
|
+
return 3;
|
|
21734
|
+
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
21735
|
+
return 6;
|
|
21736
|
+
else
|
|
21737
|
+
return 12;
|
|
21738
|
+
};
|
|
21739
|
+
|
|
21740
|
+
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
21741
|
+
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
21742
|
+
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
21743
|
+
}
|
|
21744
|
+
|
|
21745
|
+
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
21746
|
+
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
21747
|
+
priceLists {
|
|
21748
|
+
id
|
|
21749
|
+
isVisible
|
|
21750
|
+
periodMonths
|
|
21751
|
+
}
|
|
21752
|
+
}
|
|
21753
|
+
`);
|
|
21754
|
+
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
21755
|
+
// Read fragments
|
|
21756
|
+
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
21757
|
+
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
21758
|
+
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
21759
|
+
var _a;
|
|
21760
|
+
return !((_a = currentSubscription === null || currentSubscription === void 0 ? void 0 : currentSubscription.addonSubscriptions) === null || _a === void 0 ? void 0 : _a.some(addonSubscription => addonSubscription.priceList.id === addonPriceList.id));
|
|
21761
|
+
});
|
|
21762
|
+
return unpurchasedAddonPriceLists.length > 0;
|
|
21704
21763
|
}
|
|
21705
21764
|
|
|
21706
21765
|
function hasUnpurchasedFeatureAddons(priceList, currentSubscription) {
|
|
@@ -21727,775 +21786,764 @@ function featureAddonSwitchTestId(addonName) {
|
|
|
21727
21786
|
return `feature-addon-switch-${name}`;
|
|
21728
21787
|
}
|
|
21729
21788
|
|
|
21730
|
-
const
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
21736
|
-
var _a, _b;
|
|
21737
|
-
const response = await gqlRequest({
|
|
21738
|
-
query: MUTATION$4,
|
|
21739
|
-
token,
|
|
21740
|
-
apiHost: apiHost,
|
|
21741
|
-
});
|
|
21742
|
-
return ((_b = (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.taxationRequiredAccountFields) === null || _b === void 0 ? void 0 : _b.length) > 0
|
|
21743
|
-
? response.currentUser.taxationRequiredAccountFields
|
|
21744
|
-
: null;
|
|
21789
|
+
const canSubscriptionUpgradeFromTrial = (subscription) => {
|
|
21790
|
+
var _a;
|
|
21791
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
21792
|
+
subscription.plan.selfServiceBuy) ||
|
|
21793
|
+
false;
|
|
21745
21794
|
};
|
|
21746
|
-
|
|
21747
|
-
|
|
21748
|
-
return (
|
|
21795
|
+
const canSubscriptionUpgradeFromTrialExpired = (subscription) => {
|
|
21796
|
+
var _a;
|
|
21797
|
+
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
21798
|
+
subscription.plan.selfServiceBuy) ||
|
|
21799
|
+
false;
|
|
21749
21800
|
};
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
const { privacyUrl, termsUrl } = currentUser;
|
|
21756
|
-
const isMobile = common.useIsMobile();
|
|
21757
|
-
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-items-center bunny-justify-between bunny-shrink-0 ${isMobile ? 'bunny-flex-col bunny-gap-2' : ''} ${className}`, children: [(termsUrl || privacyUrl) && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsxRuntime.jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsxRuntime.jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsxRuntime.jsx(BunnyMarketingLink, {})] }));
|
|
21801
|
+
const isSubscriptionNotActive = (subscription) => {
|
|
21802
|
+
var _a, _b, _c;
|
|
21803
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
21804
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
21805
|
+
((_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
21758
21806
|
};
|
|
21759
|
-
const
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21807
|
+
const isSubscriptionActiveOrPending = (subscription) => {
|
|
21808
|
+
var _a, _b;
|
|
21809
|
+
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'ACTIVE') ||
|
|
21810
|
+
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'PENDING');
|
|
21763
21811
|
};
|
|
21764
|
-
const
|
|
21765
|
-
|
|
21766
|
-
|
|
21767
|
-
|
|
21768
|
-
|
|
21769
|
-
}
|
|
21770
|
-
text-decoration: none;
|
|
21771
|
-
`;
|
|
21772
|
-
const StyledBunnyLink = styled(StyedLink) `
|
|
21773
|
-
&:hover {
|
|
21774
|
-
color: ${common.PRIMARY_COLOR} !important;
|
|
21775
|
-
}
|
|
21776
|
-
`;
|
|
21777
|
-
|
|
21778
|
-
const MUTATION$3 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
21779
|
-
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
21780
|
-
quoteChange {
|
|
21781
|
-
id
|
|
21782
|
-
charges {
|
|
21783
|
-
id
|
|
21784
|
-
amount
|
|
21785
|
-
couponId
|
|
21786
|
-
}
|
|
21787
|
-
}
|
|
21788
|
-
}
|
|
21789
|
-
}`;
|
|
21790
|
-
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
21812
|
+
const isSubscriptionTrial = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL'); };
|
|
21813
|
+
const isSubscriptionTrialExpired = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED'); };
|
|
21814
|
+
// Helper function to check if charge is a discount
|
|
21815
|
+
const isDiscount$1 = (kind) => kind === common.QuoteChangeKind.DISCOUNT || kind === common.QuoteChangeKind.FREE_PERIOD_DISCOUNT;
|
|
21816
|
+
const hasPriceTiers = (charge) => {
|
|
21791
21817
|
var _a;
|
|
21792
|
-
|
|
21793
|
-
const response = await gqlRequest({
|
|
21794
|
-
query: MUTATION$3,
|
|
21795
|
-
token,
|
|
21796
|
-
vars,
|
|
21797
|
-
apiHost,
|
|
21798
|
-
});
|
|
21799
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
21800
|
-
if (errors)
|
|
21801
|
-
throw errors;
|
|
21802
|
-
return response.quote;
|
|
21818
|
+
return Boolean((_a = charge === null || charge === void 0 ? void 0 : charge.priceTiers) === null || _a === void 0 ? void 0 : _a.length);
|
|
21803
21819
|
};
|
|
21804
21820
|
|
|
21805
|
-
const
|
|
21806
|
-
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
}
|
|
21810
|
-
`;
|
|
21811
|
-
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
21812
|
-
var _a;
|
|
21813
|
-
const vars = { couponCode, quoteChangeId };
|
|
21814
|
-
const response = await gqlRequest({
|
|
21815
|
-
query: MUTATION$2,
|
|
21816
|
-
token,
|
|
21817
|
-
vars,
|
|
21818
|
-
apiHost,
|
|
21819
|
-
});
|
|
21820
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeRemoveCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
21821
|
-
if (errors)
|
|
21822
|
-
throw errors;
|
|
21823
|
-
return response.quote;
|
|
21821
|
+
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
21822
|
+
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
21823
|
+
const createPlanDescription = (planDescription) => {
|
|
21824
|
+
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
21824
21825
|
};
|
|
21825
|
-
|
|
21826
|
-
|
|
21827
|
-
|
|
21828
|
-
coupons(filter: ${filter ? `"${filter}"` : 'null'}) {
|
|
21829
|
-
totalCount
|
|
21830
|
-
}
|
|
21826
|
+
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
21827
|
+
if (!priceList) {
|
|
21828
|
+
return;
|
|
21831
21829
|
}
|
|
21832
|
-
|
|
21833
|
-
|
|
21834
|
-
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
|
|
21839
|
-
}
|
|
21840
|
-
|
|
21841
|
-
|
|
21842
|
-
|
|
21843
|
-
|
|
21844
|
-
|
|
21845
|
-
|
|
21846
|
-
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
const { mutate: addCoupon, isPending: isAddingCoupon } = reactQuery.useMutation({
|
|
21850
|
-
mutationFn: (couponCode) => {
|
|
21851
|
-
if (!token) {
|
|
21852
|
-
throw new Error('Token is required');
|
|
21853
|
-
}
|
|
21854
|
-
if (!quoteChangeId) {
|
|
21855
|
-
throw new Error('Quote change ID is required');
|
|
21856
|
-
}
|
|
21857
|
-
return quoteChangeAddCoupon({
|
|
21858
|
-
quoteChangeId,
|
|
21859
|
-
couponCode,
|
|
21860
|
-
apiHost,
|
|
21861
|
-
token,
|
|
21862
|
-
});
|
|
21863
|
-
},
|
|
21864
|
-
onSuccess: () => {
|
|
21865
|
-
onCouponAdded === null || onCouponAdded === void 0 ? void 0 : onCouponAdded();
|
|
21866
|
-
},
|
|
21867
|
-
onError: (error) => {
|
|
21868
|
-
var _a, _b;
|
|
21869
|
-
showErrorNotification$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error adding coupon');
|
|
21870
|
-
},
|
|
21871
|
-
});
|
|
21872
|
-
const { mutate: removeCoupon, isPending: isRemovingCoupon } = reactQuery.useMutation({
|
|
21873
|
-
mutationFn: (couponCode) => {
|
|
21874
|
-
if (!quoteChangeId) {
|
|
21875
|
-
throw new Error('Quote change ID is required');
|
|
21830
|
+
// If a period option is selected, return the charge that matches the selected period option
|
|
21831
|
+
let activeBillingPLCharge;
|
|
21832
|
+
// Default to first price list charge
|
|
21833
|
+
let lowestPLCharge;
|
|
21834
|
+
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
21835
|
+
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
21836
|
+
activeBillingPLCharge = priceList.charges[0];
|
|
21837
|
+
}
|
|
21838
|
+
for (let j = 0; j < priceList.charges.length; j++) {
|
|
21839
|
+
const charge = priceList.charges[j];
|
|
21840
|
+
if (charge.chargeType === common.ChargeType.USAGE || charge.featureAddon === true)
|
|
21841
|
+
continue;
|
|
21842
|
+
if (activeBillingPLCharge) {
|
|
21843
|
+
// If we already found a charge with the same billing period check if this charge is lower
|
|
21844
|
+
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
21845
|
+
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
21846
|
+
activeBillingPLCharge = charge;
|
|
21876
21847
|
}
|
|
21877
|
-
|
|
21878
|
-
|
|
21879
|
-
|
|
21880
|
-
|
|
21881
|
-
|
|
21882
|
-
|
|
21883
|
-
|
|
21884
|
-
|
|
21885
|
-
|
|
21886
|
-
}
|
|
21887
|
-
|
|
21888
|
-
var _a, _b;
|
|
21889
|
-
showErrorNotification$3((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error removing coupon');
|
|
21890
|
-
},
|
|
21891
|
-
});
|
|
21848
|
+
}
|
|
21849
|
+
// If a period option is selected, only return the charge if it matches the selected period option
|
|
21850
|
+
else if (selectedPriceList &&
|
|
21851
|
+
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
21852
|
+
activeBillingPLCharge = charge;
|
|
21853
|
+
}
|
|
21854
|
+
// Otherwise, return the lowest price list charge
|
|
21855
|
+
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
21856
|
+
lowestPLCharge = charge;
|
|
21857
|
+
}
|
|
21858
|
+
}
|
|
21892
21859
|
return {
|
|
21893
|
-
|
|
21894
|
-
removeCoupon,
|
|
21895
|
-
isAddingCoupon,
|
|
21896
|
-
isRemovingCoupon,
|
|
21897
|
-
activeCouponsExist: (coupons === null || coupons === void 0 ? void 0 : coupons.totalCount) > 0,
|
|
21860
|
+
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
21898
21861
|
};
|
|
21899
21862
|
};
|
|
21900
|
-
|
|
21901
|
-
|
|
21902
|
-
|
|
21903
|
-
|
|
21904
|
-
(
|
|
21905
|
-
|
|
21906
|
-
const totalPrice = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.charges.reduce((acc, charge) => acc + Number((charge === null || charge === void 0 ? void 0 : charge.discountedPrice) || 0), 0);
|
|
21907
|
-
return totalPrice === 0;
|
|
21863
|
+
const showErrorNotification$3 = common.useErrorNotification();
|
|
21864
|
+
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
21865
|
+
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
21866
|
+
if (!priceListAddonPlans) {
|
|
21867
|
+
showErrorNotification$3('Price list addon plans are undefined');
|
|
21868
|
+
return false;
|
|
21908
21869
|
}
|
|
21909
|
-
const
|
|
21910
|
-
|
|
21911
|
-
|
|
21912
|
-
|
|
21913
|
-
|
|
21870
|
+
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
21871
|
+
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
21872
|
+
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription);
|
|
21873
|
+
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription);
|
|
21874
|
+
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
21875
|
+
// When should priceList be disabled?
|
|
21876
|
+
// if upgradingSubscription?.priceList.id === priceList.id
|
|
21877
|
+
// AND the upgradingSubscription is not in trial
|
|
21878
|
+
// AND cannot purchase feature addons
|
|
21879
|
+
// AND cannot purchase add-on plans
|
|
21880
|
+
// AND selfServiceBuy is false
|
|
21881
|
+
// if upgradingSubscription?.priceList.id != priceList.id
|
|
21882
|
+
// AND upgradingSubscription is expired trial
|
|
21883
|
+
if (isUpgradingSubscriptionPriceList) {
|
|
21884
|
+
return (!existingSubscriptionInTrial &&
|
|
21885
|
+
!existingSubscriptionInTrialExpired &&
|
|
21886
|
+
!canPurchaseFeatureAddons &&
|
|
21887
|
+
!canPurchasePlanAddons);
|
|
21914
21888
|
}
|
|
21915
|
-
|
|
21916
|
-
|
|
21917
|
-
|
|
21918
|
-
function CouponEditor({ className, onAddCoupon, isAddingCoupon, couponCode, setCouponCode, }) {
|
|
21919
|
-
async function handleAddCoupon() {
|
|
21920
|
-
onAddCoupon(couponCode);
|
|
21889
|
+
else {
|
|
21890
|
+
return false;
|
|
21921
21891
|
}
|
|
21922
|
-
|
|
21892
|
+
};
|
|
21893
|
+
|
|
21894
|
+
const CheckoutButton = ({ disabled, onClickCheckout, loading, tooltipText, }) => {
|
|
21895
|
+
const isMobile = common.useIsMobile();
|
|
21896
|
+
const TooltipWrapper = ({ children }) => {
|
|
21897
|
+
if (tooltipText) {
|
|
21898
|
+
return jsxRuntime.jsx(antd.Tooltip, { title: tooltipText, children: children });
|
|
21899
|
+
}
|
|
21900
|
+
return jsxRuntime.jsx("div", { children: children });
|
|
21901
|
+
};
|
|
21902
|
+
return (jsxRuntime.jsx(TooltipWrapper, { children: jsxRuntime.jsx(antd.Button, { className: isMobile ? 'w-full' : '', disabled: disabled, onClick: onClickCheckout, size: isMobile ? 'large' : 'middle', type: "primary", loading: loading, children: "Proceed to checkout" }) }));
|
|
21903
|
+
};
|
|
21904
|
+
|
|
21905
|
+
var localizedFormat$2 = {exports: {}};
|
|
21906
|
+
|
|
21907
|
+
var localizedFormat$1 = localizedFormat$2.exports;
|
|
21908
|
+
|
|
21909
|
+
var hasRequiredLocalizedFormat;
|
|
21910
|
+
|
|
21911
|
+
function requireLocalizedFormat () {
|
|
21912
|
+
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
21913
|
+
hasRequiredLocalizedFormat = 1;
|
|
21914
|
+
(function (module, exports) {
|
|
21915
|
+
!function(e,t){module.exports=t();}(localizedFormat$1,(function(){var e={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};return function(t,o,n){var r=o.prototype,i=r.format;n.en.formats=e,r.format=function(t){void 0===t&&(t="YYYY-MM-DDTHH:mm:ssZ");var o=this.$locale().formats,n=function(t,o){return t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var i=r&&r.toUpperCase();return n||o[r]||e[r]||o[i].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,o){return t||o.slice(1)}))}))}(t,void 0===o?{}:o);return i.call(this,n)};}}));
|
|
21916
|
+
} (localizedFormat$2));
|
|
21917
|
+
return localizedFormat$2.exports;
|
|
21923
21918
|
}
|
|
21924
21919
|
|
|
21925
|
-
|
|
21926
|
-
|
|
21927
|
-
|
|
21928
|
-
|
|
21929
|
-
|
|
21930
|
-
|
|
21931
|
-
|
|
21932
|
-
|
|
21933
|
-
|
|
21920
|
+
var localizedFormatExports = requireLocalizedFormat();
|
|
21921
|
+
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
21922
|
+
|
|
21923
|
+
dayjs.extend(localizedFormat);
|
|
21924
|
+
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
21925
|
+
if (value !== 0 && !value)
|
|
21926
|
+
return '';
|
|
21927
|
+
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
21928
|
+
if (isNaN(currencyValue))
|
|
21929
|
+
return value;
|
|
21930
|
+
const localeOptions = {
|
|
21931
|
+
minimumFractionDigits: decimals,
|
|
21932
|
+
maximumFractionDigits: decimals,
|
|
21933
|
+
};
|
|
21934
|
+
localeOptions.style = 'currency';
|
|
21935
|
+
localeOptions.currency = currencyIsoCode;
|
|
21936
|
+
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
21937
|
+
};
|
|
21938
|
+
|
|
21939
|
+
const CheckoutPrice_QuoteFragment = t(`
|
|
21940
|
+
fragment CheckoutPrice_QuoteFragment on Quote {
|
|
21934
21941
|
periodAmount
|
|
21935
|
-
|
|
21936
|
-
|
|
21937
|
-
|
|
21938
|
-
|
|
21939
|
-
|
|
21940
|
-
|
|
21941
|
-
|
|
21942
|
-
|
|
21943
|
-
|
|
21944
|
-
|
|
21945
|
-
|
|
21942
|
+
amountDue
|
|
21943
|
+
}
|
|
21944
|
+
`);
|
|
21945
|
+
const CheckoutPrice = ({ isUsage, quote: maskedQuote, selectedPriceList, }) => {
|
|
21946
|
+
var _a;
|
|
21947
|
+
// Read fragments
|
|
21948
|
+
const quote = readFragment(CheckoutPrice_QuoteFragment, maskedQuote);
|
|
21949
|
+
// Hooks
|
|
21950
|
+
const isMobile = common.useIsMobile();
|
|
21951
|
+
// amountDue might not be available, so we use periodAmount as a fallback
|
|
21952
|
+
const displayAmount = (_a = quote === null || quote === void 0 ? void 0 : quote.amountDue) !== null && _a !== void 0 ? _a : quote === null || quote === void 0 ? void 0 : quote.periodAmount;
|
|
21953
|
+
if (!isUsage && (!selectedPriceList || displayAmount === undefined))
|
|
21954
|
+
return null;
|
|
21955
|
+
const convertedPeriodMonths = periodMonthsConverter(selectedPriceList.periodMonths);
|
|
21956
|
+
const periodLabel = convertedPeriodMonths ? common.PERIOD_LABELS[convertedPeriodMonths] : 'undefined';
|
|
21957
|
+
return (jsxRuntime.jsx("div", { className: `bunny-font-medium ${isMobile ? 'bunny-text-2xl' : ''}`, children: isUsage
|
|
21958
|
+
? 'Usage based pricing'
|
|
21959
|
+
: selectedPriceList && displayAmount !== undefined
|
|
21960
|
+
? `${formatCurrency(displayAmount, selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.currencyId, undefined)} / ${periodLabel}`
|
|
21961
|
+
: '' }));
|
|
21962
|
+
};
|
|
21963
|
+
|
|
21964
|
+
const { Text: Text$p } = antd.Typography;
|
|
21965
|
+
const CheckoutBarSummarySection_QuoteFragment = t(`
|
|
21966
|
+
fragment CheckoutBarSummarySection_QuoteFragment on Quote {
|
|
21946
21967
|
quoteChanges {
|
|
21947
|
-
currencyId
|
|
21948
|
-
id
|
|
21949
|
-
kind
|
|
21950
21968
|
charges {
|
|
21951
|
-
subtotal
|
|
21952
|
-
amountsByPeriod {
|
|
21953
|
-
amount
|
|
21954
|
-
startDate
|
|
21955
|
-
}
|
|
21956
|
-
amount
|
|
21957
|
-
billingPeriod
|
|
21958
|
-
currencyId
|
|
21959
|
-
feature {
|
|
21960
|
-
unitName
|
|
21961
|
-
}
|
|
21962
|
-
id
|
|
21963
|
-
name
|
|
21964
|
-
priceListCharge {
|
|
21965
|
-
id
|
|
21966
|
-
}
|
|
21967
|
-
priceList {
|
|
21968
|
-
id
|
|
21969
|
-
}
|
|
21970
|
-
coupon {
|
|
21971
|
-
couponCode
|
|
21972
|
-
}
|
|
21973
|
-
quantity
|
|
21974
|
-
kind
|
|
21975
|
-
}
|
|
21976
|
-
priceList {
|
|
21977
21969
|
id
|
|
21978
|
-
plan {
|
|
21979
|
-
name
|
|
21980
|
-
}
|
|
21981
|
-
product {
|
|
21982
|
-
name
|
|
21983
|
-
}
|
|
21984
21970
|
}
|
|
21985
21971
|
}
|
|
21972
|
+
...CheckoutPrice_QuoteFragment
|
|
21986
21973
|
}
|
|
21987
|
-
|
|
21974
|
+
`, [CheckoutPrice_QuoteFragment]);
|
|
21975
|
+
const CheckoutBarSummarySection = ({ selectedPriceList, onClickCheckout, }) => {
|
|
21976
|
+
var _a, _b;
|
|
21977
|
+
// Context
|
|
21978
|
+
const { quote: maskedQuote, isQuotePending, isUpdatingQuote } = react.useContext(QuoteContext);
|
|
21979
|
+
const quote = readFragment(CheckoutBarSummarySection_QuoteFragment, maskedQuote);
|
|
21980
|
+
const { isInPreviewMode } = react.useContext(SubscriptionsContext);
|
|
21981
|
+
// Hooks
|
|
21982
|
+
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
21983
|
+
const isMobile = common.useIsMobile();
|
|
21984
|
+
const hasPaymentPlugins = Boolean(paymentPlugins === null || paymentPlugins === void 0 ? void 0 : paymentPlugins.length);
|
|
21985
|
+
const quoteHasCharges = Boolean((_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.some(qc => qc.charges.length > 0));
|
|
21986
|
+
const checkoutButtonDisabled = Boolean(!selectedPriceList || !quoteHasCharges || !hasPaymentPlugins || isInPreviewMode);
|
|
21987
|
+
const activeCharge = (_b = getActivePlanPriceData(selectedPriceList, selectedPriceList)) === null || _b === void 0 ? void 0 : _b.activeCharge;
|
|
21988
|
+
const isUsage = (activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.chargeType) === common.ChargeType.USAGE;
|
|
21989
|
+
return (jsxRuntime.jsxs(Text$p, { className: `bunny-flex bunny-items-center bunny-gap-4 ${isMobile ? 'bunny-flex-col' : ''}`, children: [quote && (jsxRuntime.jsxs("div", { className: `bunny-flex ${isMobile ? 'items-center justify-between w-full' : 'flex-col'}`, children: [jsxRuntime.jsx("div", { className: "bunny-text-slate-500 bunny-font-medium bunny-text-right", style: { fontSize: '11px' }, children: "TOTAL" }), jsxRuntime.jsx(CheckoutPrice, { isUsage: isUsage, quote: quote, selectedPriceList: selectedPriceList })] })), jsxRuntime.jsx(CheckoutButton, { disabled: checkoutButtonDisabled, onClickCheckout: onClickCheckout, loading: isQuotePending || isUpdatingQuote, tooltipText: isInPreviewMode
|
|
21990
|
+
? 'Checkout is disabled in preview mode'
|
|
21991
|
+
: !hasPaymentPlugins
|
|
21992
|
+
? 'Cannot checkout. No valid payment plugins found. Please contact your administrator.'
|
|
21993
|
+
: undefined })] }));
|
|
21994
|
+
};
|
|
21988
21995
|
|
|
21989
|
-
const MUTATION$
|
|
21990
|
-
|
|
21991
|
-
|
|
21992
|
-
|
|
21993
|
-
|
|
21994
|
-
|
|
21995
|
-
|
|
21996
|
-
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
22002
|
-
|
|
22003
|
-
|
|
22004
|
-
|
|
21996
|
+
const MUTATION$3 = `{
|
|
21997
|
+
currentUser {
|
|
21998
|
+
taxationRequiredAccountFields
|
|
21999
|
+
}
|
|
22000
|
+
}`;
|
|
22001
|
+
const getTaxationRequiredAccountFields = async ({ apiHost, token, }) => {
|
|
22002
|
+
var _a, _b;
|
|
22003
|
+
const response = await gqlRequest({
|
|
22004
|
+
query: MUTATION$3,
|
|
22005
|
+
token,
|
|
22006
|
+
apiHost: apiHost,
|
|
22007
|
+
});
|
|
22008
|
+
return ((_b = (_a = response === null || response === void 0 ? void 0 : response.currentUser) === null || _a === void 0 ? void 0 : _a.taxationRequiredAccountFields) === null || _b === void 0 ? void 0 : _b.length) > 0
|
|
22009
|
+
? response.currentUser.taxationRequiredAccountFields
|
|
22010
|
+
: null;
|
|
22011
|
+
};
|
|
22012
|
+
|
|
22013
|
+
const BunnyFooterIcon = ({ color }) => {
|
|
22014
|
+
return (jsxRuntime.jsxs("svg", { width: "45", height: "15", viewBox: "0 0 39 13", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [jsxRuntime.jsxs("g", { clipPath: "url(#clip0_6_851)", children: [jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M14.5898 7.19708C14.5898 9.35053 13.0926 10.325 11.2495 10.325C9.39955 10.325 7.90234 9.35001 7.90234 7.18967V3.26221H10.1125V7.00052C10.1125 7.87719 10.5855 8.27725 11.2495 8.27725C11.9061 8.27725 12.3865 7.87719 12.3865 7.00052V3.26221H14.5898V7.19708Z", fill: color }), jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M31.8943 12.9625H29.4793L31.8523 8.62816L28.9355 3.26221H31.4708L33.0457 6.35524L34.5924 3.26221H37.0075L31.8943 12.9625Z", fill: color }), jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M15.1602 5.96827C15.1602 3.8148 16.6574 2.84033 18.5005 2.84033C20.3504 2.84033 21.8476 3.81533 21.8476 5.97568V10.1473H19.6374V6.16483C19.6374 5.28815 19.1645 4.8881 18.5005 4.8881C17.8439 4.8881 17.3634 5.28815 17.3634 6.16483V10.1473H15.1602V5.96827Z", fill: color }), jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M22.4316 5.96827C22.4316 3.8148 23.9289 2.84033 25.7719 2.84033C27.6219 2.84033 29.1191 3.81533 29.1191 5.97568V10.1473H26.9089V6.16483C26.9089 5.28815 26.4359 4.8881 25.7719 4.8881C25.1154 4.8881 24.6349 5.28815 24.6349 6.16483V10.1473H22.4316V5.96827Z", fill: color }), jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M7.40511 6.68957C7.40511 8.7236 6.02815 10.3227 4.17816 10.3227C3.23907 10.3227 2.61071 9.94378 2.19358 9.40371V10.1404H0.0605469V0.0405273H2.26381V3.91939C2.68041 3.42158 3.28802 3.07069 4.17763 3.07069C6.02759 3.07069 7.40511 4.66981 7.40511 6.68957ZM2.17229 6.69642C2.17229 7.60802 2.77937 8.2744 3.64823 8.2744C4.53783 8.2744 5.13107 7.59372 5.13107 6.69642C5.13107 5.79912 4.53783 5.11844 3.64823 5.11844C2.77937 5.11844 2.17229 5.78482 2.17229 6.69642Z", fill: color }), jsxRuntime.jsx("path", { className: "bunny-icon-path", d: "M38.966 8.94801C38.966 9.76181 38.2668 10.4631 37.4618 10.4631C36.6499 10.4631 35.9434 9.76181 35.9434 8.94801C35.9434 8.14846 36.6494 7.46094 37.4618 7.46094C38.2668 7.46094 38.966 8.14846 38.966 8.94801Z", fill: color })] }), jsxRuntime.jsx("defs", { children: jsxRuntime.jsx("clipPath", { id: "clip0_6_851", children: jsxRuntime.jsx("rect", { width: "39", height: "13", fill: "white" }) }) })] }));
|
|
22015
|
+
};
|
|
22016
|
+
|
|
22017
|
+
const { Text: Text$o } = antd.Typography;
|
|
22018
|
+
const Footer = ({ className }) => {
|
|
22019
|
+
const token = useToken();
|
|
22020
|
+
const { currentUser } = useCurrentUserData(token);
|
|
22021
|
+
const { privacyUrl, termsUrl } = currentUser;
|
|
22022
|
+
const isMobile = common.useIsMobile();
|
|
22023
|
+
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-items-center bunny-justify-between bunny-shrink-0 ${isMobile ? 'bunny-flex-col bunny-gap-2' : ''} ${className}`, children: [(termsUrl || privacyUrl) && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center bunny-gap-3", children: [termsUrl && (jsxRuntime.jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: termsUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Terms" })), privacyUrl && (jsxRuntime.jsx(StyedLink, { className: "bunny-text-xs bunny-text-slate-400", href: privacyUrl, rel: "noopener noreferrer", target: "_blank", type: "text", children: "Privacy" }))] })), jsxRuntime.jsx(BunnyMarketingLink, {})] }));
|
|
22024
|
+
};
|
|
22025
|
+
const BunnyMarketingLink = () => {
|
|
22026
|
+
const [isHovered, setIsHovered] = react.useState(false);
|
|
22027
|
+
const isMobile = common.useIsMobile();
|
|
22028
|
+
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-items-end bunny-justify-end ${isMobile ? '' : 'grow'}`, children: jsxRuntime.jsx(StyledBunnyLink, { className: "bunny-flex bunny-items-end bunny-justify-end bunny-text-slate-400", href: "https://bunny.com/", rel: "noopener noreferrer", target: "_blank", children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-items-center", onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), children: [jsxRuntime.jsx(Text$o, { className: "bunny-text-slate-400", children: "Powered by\u00A0" }), jsxRuntime.jsx("div", { style: { paddingTop: '5px' }, children: jsxRuntime.jsx(BunnyFooterIcon, { color: isHovered ? common.PRIMARY_COLOR : common.SLATE_400 }) })] }) }) }));
|
|
22029
|
+
};
|
|
22030
|
+
const StyedLink = styled.a `
|
|
22031
|
+
color: ${common.SLATE_400};
|
|
22032
|
+
transition: color 0.3s;
|
|
22033
|
+
&:hover {
|
|
22034
|
+
color: ${common.SLATE_500};
|
|
22035
|
+
}
|
|
22036
|
+
text-decoration: none;
|
|
22037
|
+
`;
|
|
22038
|
+
const StyledBunnyLink = styled(StyedLink) `
|
|
22039
|
+
&:hover {
|
|
22040
|
+
color: ${common.PRIMARY_COLOR} !important;
|
|
22041
|
+
}
|
|
22042
|
+
`;
|
|
22043
|
+
|
|
22044
|
+
const MUTATION$2 = `mutation quoteChangeAddCoupon($couponCode: String!, $quoteChangeId: ID!) {
|
|
22045
|
+
quoteChangeAddCoupon(couponCode: $couponCode, quoteChangeId: $quoteChangeId) {
|
|
22046
|
+
quoteChange {
|
|
22047
|
+
id
|
|
22048
|
+
charges {
|
|
22049
|
+
id
|
|
22050
|
+
amount
|
|
22051
|
+
couponId
|
|
22005
22052
|
}
|
|
22006
|
-
errors
|
|
22007
22053
|
}
|
|
22008
|
-
|
|
22054
|
+
}
|
|
22055
|
+
}`;
|
|
22056
|
+
const quoteChangeAddCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22057
|
+
var _a;
|
|
22058
|
+
const vars = { couponCode, quoteChangeId };
|
|
22059
|
+
const response = await gqlRequest({
|
|
22060
|
+
query: MUTATION$2,
|
|
22061
|
+
token,
|
|
22062
|
+
vars,
|
|
22063
|
+
apiHost,
|
|
22064
|
+
});
|
|
22065
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteAddCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22066
|
+
if (errors)
|
|
22067
|
+
throw errors;
|
|
22068
|
+
return response.quote;
|
|
22069
|
+
};
|
|
22070
|
+
|
|
22071
|
+
const MUTATION$1 = `mutation quoteChangeRemoveCoupon($quoteChangeId: ID!, $couponCode: String!) {
|
|
22072
|
+
quoteChangeRemoveCoupon(quoteChangeId: $quoteChangeId, couponCode: $couponCode) {
|
|
22073
|
+
errors
|
|
22074
|
+
}
|
|
22075
|
+
}
|
|
22009
22076
|
`;
|
|
22010
|
-
const
|
|
22077
|
+
const quoteChangeRemoveCoupon = async ({ quoteChangeId, couponCode, token, apiHost, }) => {
|
|
22011
22078
|
var _a;
|
|
22012
|
-
const vars = {
|
|
22079
|
+
const vars = { couponCode, quoteChangeId };
|
|
22013
22080
|
const response = await gqlRequest({
|
|
22014
22081
|
query: MUTATION$1,
|
|
22015
22082
|
token,
|
|
22016
22083
|
vars,
|
|
22017
22084
|
apiHost,
|
|
22018
22085
|
});
|
|
22019
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.
|
|
22086
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeRemoveCoupon) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22020
22087
|
if (errors)
|
|
22021
22088
|
throw errors;
|
|
22022
|
-
return response.
|
|
22089
|
+
return response.quote;
|
|
22023
22090
|
};
|
|
22024
22091
|
|
|
22025
|
-
const
|
|
22026
|
-
|
|
22027
|
-
|
|
22028
|
-
|
|
22029
|
-
|
|
22030
|
-
|
|
22031
|
-
|
|
22032
|
-
|
|
22033
|
-
const
|
|
22034
|
-
|
|
22035
|
-
|
|
22036
|
-
|
|
22037
|
-
|
|
22038
|
-
|
|
22092
|
+
const COUPONS_QUERY = (filter) => `
|
|
22093
|
+
query Coupons {
|
|
22094
|
+
coupons(filter: ${filter ? `"${filter}"` : 'null'}) {
|
|
22095
|
+
totalCount
|
|
22096
|
+
}
|
|
22097
|
+
}
|
|
22098
|
+
`;
|
|
22099
|
+
const getCoupons = async ({ token, apiHost, filter, }) => {
|
|
22100
|
+
const response = await gqlRequest({
|
|
22101
|
+
query: COUPONS_QUERY(filter),
|
|
22102
|
+
token,
|
|
22103
|
+
vars: {},
|
|
22104
|
+
apiHost,
|
|
22105
|
+
});
|
|
22106
|
+
return response === null || response === void 0 ? void 0 : response.coupons;
|
|
22107
|
+
};
|
|
22108
|
+
|
|
22109
|
+
const showErrorNotification$2 = common.useErrorNotification();
|
|
22110
|
+
const useUpdateCoupons = ({ apiHost, token, quoteChangeId, onCouponAdded, onCouponRemoved, }) => {
|
|
22111
|
+
const { data: coupons } = reactQuery.useQuery({
|
|
22112
|
+
queryKey: ['coupons', token],
|
|
22113
|
+
queryFn: () => getCoupons({ token, apiHost, filter: 'coupon.active is true' }),
|
|
22114
|
+
});
|
|
22115
|
+
const { mutate: addCoupon, isPending: isAddingCoupon } = reactQuery.useMutation({
|
|
22116
|
+
mutationFn: (couponCode) => {
|
|
22117
|
+
if (!token) {
|
|
22118
|
+
throw new Error('Token is required');
|
|
22119
|
+
}
|
|
22120
|
+
if (!quoteChangeId) {
|
|
22121
|
+
throw new Error('Quote change ID is required');
|
|
22122
|
+
}
|
|
22123
|
+
return quoteChangeAddCoupon({
|
|
22124
|
+
quoteChangeId,
|
|
22125
|
+
couponCode,
|
|
22039
22126
|
apiHost,
|
|
22127
|
+
token,
|
|
22040
22128
|
});
|
|
22041
|
-
return account;
|
|
22042
22129
|
},
|
|
22043
22130
|
onSuccess: () => {
|
|
22044
|
-
|
|
22045
|
-
|
|
22131
|
+
onCouponAdded === null || onCouponAdded === void 0 ? void 0 : onCouponAdded();
|
|
22132
|
+
},
|
|
22133
|
+
onError: (error) => {
|
|
22134
|
+
var _a, _b;
|
|
22135
|
+
showErrorNotification$2((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error adding coupon');
|
|
22136
|
+
},
|
|
22137
|
+
});
|
|
22138
|
+
const { mutate: removeCoupon, isPending: isRemovingCoupon } = reactQuery.useMutation({
|
|
22139
|
+
mutationFn: (couponCode) => {
|
|
22140
|
+
if (!quoteChangeId) {
|
|
22141
|
+
throw new Error('Quote change ID is required');
|
|
22142
|
+
}
|
|
22143
|
+
return quoteChangeRemoveCoupon({
|
|
22144
|
+
quoteChangeId,
|
|
22145
|
+
couponCode,
|
|
22146
|
+
apiHost,
|
|
22147
|
+
token,
|
|
22046
22148
|
});
|
|
22047
22149
|
},
|
|
22150
|
+
onSuccess: () => {
|
|
22151
|
+
onCouponRemoved === null || onCouponRemoved === void 0 ? void 0 : onCouponRemoved();
|
|
22152
|
+
},
|
|
22153
|
+
onError: (error) => {
|
|
22154
|
+
var _a, _b;
|
|
22155
|
+
showErrorNotification$2((_b = (_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.errors[0]) === null || _b === void 0 ? void 0 : _b.message, 'Error removing coupon');
|
|
22156
|
+
},
|
|
22048
22157
|
});
|
|
22049
|
-
return
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
const billingCountry = antd.Form.useWatch('billingCountry');
|
|
22057
|
-
const billingStateRequired = COUNTRIES_REQUIRING_STATE.includes(billingCountry);
|
|
22058
|
-
return (jsxRuntime.jsx(antd.Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsxRuntime.jsx(antd.Input, { placeholder: "State" }) }));
|
|
22158
|
+
return {
|
|
22159
|
+
addCoupon,
|
|
22160
|
+
removeCoupon,
|
|
22161
|
+
isAddingCoupon,
|
|
22162
|
+
isRemovingCoupon,
|
|
22163
|
+
activeCouponsExist: (coupons === null || coupons === void 0 ? void 0 : coupons.totalCount) > 0,
|
|
22164
|
+
};
|
|
22059
22165
|
};
|
|
22060
22166
|
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22167
|
+
function shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) {
|
|
22168
|
+
var _a, _b;
|
|
22169
|
+
const upgradingFromTrial = ((_a = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') ||
|
|
22170
|
+
((_b = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
22171
|
+
function upgradingFromFree() {
|
|
22172
|
+
const totalPrice = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.charges.reduce((acc, charge) => acc + Number((charge === null || charge === void 0 ? void 0 : charge.discountedPrice) || 0), 0);
|
|
22173
|
+
return totalPrice === 0;
|
|
22174
|
+
}
|
|
22175
|
+
const quoteKindIsValid = quote.kind === common.QuoteChangeKind.SUBSCRIBE ||
|
|
22176
|
+
quote.kind === common.QuoteChangeKind.ADJUSTMENT ||
|
|
22177
|
+
quote.kind === common.QuoteChangeKind.ACTIVATE;
|
|
22178
|
+
if (quoteKindIsValid) {
|
|
22179
|
+
return activeCouponsExist && (upgradingFromTrial || upgradingFromFree());
|
|
22180
|
+
}
|
|
22181
|
+
return false;
|
|
22182
|
+
}
|
|
22183
|
+
|
|
22184
|
+
function CouponEditor({ className, onAddCoupon, isAddingCoupon, couponCode, setCouponCode, }) {
|
|
22185
|
+
async function handleAddCoupon() {
|
|
22186
|
+
onAddCoupon(couponCode);
|
|
22187
|
+
}
|
|
22188
|
+
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 ${className}`, children: jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2", children: [jsxRuntime.jsx(antd.Input, { value: couponCode, onChange: e => setCouponCode(e.target.value), placeholder: "Coupon code", disabled: isAddingCoupon, size: "small" }), jsxRuntime.jsx(antd.Button, { loading: isAddingCoupon, type: "primary", onClick: handleAddCoupon, disabled: couponCode.length === 0, children: "Apply" })] }) }));
|
|
22189
|
+
}
|
|
22190
|
+
|
|
22191
|
+
const QuoteFields_QuoteFragment = t(`
|
|
22192
|
+
fragment QuoteFields_QuoteFragment on Quote @_unmask {
|
|
22067
22193
|
accountId
|
|
22068
|
-
amountDue
|
|
22069
22194
|
amount
|
|
22195
|
+
amountDue
|
|
22196
|
+
smallUnitAmountDue
|
|
22197
|
+
currencyId
|
|
22198
|
+
id
|
|
22199
|
+
payableId
|
|
22200
|
+
periodAmount
|
|
22201
|
+
subtotal
|
|
22202
|
+
taxAmount
|
|
22203
|
+
startDate
|
|
22204
|
+
formattedQuote {
|
|
22205
|
+
html
|
|
22206
|
+
}
|
|
22207
|
+
amountsByPeriod {
|
|
22208
|
+
amount
|
|
22209
|
+
startDate
|
|
22210
|
+
}
|
|
22211
|
+
kind
|
|
22070
22212
|
quoteChanges {
|
|
22213
|
+
currencyId
|
|
22071
22214
|
id
|
|
22215
|
+
kind
|
|
22072
22216
|
charges {
|
|
22073
|
-
|
|
22217
|
+
subtotal
|
|
22218
|
+
amountsByPeriod {
|
|
22219
|
+
amount
|
|
22220
|
+
startDate
|
|
22221
|
+
}
|
|
22222
|
+
amount
|
|
22223
|
+
billingPeriod
|
|
22224
|
+
currencyId
|
|
22225
|
+
feature {
|
|
22226
|
+
unitName
|
|
22227
|
+
}
|
|
22228
|
+
id
|
|
22229
|
+
name
|
|
22230
|
+
priceListCharge {
|
|
22231
|
+
id
|
|
22232
|
+
}
|
|
22233
|
+
priceList {
|
|
22234
|
+
id
|
|
22235
|
+
}
|
|
22074
22236
|
coupon {
|
|
22075
22237
|
couponCode
|
|
22076
22238
|
}
|
|
22239
|
+
quantity
|
|
22240
|
+
kind
|
|
22077
22241
|
}
|
|
22078
|
-
|
|
22079
|
-
|
|
22080
|
-
|
|
22081
|
-
|
|
22082
|
-
|
|
22083
|
-
|
|
22084
|
-
|
|
22085
|
-
|
|
22086
|
-
|
|
22242
|
+
priceList {
|
|
22243
|
+
id
|
|
22244
|
+
plan {
|
|
22245
|
+
name
|
|
22246
|
+
}
|
|
22247
|
+
product {
|
|
22248
|
+
name
|
|
22249
|
+
}
|
|
22250
|
+
}
|
|
22251
|
+
}
|
|
22252
|
+
}
|
|
22253
|
+
`);
|
|
22254
|
+
|
|
22255
|
+
const MUTATION = `
|
|
22256
|
+
mutation accountUpdate(
|
|
22257
|
+
$id: ID!,
|
|
22258
|
+
$attributes: AccountAttributes!) {
|
|
22259
|
+
accountUpdate(
|
|
22260
|
+
id: $id,
|
|
22261
|
+
attributes: $attributes
|
|
22262
|
+
) {
|
|
22263
|
+
account {
|
|
22264
|
+
id
|
|
22265
|
+
billingCountry
|
|
22266
|
+
billingState
|
|
22267
|
+
billingStreet
|
|
22268
|
+
billingCity
|
|
22269
|
+
billingZip
|
|
22270
|
+
name
|
|
22271
|
+
}
|
|
22272
|
+
errors
|
|
22273
|
+
}
|
|
22274
|
+
}
|
|
22275
|
+
`;
|
|
22276
|
+
const accountUpdate$1 = async ({ accountId, attributes, token, apiHost, }) => {
|
|
22277
|
+
var _a;
|
|
22278
|
+
const vars = { id: accountId, attributes };
|
|
22279
|
+
const response = await gqlRequest({
|
|
22280
|
+
query: MUTATION,
|
|
22281
|
+
token,
|
|
22282
|
+
vars,
|
|
22283
|
+
apiHost,
|
|
22284
|
+
});
|
|
22285
|
+
const errors = (_a = response === null || response === void 0 ? void 0 : response.accountUpdate) === null || _a === void 0 ? void 0 : _a.errors;
|
|
22286
|
+
if (errors)
|
|
22287
|
+
throw errors;
|
|
22288
|
+
return response.accountUpdate;
|
|
22289
|
+
};
|
|
22290
|
+
|
|
22291
|
+
const COUNTRIES_REQUIRING_STATE = ['US', 'CA'];
|
|
22292
|
+
const TaxationForm = ({ account, accountId }) => {
|
|
22293
|
+
// Hooks
|
|
22294
|
+
const queryClient = reactQuery.useQueryClient();
|
|
22087
22295
|
const { apiHost } = react.useContext(BunnyContext);
|
|
22088
|
-
const { upgradingSubscription } = react.useContext(SubscriptionsContext);
|
|
22089
22296
|
const token = useToken();
|
|
22090
|
-
const
|
|
22091
|
-
|
|
22092
|
-
const
|
|
22093
|
-
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
onCouponAdded: () => {
|
|
22100
|
-
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
22101
|
-
throw new Error('Quote ID is required');
|
|
22102
|
-
queryClient.invalidateQueries({
|
|
22103
|
-
queryKey: common.QueryKeyFactory.default.createObjectKey({
|
|
22104
|
-
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
22105
|
-
objectName: 'editingQuote',
|
|
22106
|
-
token,
|
|
22107
|
-
}),
|
|
22297
|
+
const [form] = antd.Form.useForm();
|
|
22298
|
+
// Mutations
|
|
22299
|
+
const { mutate: updateAccount, isPending: isUpdatingAccount } = reactQuery.useMutation({
|
|
22300
|
+
mutationFn: async (changedFormData) => {
|
|
22301
|
+
const account = await accountUpdate$1({
|
|
22302
|
+
accountId,
|
|
22303
|
+
attributes: changedFormData,
|
|
22304
|
+
token,
|
|
22305
|
+
apiHost,
|
|
22108
22306
|
});
|
|
22109
|
-
|
|
22110
|
-
onRecalculateTaxes();
|
|
22111
|
-
setCouponCode('');
|
|
22307
|
+
return account;
|
|
22112
22308
|
},
|
|
22113
|
-
|
|
22114
|
-
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
22115
|
-
throw new Error('Quote ID is required');
|
|
22309
|
+
onSuccess: () => {
|
|
22116
22310
|
queryClient.invalidateQueries({
|
|
22117
|
-
queryKey:
|
|
22118
|
-
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
22119
|
-
objectName: 'editingQuote',
|
|
22120
|
-
token,
|
|
22121
|
-
}),
|
|
22311
|
+
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
22122
22312
|
});
|
|
22123
|
-
showSuccessNotification$1('Coupon removed');
|
|
22124
|
-
onRecalculateTaxes();
|
|
22125
22313
|
},
|
|
22126
22314
|
});
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
if (paymentRequired)
|
|
22133
|
-
throw new Error('Payment is required');
|
|
22134
|
-
return await checkout({ quoteId: quote.id, token, apiHost });
|
|
22135
|
-
},
|
|
22136
|
-
onSuccess,
|
|
22137
|
-
onError: onFail,
|
|
22138
|
-
});
|
|
22139
|
-
async function handleCheckoutNoPayment() {
|
|
22140
|
-
setIsSaving(true);
|
|
22141
|
-
checkoutMutation.mutate();
|
|
22142
|
-
setIsSaving(false);
|
|
22143
|
-
}
|
|
22144
|
-
if (taxationRequiredAccountFields)
|
|
22145
|
-
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsxRuntime.jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
22146
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: paymentRequired ? (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote }), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: upgradingSubscription &&
|
|
22147
|
-
shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) && (jsxRuntime.jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", quote: quote, onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsxRuntime.jsx(antd.Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
22148
|
-
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
22149
|
-
var _a;
|
|
22150
|
-
const couponCode = (_a = couponCharge === null || couponCharge === void 0 ? void 0 : couponCharge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode;
|
|
22151
|
-
if (couponCode) {
|
|
22152
|
-
removeCoupon(couponCode);
|
|
22153
|
-
}
|
|
22154
|
-
});
|
|
22155
|
-
}, children: "Remove coupon(s)" }))] })) : (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsxRuntime.jsx(antd.Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsxRuntime.jsx("div", { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] }) })) }));
|
|
22315
|
+
return (jsxRuntime.jsxs(antd.Form, { className: "bunny-flex bunny-flex-col bunny-gap-4", form: form, initialValues: account, layout: "vertical", onFinish: updateAccount, children: [jsxRuntime.jsx(antd.Form.Item, { label: "Billing street", name: "billingStreet", children: jsxRuntime.jsx(antd.Input, { placeholder: "Street" }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Billing city", name: "billingCity", children: jsxRuntime.jsx(antd.Input, { placeholder: "City" }) }), jsxRuntime.jsx(FormBillingState, {}), jsxRuntime.jsx(antd.Form.Item, { label: "Billing country", name: "billingCountry", rules: [{ required: true }], children: jsxRuntime.jsx(antd.Select, { options: common.Lists.COUNTRY_LIST, placeholder: "Select a country", showSearch: true, filterOption: (input, option) => {
|
|
22316
|
+
var _a, _b;
|
|
22317
|
+
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
22318
|
+
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
22319
|
+
} }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Billing zip", name: "billingZip", children: jsxRuntime.jsx(antd.Input, { placeholder: "Zip" }) }), jsxRuntime.jsx(antd.Form.Item, { children: jsxRuntime.jsx(antd.Button, { className: "bunny-w-full", disabled: isUpdatingAccount, htmlType: "submit", type: "primary", children: "Submit" }) })] }));
|
|
22156
22320
|
};
|
|
22157
|
-
const
|
|
22158
|
-
const
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
? setMaxHeight
|
|
22162
|
-
? { maxHeight: '60vh' }
|
|
22163
|
-
: {}
|
|
22164
|
-
: {
|
|
22165
|
-
width: '100%',
|
|
22166
|
-
maxWidth: '350px',
|
|
22167
|
-
}),
|
|
22168
|
-
}, children: children }));
|
|
22321
|
+
const FormBillingState = () => {
|
|
22322
|
+
const billingCountry = antd.Form.useWatch('billingCountry');
|
|
22323
|
+
const billingStateRequired = COUNTRIES_REQUIRING_STATE.includes(billingCountry);
|
|
22324
|
+
return (jsxRuntime.jsx(antd.Form.Item, { label: "Billing state", name: "billingState", rules: [{ required: billingStateRequired }], children: jsxRuntime.jsx(antd.Input, { placeholder: "State" }) }));
|
|
22169
22325
|
};
|
|
22170
22326
|
|
|
22171
|
-
const
|
|
22172
|
-
|
|
22173
|
-
|
|
22327
|
+
const { Text: Text$n } = antd.Typography;
|
|
22328
|
+
// HACK: I have imported QuoteFields_QuoteFragment here as a hack to ensure I have all of the quote data needed for
|
|
22329
|
+
// the eventual children of this component.
|
|
22330
|
+
// Solution: Eventually all children of this component should be using query fragments to avoid this
|
|
22331
|
+
const QuoteCheckout_QuoteFragment = t(`
|
|
22332
|
+
fragment QuoteCheckout_QuoteFragment on Quote {
|
|
22174
22333
|
id
|
|
22175
22334
|
accountId
|
|
22176
|
-
|
|
22177
|
-
|
|
22335
|
+
amountDue
|
|
22336
|
+
amount
|
|
22337
|
+
quoteChanges {
|
|
22338
|
+
id
|
|
22339
|
+
charges {
|
|
22340
|
+
kind
|
|
22341
|
+
coupon {
|
|
22342
|
+
couponCode
|
|
22343
|
+
}
|
|
22344
|
+
}
|
|
22178
22345
|
}
|
|
22179
|
-
...
|
|
22346
|
+
...QuoteFields_QuoteFragment
|
|
22180
22347
|
}
|
|
22181
|
-
`, [
|
|
22182
|
-
const
|
|
22348
|
+
`, [QuoteFields_QuoteFragment]);
|
|
22349
|
+
const showSuccessNotification$1 = common.useSuccessNotification();
|
|
22350
|
+
const QuoteCheckout = ({ account, onSuccess, onFail, quote: maskedQuote, taxationRequiredAccountFields, onRecalculateTaxes, }) => {
|
|
22183
22351
|
var _a, _b, _c, _d, _e;
|
|
22352
|
+
// Read fragments
|
|
22353
|
+
const quote = readFragment(QuoteCheckout_QuoteFragment, maskedQuote);
|
|
22184
22354
|
const { apiHost } = react.useContext(BunnyContext);
|
|
22185
|
-
const
|
|
22355
|
+
const { upgradingSubscription } = react.useContext(SubscriptionsContext);
|
|
22186
22356
|
const token = useToken();
|
|
22187
|
-
|
|
22188
|
-
const
|
|
22189
|
-
const
|
|
22357
|
+
const isMobile = common.useIsMobile();
|
|
22358
|
+
const [isSaving, setIsSaving] = react.useState(false);
|
|
22359
|
+
const paymentRequired = getQuoteAmountDue(quote) > 0;
|
|
22360
|
+
const queryClient = reactQuery.useQueryClient();
|
|
22361
|
+
const [couponCode, setCouponCode] = react.useState('');
|
|
22362
|
+
const { addCoupon, removeCoupon, isAddingCoupon, isRemovingCoupon, activeCouponsExist } = useUpdateCoupons({
|
|
22190
22363
|
apiHost,
|
|
22191
22364
|
token,
|
|
22192
|
-
|
|
22193
|
-
|
|
22194
|
-
|
|
22195
|
-
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = reactQuery.useQuery({
|
|
22196
|
-
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
22197
|
-
queryFn: () => getTaxationRequiredAccountFields({ apiHost, token }),
|
|
22198
|
-
enabled: Boolean(quote),
|
|
22199
|
-
staleTime: 0,
|
|
22200
|
-
});
|
|
22201
|
-
const { data: account, isLoading: isLoadingAccount } = reactQuery.useQuery({
|
|
22202
|
-
queryKey: ['account', quote === null || quote === void 0 ? void 0 : quote.accountId],
|
|
22203
|
-
queryFn: () => (quote === null || quote === void 0 ? void 0 : quote.accountId) &&
|
|
22204
|
-
common.getAccount({ id: quote.accountId, apiHost, token, componentsVersion: PACKAGE_VERSION }),
|
|
22205
|
-
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
22206
|
-
});
|
|
22207
|
-
async function recalculateTaxes() {
|
|
22208
|
-
if (quote) {
|
|
22209
|
-
if (!quote.id)
|
|
22365
|
+
quoteChangeId: (_d = (_c = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a[((_b = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _b === void 0 ? void 0 : _b.length) - 1]) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : undefined,
|
|
22366
|
+
onCouponAdded: () => {
|
|
22367
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
22210
22368
|
throw new Error('Quote ID is required');
|
|
22211
|
-
|
|
22212
|
-
|
|
22213
|
-
|
|
22214
|
-
|
|
22215
|
-
|
|
22216
|
-
|
|
22217
|
-
|
|
22218
|
-
|
|
22219
|
-
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
|
|
22248
|
-
|
|
22249
|
-
|
|
22250
|
-
|
|
22251
|
-
|
|
22252
|
-
await recalculateTaxes();
|
|
22253
|
-
}
|
|
22254
|
-
} })) : (jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess }))] }), jsxRuntime.jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
22255
|
-
};
|
|
22256
|
-
|
|
22257
|
-
const QuoteContext = react.createContext({});
|
|
22258
|
-
|
|
22259
|
-
const { Text: Text$n } = antd.Typography;
|
|
22260
|
-
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
22261
|
-
var _a;
|
|
22262
|
-
const [isTooltipOpen, setIsTooltipOpen] = react.useState(false);
|
|
22263
|
-
const isMobile = common.useIsMobile();
|
|
22264
|
-
react.useEffect(() => {
|
|
22265
|
-
setTimeout(() => {
|
|
22266
|
-
setIsTooltipOpen(true);
|
|
22267
|
-
}, 1000);
|
|
22268
|
-
setTimeout(() => {
|
|
22269
|
-
setIsTooltipOpen(false);
|
|
22270
|
-
}, 6000);
|
|
22271
|
-
}, []);
|
|
22272
|
-
return (jsxRuntime.jsxs(Text$n, { className: `bunny-flex bunny-items-center bunny-gap-2 ${isMobile ? 'bunny-justify-between' : ''}`, children: [jsxRuntime.jsx(QuantityLabel, { activeCharge: priceListCharge }), jsxRuntime.jsx(antd.Tooltip, { onOpenChange: setIsTooltipOpen, open: isTooltipOpen, title: "Change quantity here", styles: {
|
|
22273
|
-
body: {
|
|
22274
|
-
paddingTop: '0.75rem',
|
|
22275
|
-
paddingBottom: '0.75rem',
|
|
22276
|
-
},
|
|
22277
|
-
}, children: jsxRuntime.jsx(antd.Input, { id: `${(_a = priceListCharge.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().replace(/ /g, '-')}-quantity-input`, className: isMobile ? 'text-right' : '', disabled: disabled, onChange: e => {
|
|
22278
|
-
onQuantityChanged(Number(e.target.value));
|
|
22279
|
-
}, min: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMin, max: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMax, style: { minWidth: '120px' }, type: "number", value: quantity, required: true }) })] }));
|
|
22280
|
-
};
|
|
22281
|
-
const QuantityLabel = ({ activeCharge }) => {
|
|
22282
|
-
const chargeName = activeCharge.name;
|
|
22283
|
-
return (jsxRuntime.jsx(Text$n, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
22284
|
-
};
|
|
22285
|
-
|
|
22286
|
-
const periodMonthsConverter = (period) => {
|
|
22287
|
-
if (period === 0)
|
|
22288
|
-
return graphql.scalar('BillingPeriod', 'ONCE');
|
|
22289
|
-
else if (period === 1)
|
|
22290
|
-
return graphql.scalar('BillingPeriod', 'MONTHLY');
|
|
22291
|
-
else if (period === 3)
|
|
22292
|
-
return graphql.scalar('BillingPeriod', 'QUARTERLY');
|
|
22293
|
-
else if (period === 6)
|
|
22294
|
-
return graphql.scalar('BillingPeriod', 'SEMI_ANNUAL');
|
|
22295
|
-
else if (period === 12)
|
|
22296
|
-
return graphql.scalar('BillingPeriod', 'ANNUAL');
|
|
22297
|
-
else
|
|
22298
|
-
return null;
|
|
22299
|
-
};
|
|
22300
|
-
const billingPeriodConverter = (period) => {
|
|
22301
|
-
if (period === graphql.scalar('BillingPeriod', 'ONCE'))
|
|
22302
|
-
return 0;
|
|
22303
|
-
else if (period === graphql.scalar('BillingPeriod', 'MONTHLY'))
|
|
22304
|
-
return 1;
|
|
22305
|
-
else if (period === graphql.scalar('BillingPeriod', 'QUARTERLY'))
|
|
22306
|
-
return 3;
|
|
22307
|
-
else if (period === graphql.scalar('BillingPeriod', 'SEMI_ANNUAL'))
|
|
22308
|
-
return 6;
|
|
22309
|
-
else
|
|
22310
|
-
return 12;
|
|
22311
|
-
};
|
|
22312
|
-
|
|
22313
|
-
function getAddonsForBillingPeriod(billingPeriod, addonPlans) {
|
|
22314
|
-
const flattenedPriceLists = addonPlans.flatMap(addonPlan => addonPlan.priceLists);
|
|
22315
|
-
return flattenedPriceLists.filter(priceList => priceList.periodMonths === billingPeriodConverter(billingPeriod));
|
|
22316
|
-
}
|
|
22317
|
-
|
|
22318
|
-
const hasUnpurchasedAddonPriceLists_PlanFragment = t(`
|
|
22319
|
-
fragment hasUnpurchasedAddonPriceLists_PlanFragment on Plan {
|
|
22320
|
-
priceLists {
|
|
22321
|
-
id
|
|
22322
|
-
isVisible
|
|
22323
|
-
periodMonths
|
|
22324
|
-
}
|
|
22325
|
-
}
|
|
22326
|
-
`);
|
|
22327
|
-
function hasUnpurchasedAddonPriceLists(maskedPriceListAddonPlans, currentSubscription, billingPeriod) {
|
|
22328
|
-
// Read fragments
|
|
22329
|
-
const priceListAddonPlans = maskedPriceListAddonPlans.map(maskedAddonPlan => readFragment(hasUnpurchasedAddonPriceLists_PlanFragment, maskedAddonPlan));
|
|
22330
|
-
const addonPriceLists = getAddonsForBillingPeriod(billingPeriod, priceListAddonPlans).filter(priceList => priceList.isVisible);
|
|
22331
|
-
const unpurchasedAddonPriceLists = addonPriceLists === null || addonPriceLists === void 0 ? void 0 : addonPriceLists.filter(addonPriceList => {
|
|
22332
|
-
var _a;
|
|
22333
|
-
return !((_a = currentSubscription === null || currentSubscription === void 0 ? void 0 : currentSubscription.addonSubscriptions) === null || _a === void 0 ? void 0 : _a.some(addonSubscription => addonSubscription.priceList.id === addonPriceList.id));
|
|
22334
|
-
});
|
|
22335
|
-
return unpurchasedAddonPriceLists.length > 0;
|
|
22336
|
-
}
|
|
22337
|
-
|
|
22338
|
-
const canSubscriptionUpgradeFromTrial = (subscription) => {
|
|
22339
|
-
var _a;
|
|
22340
|
-
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL') &&
|
|
22341
|
-
subscription.plan.selfServiceBuy) ||
|
|
22342
|
-
false;
|
|
22343
|
-
};
|
|
22344
|
-
const canSubscriptionUpgradeFromTrialExpired = (subscription) => {
|
|
22345
|
-
var _a;
|
|
22346
|
-
return (((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED') &&
|
|
22347
|
-
subscription.plan.selfServiceBuy) ||
|
|
22348
|
-
false;
|
|
22349
|
-
};
|
|
22350
|
-
const isSubscriptionNotActive = (subscription) => {
|
|
22351
|
-
var _a, _b, _c;
|
|
22352
|
-
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'EXPIRED') ||
|
|
22353
|
-
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'CANCELED') ||
|
|
22354
|
-
((_c = subscription.state) === null || _c === void 0 ? void 0 : _c.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED');
|
|
22355
|
-
};
|
|
22356
|
-
const isSubscriptionActiveOrPending = (subscription) => {
|
|
22357
|
-
var _a, _b;
|
|
22358
|
-
return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'ACTIVE') ||
|
|
22359
|
-
((_b = subscription.state) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === t.scalar('SubscriptionState', 'PENDING');
|
|
22360
|
-
};
|
|
22361
|
-
const isSubscriptionTrial = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL'); };
|
|
22362
|
-
const isSubscriptionTrialExpired = (subscription) => { var _a; return ((_a = subscription.state) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === t.scalar('SubscriptionState', 'TRIAL_EXPIRED'); };
|
|
22363
|
-
// Helper function to check if charge is a discount
|
|
22364
|
-
const isDiscount$1 = (kind) => kind === common.QuoteChangeKind.DISCOUNT || kind === common.QuoteChangeKind.FREE_PERIOD_DISCOUNT;
|
|
22365
|
-
const hasPriceTiers = (charge) => {
|
|
22366
|
-
var _a;
|
|
22367
|
-
return Boolean((_a = charge === null || charge === void 0 ? void 0 : charge.priceTiers) === null || _a === void 0 ? void 0 : _a.length);
|
|
22368
|
-
};
|
|
22369
|
-
|
|
22370
|
-
const removeHTMLTagsRegex = /<br>(?=(?:\s*<[^>]*>)*$)|(<br>)|<[^>]*>/gi;
|
|
22371
|
-
// Description is a string that can contain HTML tags. We want to remove all HTML tags except <br> tags.
|
|
22372
|
-
const createPlanDescription = (planDescription) => {
|
|
22373
|
-
return (planDescription || '').replace(removeHTMLTagsRegex, (_, y) => (y ? ' & ' : ''));
|
|
22374
|
-
};
|
|
22375
|
-
const getActivePlanPriceData = (priceList, selectedPriceList) => {
|
|
22376
|
-
if (!priceList) {
|
|
22377
|
-
return;
|
|
22378
|
-
}
|
|
22379
|
-
// If a period option is selected, return the charge that matches the selected period option
|
|
22380
|
-
let activeBillingPLCharge;
|
|
22381
|
-
// Default to first price list charge
|
|
22382
|
-
let lowestPLCharge;
|
|
22383
|
-
// Find the lowest price list charge with a billing period that matches the selected period option
|
|
22384
|
-
if (priceList.id === (selectedPriceList === null || selectedPriceList === void 0 ? void 0 : selectedPriceList.id)) {
|
|
22385
|
-
activeBillingPLCharge = priceList.charges[0];
|
|
22386
|
-
}
|
|
22387
|
-
for (let j = 0; j < priceList.charges.length; j++) {
|
|
22388
|
-
const charge = priceList.charges[j];
|
|
22389
|
-
if (charge.chargeType === common.ChargeType.USAGE || charge.featureAddon === true)
|
|
22390
|
-
continue;
|
|
22391
|
-
if (activeBillingPLCharge) {
|
|
22392
|
-
// If we already found a charge with the same billing period check if this charge is lower
|
|
22393
|
-
if (charge.basePrice < activeBillingPLCharge.basePrice &&
|
|
22394
|
-
charge.billingPeriod === (activeBillingPLCharge === null || activeBillingPLCharge === void 0 ? void 0 : activeBillingPLCharge.billingPeriod)) {
|
|
22395
|
-
activeBillingPLCharge = charge;
|
|
22396
|
-
}
|
|
22397
|
-
}
|
|
22398
|
-
// If a period option is selected, only return the charge if it matches the selected period option
|
|
22399
|
-
else if (selectedPriceList &&
|
|
22400
|
-
charge.billingPeriod === periodMonthsConverter(selectedPriceList.periodMonths)) {
|
|
22401
|
-
activeBillingPLCharge = charge;
|
|
22402
|
-
}
|
|
22403
|
-
// Otherwise, return the lowest price list charge
|
|
22404
|
-
else if (charge.basePrice < ((lowestPLCharge === null || lowestPLCharge === void 0 ? void 0 : lowestPLCharge.basePrice) || -1)) {
|
|
22405
|
-
lowestPLCharge = charge;
|
|
22406
|
-
}
|
|
22407
|
-
}
|
|
22408
|
-
return {
|
|
22409
|
-
activeCharge: activeBillingPLCharge || lowestPLCharge,
|
|
22410
|
-
};
|
|
22411
|
-
};
|
|
22412
|
-
const showErrorNotification$2 = common.useErrorNotification();
|
|
22413
|
-
const isPriceListDisabled = ({ priceList, upgradingSubscription, }) => {
|
|
22414
|
-
const priceListAddonPlans = priceList === null || priceList === void 0 ? void 0 : priceList.plan.addonPlans;
|
|
22415
|
-
if (!priceListAddonPlans) {
|
|
22416
|
-
showErrorNotification$2('Price list addon plans are undefined');
|
|
22417
|
-
return false;
|
|
22418
|
-
}
|
|
22419
|
-
const canPurchaseFeatureAddons = hasUnpurchasedFeatureAddons(priceList, upgradingSubscription);
|
|
22420
|
-
const canPurchasePlanAddons = hasUnpurchasedAddonPriceLists(priceListAddonPlans, upgradingSubscription, periodMonthsConverter(priceList.periodMonths));
|
|
22421
|
-
const existingSubscriptionInTrial = upgradingSubscription && canSubscriptionUpgradeFromTrial(upgradingSubscription);
|
|
22422
|
-
const existingSubscriptionInTrialExpired = upgradingSubscription && canSubscriptionUpgradeFromTrialExpired(upgradingSubscription);
|
|
22423
|
-
const isUpgradingSubscriptionPriceList = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id) === priceList.id;
|
|
22424
|
-
// When should priceList be disabled?
|
|
22425
|
-
// if upgradingSubscription?.priceList.id === priceList.id
|
|
22426
|
-
// AND the upgradingSubscription is not in trial
|
|
22427
|
-
// AND cannot purchase feature addons
|
|
22428
|
-
// AND cannot purchase add-on plans
|
|
22429
|
-
// AND selfServiceBuy is false
|
|
22430
|
-
// if upgradingSubscription?.priceList.id != priceList.id
|
|
22431
|
-
// AND upgradingSubscription is expired trial
|
|
22432
|
-
if (isUpgradingSubscriptionPriceList) {
|
|
22433
|
-
return (!existingSubscriptionInTrial &&
|
|
22434
|
-
!existingSubscriptionInTrialExpired &&
|
|
22435
|
-
!canPurchaseFeatureAddons &&
|
|
22436
|
-
!canPurchasePlanAddons);
|
|
22437
|
-
}
|
|
22438
|
-
else {
|
|
22439
|
-
return false;
|
|
22369
|
+
queryClient.invalidateQueries({
|
|
22370
|
+
queryKey: common.QueryKeyFactory.default.createObjectKey({
|
|
22371
|
+
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
22372
|
+
objectName: 'editingQuote',
|
|
22373
|
+
token,
|
|
22374
|
+
}),
|
|
22375
|
+
});
|
|
22376
|
+
showSuccessNotification$1('Coupon applied');
|
|
22377
|
+
onRecalculateTaxes();
|
|
22378
|
+
setCouponCode('');
|
|
22379
|
+
},
|
|
22380
|
+
onCouponRemoved: () => {
|
|
22381
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
22382
|
+
throw new Error('Quote ID is required');
|
|
22383
|
+
queryClient.invalidateQueries({
|
|
22384
|
+
queryKey: common.QueryKeyFactory.default.createObjectKey({
|
|
22385
|
+
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
22386
|
+
objectName: 'editingQuote',
|
|
22387
|
+
token,
|
|
22388
|
+
}),
|
|
22389
|
+
});
|
|
22390
|
+
showSuccessNotification$1('Coupon removed');
|
|
22391
|
+
onRecalculateTaxes();
|
|
22392
|
+
},
|
|
22393
|
+
});
|
|
22394
|
+
const couponsOnQuote = (_e = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _e === void 0 ? void 0 : _e.flatMap(quoteChange => { var _a; return (_a = quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges) === null || _a === void 0 ? void 0 : _a.filter(charge => charge.kind === 'COUPON'); });
|
|
22395
|
+
const checkoutMutation = reactQuery.useMutation({
|
|
22396
|
+
mutationFn: async () => {
|
|
22397
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id))
|
|
22398
|
+
throw new Error('Quote ID is required');
|
|
22399
|
+
if (paymentRequired)
|
|
22400
|
+
throw new Error('Payment is required');
|
|
22401
|
+
return await checkout({ quoteId: quote.id, token, apiHost });
|
|
22402
|
+
},
|
|
22403
|
+
onSuccess,
|
|
22404
|
+
onError: onFail,
|
|
22405
|
+
});
|
|
22406
|
+
async function handleCheckoutNoPayment() {
|
|
22407
|
+
setIsSaving(true);
|
|
22408
|
+
checkoutMutation.mutate();
|
|
22409
|
+
setIsSaving(false);
|
|
22440
22410
|
}
|
|
22411
|
+
if (taxationRequiredAccountFields)
|
|
22412
|
+
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: jsxRuntime.jsx(TaxationForm, { account: account, accountId: quote.accountId }) }));
|
|
22413
|
+
return (jsxRuntime.jsx(PaymentFormWrapper, { setMaxHeight: false, children: paymentRequired ? (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-gap-2 bunny-w-full", children: [jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess, quote: quote }), (couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.length) === 0 ? (jsxRuntime.jsx(jsxRuntime.Fragment, { children: upgradingSubscription &&
|
|
22414
|
+
shouldShowCouponEditor(quote, activeCouponsExist, upgradingSubscription) && (jsxRuntime.jsx(CouponEditor, { className: "bunny-px-4 bunny-pt-1", quote: quote, onAddCoupon: addCoupon, isAddingCoupon: isAddingCoupon, couponCode: couponCode, setCouponCode: setCouponCode })) })) : (jsxRuntime.jsx(antd.Button, { type: "link", loading: isRemovingCoupon, onClick: () => {
|
|
22415
|
+
couponsOnQuote === null || couponsOnQuote === void 0 ? void 0 : couponsOnQuote.forEach(couponCharge => {
|
|
22416
|
+
var _a;
|
|
22417
|
+
const couponCode = (_a = couponCharge === null || couponCharge === void 0 ? void 0 : couponCharge.coupon) === null || _a === void 0 ? void 0 : _a.couponCode;
|
|
22418
|
+
if (couponCode) {
|
|
22419
|
+
removeCoupon(couponCode);
|
|
22420
|
+
}
|
|
22421
|
+
});
|
|
22422
|
+
}, children: "Remove coupon(s)" }))] })) : (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-2 bunny-px-4 ${isMobile ? 'bunny-shadow-padding-x' : ''}`, children: [jsxRuntime.jsx(antd.Button, { onClick: handleCheckoutNoPayment, type: "primary", children: isSaving ? 'Processing...' : 'Complete order' }), jsxRuntime.jsx(Text$n, { className: "bunny-text-xs bunny-text-slate-500", children: "No payment is required" })] })) }));
|
|
22441
22423
|
};
|
|
22442
|
-
|
|
22443
|
-
const CheckoutButton = ({ checkoutButtonDisabled, onClickCheckout, loading, tooltipText, }) => {
|
|
22424
|
+
const PaymentFormWrapper = ({ children, setMaxHeight, className, }) => {
|
|
22444
22425
|
const isMobile = common.useIsMobile();
|
|
22445
|
-
|
|
22446
|
-
|
|
22447
|
-
|
|
22448
|
-
|
|
22449
|
-
|
|
22450
|
-
|
|
22451
|
-
|
|
22426
|
+
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-w-full bunny-flex-col bunny-gap-6 ${isMobile ? 'bunny-shadow-padding-xb' : ''} ${className}`, style: {
|
|
22427
|
+
...(isMobile
|
|
22428
|
+
? setMaxHeight
|
|
22429
|
+
? { maxHeight: '60vh' }
|
|
22430
|
+
: {}
|
|
22431
|
+
: {
|
|
22432
|
+
width: '100%',
|
|
22433
|
+
maxWidth: '400px',
|
|
22434
|
+
}),
|
|
22435
|
+
}, children: children }));
|
|
22452
22436
|
};
|
|
22453
22437
|
|
|
22454
|
-
const
|
|
22438
|
+
const queryKeyFactory = common.QueryKeyFactory.default;
|
|
22439
|
+
const Checkout_QuoteFragment = t(`
|
|
22440
|
+
fragment Checkout_QuoteFragment on Quote {
|
|
22441
|
+
id
|
|
22442
|
+
accountId
|
|
22443
|
+
formattedQuote {
|
|
22444
|
+
html
|
|
22445
|
+
}
|
|
22446
|
+
...QuoteCheckout_QuoteFragment
|
|
22447
|
+
}
|
|
22448
|
+
`, [QuoteCheckout_QuoteFragment]);
|
|
22449
|
+
const Checkout = ({ onCancel, onSuccess, onFail, onRecalculateTaxes, invoice, open, quote: maskedQuote, isUpdatingQuote, }) => {
|
|
22450
|
+
var _a, _b, _c, _d, _e;
|
|
22451
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
22455
22452
|
const isMobile = common.useIsMobile();
|
|
22456
|
-
|
|
22453
|
+
const token = useToken();
|
|
22454
|
+
// Read fragments
|
|
22455
|
+
const quote = readFragment(Checkout_QuoteFragment, maskedQuote);
|
|
22456
|
+
const hasTaxPlugin = useHasTaxPlugin({
|
|
22457
|
+
apiHost,
|
|
22458
|
+
token,
|
|
22459
|
+
});
|
|
22460
|
+
// Queries
|
|
22461
|
+
const { data: taxationRequiredAccountFields, isLoading: isLoadingTaxationRequiredAccountFields } = reactQuery.useQuery({
|
|
22462
|
+
queryKey: ['getTaxationRequiredAccountFields', token],
|
|
22463
|
+
queryFn: () => getTaxationRequiredAccountFields({ apiHost, token }),
|
|
22464
|
+
enabled: Boolean(quote),
|
|
22465
|
+
staleTime: 0,
|
|
22466
|
+
});
|
|
22467
|
+
const { data: account, isLoading: isLoadingAccount } = reactQuery.useQuery({
|
|
22468
|
+
queryKey: ['account', quote === null || quote === void 0 ? void 0 : quote.accountId],
|
|
22469
|
+
queryFn: () => (quote === null || quote === void 0 ? void 0 : quote.accountId) &&
|
|
22470
|
+
common.getAccount({ id: quote.accountId, apiHost, token, componentsVersion: PACKAGE_VERSION }),
|
|
22471
|
+
enabled: Boolean(quote === null || quote === void 0 ? void 0 : quote.accountId) && ((taxationRequiredAccountFields === null || taxationRequiredAccountFields === void 0 ? void 0 : taxationRequiredAccountFields.length) || 0) > 0,
|
|
22472
|
+
});
|
|
22473
|
+
// Use onRecalculateTaxes callback because parents need to define recalculateTaxes to get and set the right quote data they need
|
|
22474
|
+
async function recalculateTaxes() {
|
|
22475
|
+
if (quote) {
|
|
22476
|
+
if (!quote.id)
|
|
22477
|
+
throw new Error('Quote ID is required');
|
|
22478
|
+
onRecalculateTaxes(quote.id);
|
|
22479
|
+
}
|
|
22480
|
+
return {};
|
|
22481
|
+
}
|
|
22482
|
+
const recalculateTaxesEnabled = Boolean(quote) &&
|
|
22483
|
+
open &&
|
|
22484
|
+
hasTaxPlugin &&
|
|
22485
|
+
!taxationRequiredAccountFields &&
|
|
22486
|
+
!isLoadingTaxationRequiredAccountFields &&
|
|
22487
|
+
!isUpdatingQuote;
|
|
22488
|
+
reactQuery.useQuery({
|
|
22489
|
+
queryKey: queryKeyFactory.createQuoteTaxCalculateKey({
|
|
22490
|
+
id: (_a = quote === null || quote === void 0 ? void 0 : quote.id) !== null && _a !== void 0 ? _a : undefined,
|
|
22491
|
+
token,
|
|
22492
|
+
}),
|
|
22493
|
+
queryFn: recalculateTaxes,
|
|
22494
|
+
// Recalculate taxes if the quote is open, has a tax plugin, and the taxation required account fields are not required
|
|
22495
|
+
enabled: recalculateTaxesEnabled,
|
|
22496
|
+
staleTime: 0,
|
|
22497
|
+
});
|
|
22498
|
+
if (!open || isLoadingTaxationRequiredAccountFields || isLoadingAccount)
|
|
22457
22499
|
return null;
|
|
22458
|
-
|
|
22459
|
-
|
|
22460
|
-
|
|
22461
|
-
|
|
22462
|
-
|
|
22463
|
-
|
|
22464
|
-
|
|
22500
|
+
return (jsxRuntime.jsx("div", { className: `bunny-flex bunny-flex-col bunny-fixed bunny-top-0 bunny-left-0 bunny-right-0 bunny-bottom-0 bunny-bg-slate-50
|
|
22501
|
+
bunny-overflow-auto bunny-height-full`, style: {
|
|
22502
|
+
zIndex: 1001,
|
|
22503
|
+
}, children: jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-grow bunny-pt-4 ${isMobile ? 'bunny-pb-4' : 'bunny-pb-8'} bunny-content-container`, children: [jsxRuntime.jsx("div", { className: "bunny-flex bunny-justify-end bunny-w-full bunny-pr-4", children: jsxRuntime.jsx(icons.CloseOutlined, { className: "bunny-text-base bunny-shadow-padding-xb", onClick: onCancel }) }), jsxRuntime.jsxs("div", { className: `bunny-flex bunny-justify-end bunny-pt-4 bunny-gap-4 ${isMobile ? 'bunny-flex-col' : 'bunny-shadow-padding-xb'}`, children: [((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_b = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _b === void 0 ? void 0 : _b.html)) && (jsxRuntime.jsx(InvoiceQuoteView, { html: invoice ? invoice.html : (_d = (_c = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _c === void 0 ? void 0 : _c.html) !== null && _d !== void 0 ? _d : '' })), !isMobile && ((invoice === null || invoice === void 0 ? void 0 : invoice.html) || ((_e = quote === null || quote === void 0 ? void 0 : quote.formattedQuote) === null || _e === void 0 ? void 0 : _e.html)) && (jsxRuntime.jsx(antd.Divider, { className: "bunny-h-full", type: "vertical" })), invoice ? (jsxRuntime.jsx("div", { className: "bunny-w-full bunny-pt-12", children: jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess, invoice: invoice }) })) : quote ? (jsxRuntime.jsx(QuoteCheckout, { account: account, onFail: error => {
|
|
22504
|
+
onFail(error);
|
|
22505
|
+
}, onSuccess: onSuccess, quote: quote, taxationRequiredAccountFields: taxationRequiredAccountFields, token: token, onRecalculateTaxes: async () => {
|
|
22506
|
+
if (recalculateTaxesEnabled) {
|
|
22507
|
+
await recalculateTaxes();
|
|
22508
|
+
}
|
|
22509
|
+
} })) : (jsxRuntime.jsx(PaymentForm, { onPaymentSuccess: onSuccess }))] }), jsxRuntime.jsx(Footer, { className: "bunny-px-12" })] }) }));
|
|
22465
22510
|
};
|
|
22466
22511
|
|
|
22512
|
+
function canEditChargeQuantity(charge) {
|
|
22513
|
+
if (!charge)
|
|
22514
|
+
return false;
|
|
22515
|
+
if (charge.chargeType === graphql.scalar('ChargeType', 'USAGE'))
|
|
22516
|
+
return false;
|
|
22517
|
+
if (charge.pricingModel === graphql.scalar('PricingModel', 'FLAT'))
|
|
22518
|
+
return false;
|
|
22519
|
+
return true;
|
|
22520
|
+
}
|
|
22521
|
+
|
|
22467
22522
|
const { Text: Text$m } = antd.Typography;
|
|
22468
|
-
const
|
|
22523
|
+
const CheckoutBarInput = ({ disabled, priceListCharge, quantity, onQuantityChanged, }) => {
|
|
22469
22524
|
var _a;
|
|
22470
|
-
|
|
22471
|
-
const { quote: quoteData, isQuotePending, isUpdatingQuote } = react.useContext(QuoteContext);
|
|
22472
|
-
const quote = quoteData;
|
|
22473
|
-
const { upgradingSubscription, isInPreviewMode } = react.useContext(SubscriptionsContext);
|
|
22474
|
-
// Hooks
|
|
22475
|
-
const token = useToken();
|
|
22476
|
-
const { paymentPlugins } = usePaymentPlugins(undefined);
|
|
22477
|
-
const queryClient = reactQuery.useQueryClient();
|
|
22525
|
+
const [isTooltipOpen, setIsTooltipOpen] = react.useState(false);
|
|
22478
22526
|
const isMobile = common.useIsMobile();
|
|
22479
|
-
|
|
22480
|
-
|
|
22481
|
-
|
|
22482
|
-
|
|
22483
|
-
|
|
22484
|
-
|
|
22485
|
-
|
|
22486
|
-
|
|
22487
|
-
|
|
22488
|
-
|
|
22489
|
-
|
|
22490
|
-
|
|
22491
|
-
|
|
22492
|
-
|
|
22493
|
-
|
|
22494
|
-
|
|
22495
|
-
|
|
22496
|
-
|
|
22497
|
-
|
|
22498
|
-
|
|
22527
|
+
react.useEffect(() => {
|
|
22528
|
+
setTimeout(() => {
|
|
22529
|
+
setIsTooltipOpen(true);
|
|
22530
|
+
}, 1000);
|
|
22531
|
+
setTimeout(() => {
|
|
22532
|
+
setIsTooltipOpen(false);
|
|
22533
|
+
}, 6000);
|
|
22534
|
+
}, []);
|
|
22535
|
+
return (jsxRuntime.jsxs(Text$m, { className: `bunny-flex bunny-items-center bunny-gap-2 ${isMobile ? 'bunny-justify-between' : ''}`, children: [jsxRuntime.jsx(QuantityLabel, { activeCharge: priceListCharge }), jsxRuntime.jsx(antd.Tooltip, { onOpenChange: setIsTooltipOpen, open: isTooltipOpen, title: "Change quantity here", styles: {
|
|
22536
|
+
body: {
|
|
22537
|
+
paddingTop: '0.75rem',
|
|
22538
|
+
paddingBottom: '0.75rem',
|
|
22539
|
+
},
|
|
22540
|
+
}, children: jsxRuntime.jsx(antd.Input, { id: `${(_a = priceListCharge.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().replace(/ /g, '-')}-quantity-input`, className: isMobile ? 'text-right' : '', disabled: disabled, onChange: e => {
|
|
22541
|
+
onQuantityChanged(Number(e.target.value));
|
|
22542
|
+
}, min: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMin, max: priceListCharge === null || priceListCharge === void 0 ? void 0 : priceListCharge.quantityMax, style: { minWidth: '120px' }, type: "number", value: quantity, required: true }) })] }));
|
|
22543
|
+
};
|
|
22544
|
+
const QuantityLabel = ({ activeCharge }) => {
|
|
22545
|
+
const chargeName = activeCharge.name;
|
|
22546
|
+
return (jsxRuntime.jsx(Text$m, { className: "bunny-text-slate-500 bunny-font-medium bunny-text-nowrap", style: { fontSize: '11px' }, children: chargeName.toUpperCase() }));
|
|
22499
22547
|
};
|
|
22500
22548
|
|
|
22501
22549
|
const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
@@ -22515,8 +22563,8 @@ const PlanPickerCheckoutBar_QuoteFragment = t(`
|
|
|
22515
22563
|
`, [Checkout_QuoteFragment]);
|
|
22516
22564
|
const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onCheckoutSuccess, }) => {
|
|
22517
22565
|
// Context
|
|
22518
|
-
const { shadow
|
|
22519
|
-
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, isFeatureAddonsLoading, isUpdatingQuote, } = react.useContext(QuoteContext);
|
|
22566
|
+
const { shadow } = react.useContext(SubscriptionsContext);
|
|
22567
|
+
const { quote: maskedQuote, onChangeQuantity, getFeatureQuantity, onRecalculateTaxes, isFeatureAddonsLoading, isUpdatingQuote, } = react.useContext(QuoteContext);
|
|
22520
22568
|
// Read fragments
|
|
22521
22569
|
const quote = readFragment(PlanPickerCheckoutBar_QuoteFragment, maskedQuote);
|
|
22522
22570
|
// Local state
|
|
@@ -22564,9 +22612,6 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22564
22612
|
const isFeatureAddon = charge.featureAddon;
|
|
22565
22613
|
const quantity = getFeatureQuantity((_d = charge.feature) === null || _d === void 0 ? void 0 : _d.id, charge.id);
|
|
22566
22614
|
const maybeIsChargeLoading = isFeatureAddon && isFeatureAddonsLoading;
|
|
22567
|
-
const showInput = selectedPriceList.id !== (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.id);
|
|
22568
|
-
if (!isFeatureAddon && !showInput)
|
|
22569
|
-
return null;
|
|
22570
22615
|
if (!quantity)
|
|
22571
22616
|
return null;
|
|
22572
22617
|
// if charge is a feature addon, and a corresponding quote charge is not found in quote, return null
|
|
@@ -22577,9 +22622,40 @@ const PlanPickerCheckoutBar = ({ selectedPriceList, handlePortalErrors, onChecko
|
|
|
22577
22622
|
return (jsxRuntime.jsx(CheckoutBarInput, { disabled: isDisabled, priceListCharge: charge, quantity: quantity, onQuantityChanged: quantity => {
|
|
22578
22623
|
onChangeQuantity(charge.id, quantity);
|
|
22579
22624
|
} }, index));
|
|
22580
|
-
}) }), jsxRuntime.jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true),
|
|
22625
|
+
}) }), jsxRuntime.jsx(CheckoutBarSummarySection, { onClickCheckout: () => setPayModalVisible(true), selectedPriceList: selectedPriceList }), jsxRuntime.jsx(Checkout, { onCancel: () => setPayModalVisible(false), onFail: error => handlePortalErrors === null || handlePortalErrors === void 0 ? void 0 : handlePortalErrors(error), onSuccess: handleCheckoutSuccess, onRecalculateTaxes: onRecalculateTaxes, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: isUpdatingQuote })] }));
|
|
22581
22626
|
};
|
|
22582
22627
|
|
|
22628
|
+
const useQuoteUpdateFeatureAddon_QuoteFragment = t(`
|
|
22629
|
+
fragment useQuoteUpdateFeatureAddon_QuoteFragment on Quote {
|
|
22630
|
+
id
|
|
22631
|
+
startDate
|
|
22632
|
+
}
|
|
22633
|
+
`);
|
|
22634
|
+
|
|
22635
|
+
const FeatureAddonRow_QuoteFragment = t(`
|
|
22636
|
+
fragment FeatureAddonRow_QuoteFragment on Quote {
|
|
22637
|
+
...useQuoteUpdateFeatureAddon_QuoteFragment
|
|
22638
|
+
}
|
|
22639
|
+
`, [useQuoteUpdateFeatureAddon_QuoteFragment]);
|
|
22640
|
+
|
|
22641
|
+
const useToggleAddonPlan_QuoteFragment = t(`
|
|
22642
|
+
fragment useToggleAddonPlan_QuoteFragment on Quote {
|
|
22643
|
+
quoteChanges {
|
|
22644
|
+
priceList {
|
|
22645
|
+
id
|
|
22646
|
+
}
|
|
22647
|
+
id
|
|
22648
|
+
}
|
|
22649
|
+
id
|
|
22650
|
+
}
|
|
22651
|
+
`);
|
|
22652
|
+
|
|
22653
|
+
const AddonPlanRow_QuoteFragment = t(`
|
|
22654
|
+
fragment AddonPlanRow_QuoteFragment on Quote {
|
|
22655
|
+
...useToggleAddonPlan_QuoteFragment
|
|
22656
|
+
}
|
|
22657
|
+
`, [useToggleAddonPlan_QuoteFragment]);
|
|
22658
|
+
|
|
22583
22659
|
/**
|
|
22584
22660
|
* Central quote fragment for QuoteProvider context.
|
|
22585
22661
|
*
|
|
@@ -22597,6 +22673,7 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22597
22673
|
id
|
|
22598
22674
|
currencyId
|
|
22599
22675
|
amountDue
|
|
22676
|
+
startDate
|
|
22600
22677
|
quoteChanges {
|
|
22601
22678
|
id
|
|
22602
22679
|
kind
|
|
@@ -22620,75 +22697,17 @@ const QuoteContext_QuoteFragment = t(`
|
|
|
22620
22697
|
}
|
|
22621
22698
|
}
|
|
22622
22699
|
...PlanPickerCheckoutBar_QuoteFragment
|
|
22623
|
-
|
|
22624
|
-
|
|
22625
|
-
|
|
22626
|
-
|
|
22627
|
-
|
|
22628
|
-
|
|
22629
|
-
|
|
22630
|
-
|
|
22631
|
-
|
|
22632
|
-
|
|
22633
|
-
|
|
22634
|
-
${removeFormattedQuoteField ? '' : `formattedQuote { html }`}
|
|
22635
|
-
id
|
|
22636
|
-
payableId
|
|
22637
|
-
periodAmount
|
|
22638
|
-
subtotal
|
|
22639
|
-
taxAmount
|
|
22640
|
-
startDate
|
|
22641
|
-
amountsByPeriod {
|
|
22642
|
-
amount
|
|
22643
|
-
startDate
|
|
22644
|
-
}
|
|
22645
|
-
kind
|
|
22646
|
-
quoteChanges {
|
|
22647
|
-
currencyId
|
|
22648
|
-
id
|
|
22649
|
-
kind
|
|
22650
|
-
charges {
|
|
22651
|
-
subtotal
|
|
22652
|
-
amountsByPeriod {
|
|
22653
|
-
amount
|
|
22654
|
-
startDate
|
|
22655
|
-
}
|
|
22656
|
-
amount
|
|
22657
|
-
billingPeriod
|
|
22658
|
-
currencyId
|
|
22659
|
-
feature {
|
|
22660
|
-
id
|
|
22661
|
-
unitName
|
|
22662
|
-
}
|
|
22663
|
-
id
|
|
22664
|
-
name
|
|
22665
|
-
priceListCharge {
|
|
22666
|
-
id
|
|
22667
|
-
quantityMax
|
|
22668
|
-
quantityMin
|
|
22669
|
-
selfServiceQuantity
|
|
22670
|
-
}
|
|
22671
|
-
priceList {
|
|
22672
|
-
id
|
|
22673
|
-
}
|
|
22674
|
-
coupon {
|
|
22675
|
-
couponCode
|
|
22676
|
-
}
|
|
22677
|
-
quantity
|
|
22678
|
-
kind
|
|
22679
|
-
}
|
|
22680
|
-
priceList {
|
|
22681
|
-
id
|
|
22682
|
-
plan {
|
|
22683
|
-
name
|
|
22684
|
-
}
|
|
22685
|
-
product {
|
|
22686
|
-
name
|
|
22687
|
-
}
|
|
22688
|
-
}
|
|
22689
|
-
}
|
|
22690
|
-
}
|
|
22691
|
-
`;
|
|
22700
|
+
...CheckoutBarSummarySection_QuoteFragment
|
|
22701
|
+
...AddonPlanRow_QuoteFragment
|
|
22702
|
+
...FeatureAddonRow_QuoteFragment
|
|
22703
|
+
}
|
|
22704
|
+
`, [
|
|
22705
|
+
PlanPickerCheckoutBar_QuoteFragment,
|
|
22706
|
+
CheckoutBarSummarySection_QuoteFragment,
|
|
22707
|
+
AddonPlanRow_QuoteFragment,
|
|
22708
|
+
FeatureAddonRow_QuoteFragment,
|
|
22709
|
+
]);
|
|
22710
|
+
|
|
22692
22711
|
const FormattedQuoteField_QuoteFragment = t(`
|
|
22693
22712
|
fragment FormattedQuoteField_QuoteFragment on Quote {
|
|
22694
22713
|
formattedQuote {
|
|
@@ -22696,7 +22715,7 @@ const FormattedQuoteField_QuoteFragment = t(`
|
|
|
22696
22715
|
}
|
|
22697
22716
|
}
|
|
22698
22717
|
`);
|
|
22699
|
-
const query$
|
|
22718
|
+
const query$5 = t(`
|
|
22700
22719
|
query quote($id: ID, $removeFormattedQuoteField: Boolean!) {
|
|
22701
22720
|
quote(id: $id) {
|
|
22702
22721
|
...QuoteContext_QuoteFragment
|
|
@@ -22705,7 +22724,7 @@ const query$3 = t(`
|
|
|
22705
22724
|
}
|
|
22706
22725
|
`, [QuoteContext_QuoteFragment, FormattedQuoteField_QuoteFragment]);
|
|
22707
22726
|
const getQuote$1 = async ({ id, token, apiHost, removeFormattedQuoteField = false, }) => {
|
|
22708
|
-
const response = await execute(query$
|
|
22727
|
+
const response = await execute(query$5, { apiHost, token }, { id, removeFormattedQuoteField });
|
|
22709
22728
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
22710
22729
|
};
|
|
22711
22730
|
|
|
@@ -22810,7 +22829,7 @@ function Signup({ companyName, priceListCode, returnUrl, couponCode, className,
|
|
|
22810
22829
|
});
|
|
22811
22830
|
const { mutate: recalculateTaxesMutation } = reactQuery.useMutation({
|
|
22812
22831
|
mutationFn: (quoteId) => {
|
|
22813
|
-
return quoteRecalculateTaxes({ token, apiHost, quoteId });
|
|
22832
|
+
return quoteRecalculateTaxes$2({ token, apiHost, quoteId });
|
|
22814
22833
|
},
|
|
22815
22834
|
onError: (error) => {
|
|
22816
22835
|
if (!error[0].message.includes('Ensure that you have a taxation plugin')) {
|
|
@@ -22991,7 +23010,7 @@ const useQuoteQueryData = (quoteId) => {
|
|
|
22991
23010
|
return data;
|
|
22992
23011
|
};
|
|
22993
23012
|
|
|
22994
|
-
const useSetQuoteQueryData = () => {
|
|
23013
|
+
const useSetQuoteQueryData$1 = () => {
|
|
22995
23014
|
const token = useToken();
|
|
22996
23015
|
const queryClient = reactQuery.useQueryClient();
|
|
22997
23016
|
const setQuoteQueryData = (quoteId, quote) => {
|
|
@@ -23030,6 +23049,9 @@ const QuantityInput_QuoteFragment = t(`
|
|
|
23030
23049
|
}
|
|
23031
23050
|
`, []);
|
|
23032
23051
|
|
|
23052
|
+
const useQuoteIsLoadingState = (isLoading) => react.useState(isLoading !== null && isLoading !== void 0 ? isLoading : false);
|
|
23053
|
+
const [QuoteIsLoadingProvider, useQuoteIsLoading] = createStateContext(useQuoteIsLoadingState);
|
|
23054
|
+
|
|
23033
23055
|
const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
23034
23056
|
fragment QuoteChangeSummarySection_QuoteFragment on Quote {
|
|
23035
23057
|
id
|
|
@@ -23041,10 +23063,11 @@ const QuoteChangeSummarySection_QuoteFragment = t(`
|
|
|
23041
23063
|
const QuoteChangeSummarySection = ({ openCheckout, errorUpdatingQuantity, }) => {
|
|
23042
23064
|
const isMobile = common.useIsMobile();
|
|
23043
23065
|
const [quoteId] = useQuoteId();
|
|
23066
|
+
const [isQuoteLoading] = useQuoteIsLoading();
|
|
23044
23067
|
const maskedQuote = useQuoteQueryData(quoteId);
|
|
23045
23068
|
const quote = readFragment(QuoteChangeSummarySection_QuoteFragment, maskedQuote);
|
|
23046
|
-
const disabled = !quoteId || !quote || errorUpdatingQuantity;
|
|
23047
|
-
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: [quote && !disabled && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-mb-8", children: [jsxRuntime.jsx("div", { className: "bunny-text-slate-500 bunny-text-right bunny-text-xs bunny-mb-2", children: "TOTAL" }), jsxRuntime.jsx("div", { className: `bunny-text-right ${isMobile ? 'bunny-text-2xl' : 'bunny-text-xl'}`, children: common.formatCurrency(getQuoteAmountDue(quote), (quote === null || quote === void 0 ? void 0 : quote.currencyId) || '') })] })), jsxRuntime.jsx("div", { className: `bunny-flex bunny-items-center bunny-justify-end ${isMobile ? 'bunny-w-full' : ''}`, children: jsxRuntime.jsx(antd.Button, { className: "bunny-w-full", onClick: openCheckout, disabled: disabled, size: isMobile ? 'large' : 'middle', type: "primary", children: "Proceed to checkout" }) })] }));
|
|
23069
|
+
const disabled = !quoteId || !quote || errorUpdatingQuantity || isQuoteLoading;
|
|
23070
|
+
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-items-end", children: [quote && !disabled && (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-col bunny-mb-8", children: [jsxRuntime.jsx("div", { className: "bunny-text-slate-500 bunny-text-right bunny-text-xs bunny-mb-2", children: "TOTAL" }), jsxRuntime.jsx("div", { className: `bunny-text-right ${isMobile ? 'bunny-text-2xl' : 'bunny-text-xl'}`, children: common.formatCurrency(getQuoteAmountDue(quote), (quote === null || quote === void 0 ? void 0 : quote.currencyId) || '') })] })), jsxRuntime.jsx("div", { className: `bunny-flex bunny-items-center bunny-justify-end ${isMobile ? 'bunny-w-full' : ''}`, children: jsxRuntime.jsx(antd.Button, { className: "bunny-w-full", onClick: openCheckout, disabled: disabled, size: isMobile ? 'large' : 'middle', type: "primary", loading: isQuoteLoading, children: "Proceed to checkout" }) })] }));
|
|
23048
23071
|
};
|
|
23049
23072
|
|
|
23050
23073
|
const QuantityDrawer_QuoteFragment = t(`
|
|
@@ -23056,7 +23079,7 @@ const QuantityDrawer_QuoteFragment = t(`
|
|
|
23056
23079
|
}
|
|
23057
23080
|
`, [Checkout_QuoteFragment, QuantityInput_QuoteFragment, QuoteChangeSummarySection_QuoteFragment]);
|
|
23058
23081
|
|
|
23059
|
-
const mutation$
|
|
23082
|
+
const mutation$c = t(`
|
|
23060
23083
|
mutation QuoteChargeCreate(
|
|
23061
23084
|
$quoteChangeId: ID!
|
|
23062
23085
|
$startDate: ISO8601Date!
|
|
@@ -23091,11 +23114,11 @@ const mutation$4 = t(`
|
|
|
23091
23114
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23092
23115
|
const quoteChargeCreate$1 = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
23093
23116
|
var _a;
|
|
23094
|
-
const response = await execute(mutation$
|
|
23117
|
+
const response = await execute(mutation$c, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
23095
23118
|
return (_a = response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
23096
23119
|
};
|
|
23097
23120
|
|
|
23098
|
-
const mutation$
|
|
23121
|
+
const mutation$b = t(`
|
|
23099
23122
|
mutation QuoteChargeUpdate($quoteChargeId: ID!, $quantity: Int) {
|
|
23100
23123
|
quoteChargeUpdate(quoteChargeId: $quoteChargeId, quantity: $quantity) {
|
|
23101
23124
|
quoteCharge {
|
|
@@ -23114,14 +23137,29 @@ const mutation$3 = t(`
|
|
|
23114
23137
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23115
23138
|
const quoteChargeUpdate = async (quoteChargeId, quantity, apiHost, token) => {
|
|
23116
23139
|
var _a, _b;
|
|
23117
|
-
const response = await execute(mutation$
|
|
23140
|
+
const response = await execute(mutation$b, { apiHost, token }, { quoteChargeId, quantity });
|
|
23118
23141
|
if ((_a = response.quoteChargeUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23119
23142
|
throw new Error(response.quoteChargeUpdate.errors[0]);
|
|
23120
23143
|
}
|
|
23121
23144
|
return (_b = response.quoteChargeUpdate) === null || _b === void 0 ? void 0 : _b.quoteCharge;
|
|
23122
23145
|
};
|
|
23123
23146
|
|
|
23124
|
-
const mutation$
|
|
23147
|
+
const mutation$a = t(`
|
|
23148
|
+
mutation QuoteDelete($id: ID!) {
|
|
23149
|
+
quoteDelete(id: $id) {
|
|
23150
|
+
errors
|
|
23151
|
+
quote {
|
|
23152
|
+
id
|
|
23153
|
+
}
|
|
23154
|
+
}
|
|
23155
|
+
}
|
|
23156
|
+
`, []);
|
|
23157
|
+
const quoteDelete = async ({ id, token, apiHost }) => {
|
|
23158
|
+
const response = await execute(mutation$a, { apiHost, token }, { id });
|
|
23159
|
+
return response.quoteDelete;
|
|
23160
|
+
};
|
|
23161
|
+
|
|
23162
|
+
const mutation$9 = t(`
|
|
23125
23163
|
mutation quoteSubscriptionUpdate($subscriptionIds: [ID!]!) {
|
|
23126
23164
|
quoteSubscriptionUpdate(subscriptionIds: $subscriptionIds) {
|
|
23127
23165
|
quote {
|
|
@@ -23150,7 +23188,7 @@ const mutation$2 = t(`
|
|
|
23150
23188
|
`, [QuantityDrawer_QuoteFragment]);
|
|
23151
23189
|
const quoteSubscriptionUpdate = async (subscriptionIds, apiHost, token) => {
|
|
23152
23190
|
var _a, _b;
|
|
23153
|
-
const response = await execute(mutation$
|
|
23191
|
+
const response = await execute(mutation$9, { apiHost, token }, { subscriptionIds });
|
|
23154
23192
|
if ((_a = response.quoteSubscriptionUpdate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
23155
23193
|
throw new Error(response.quoteSubscriptionUpdate.errors[0]);
|
|
23156
23194
|
}
|
|
@@ -23219,6 +23257,23 @@ const canShowChangeQuantities = ({ subscriptions, }) => {
|
|
|
23219
23257
|
});
|
|
23220
23258
|
};
|
|
23221
23259
|
|
|
23260
|
+
/**
|
|
23261
|
+
* Note: It is good practice to isolate useEffects into their own components.
|
|
23262
|
+
* This approach helps prevent unnecessary re-renders when data is unchanged,
|
|
23263
|
+
* since useEffect will only be triggered in this dedicated sibling component.
|
|
23264
|
+
*/
|
|
23265
|
+
const QuoteIsLoadingUpdater = ({ quoteIsPending }) => {
|
|
23266
|
+
const [, setQuoteIsLoading] = useQuoteIsLoading();
|
|
23267
|
+
const prevValue = react.useRef(quoteIsPending);
|
|
23268
|
+
react.useEffect(() => {
|
|
23269
|
+
if (prevValue.current !== quoteIsPending) {
|
|
23270
|
+
setQuoteIsLoading(quoteIsPending);
|
|
23271
|
+
prevValue.current = quoteIsPending;
|
|
23272
|
+
}
|
|
23273
|
+
}, [quoteIsPending, setQuoteIsLoading]);
|
|
23274
|
+
return null;
|
|
23275
|
+
};
|
|
23276
|
+
|
|
23222
23277
|
const QuantityInput_SubscriptionChargeFragment = t(`
|
|
23223
23278
|
fragment QuantityInput_SubscriptionChargeFragment on SubscriptionCharge {
|
|
23224
23279
|
id
|
|
@@ -23230,7 +23285,6 @@ const QuantityInput_SubscriptionChargeFragment = t(`
|
|
|
23230
23285
|
const QuantityInput_SubscriptionFragment = t(`
|
|
23231
23286
|
fragment QuantityInput_SubscriptionFragment on Subscription {
|
|
23232
23287
|
id
|
|
23233
|
-
state
|
|
23234
23288
|
priceList {
|
|
23235
23289
|
id
|
|
23236
23290
|
}
|
|
@@ -23246,6 +23300,16 @@ const QuantityInput_SubscriptionFragment = t(`
|
|
|
23246
23300
|
CanShowQuantitiesInput_SubscriptionFragment,
|
|
23247
23301
|
]);
|
|
23248
23302
|
const DEBOUNCE_TIME$1 = 1000;
|
|
23303
|
+
/**
|
|
23304
|
+
* Design note:
|
|
23305
|
+
* If the quantity is cleared by the user (quantity becomes undefined), we delete the quote.
|
|
23306
|
+
*
|
|
23307
|
+
* Rationale:
|
|
23308
|
+
* The user may next change the quantity for a charge on a different subscription, and we need to
|
|
23309
|
+
* allow creating a new quote/quoteChange in that context. Currently there is no way to create a
|
|
23310
|
+
* quoteChange of kind "update" without first calling `quoteSubscriptionUpdate`, so we delete the
|
|
23311
|
+
* existing quote to reset the flow.
|
|
23312
|
+
*/
|
|
23249
23313
|
const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription, setUpdatingChargeQuantityId, updatingChargeQuantityId, setErrorUpdatingQuantity, }) => {
|
|
23250
23314
|
// Context
|
|
23251
23315
|
const token = useToken();
|
|
@@ -23260,7 +23324,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23260
23324
|
const quote = readFragment(QuantityInput_QuoteFragment, maskedQuote);
|
|
23261
23325
|
// Hooks
|
|
23262
23326
|
const showErrorNotification = common.useErrorNotification();
|
|
23263
|
-
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
23327
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23264
23328
|
const quantityDisabled =
|
|
23265
23329
|
// If we are editing a quote, we disable the quantity input
|
|
23266
23330
|
// If we don't have a quantity, we disable the quantity input
|
|
@@ -23273,7 +23337,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23273
23337
|
!charge.selfServiceQuantity;
|
|
23274
23338
|
const value = quantity === undefined ? '' : quantity;
|
|
23275
23339
|
// Mutations
|
|
23276
|
-
const { mutate: createCharge } = reactQuery.useMutation({
|
|
23340
|
+
const { mutate: createCharge, isPending: isCreatingCharge } = reactQuery.useMutation({
|
|
23277
23341
|
mutationFn: quoteChargeCreate$1,
|
|
23278
23342
|
onSuccess: response => {
|
|
23279
23343
|
var _a, _b;
|
|
@@ -23288,7 +23352,23 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23288
23352
|
setErrorUpdatingQuantity(true);
|
|
23289
23353
|
},
|
|
23290
23354
|
});
|
|
23291
|
-
const
|
|
23355
|
+
const { mutate: deleteQuote, isPending: isDeletingQuote } = reactQuery.useMutation({
|
|
23356
|
+
mutationFn: quoteDelete,
|
|
23357
|
+
onSuccess: response => {
|
|
23358
|
+
var _a;
|
|
23359
|
+
const quoteId = (_a = response === null || response === void 0 ? void 0 : response.quote) === null || _a === void 0 ? void 0 : _a.id;
|
|
23360
|
+
if (!quoteId) {
|
|
23361
|
+
showErrorNotification('quoteId is required');
|
|
23362
|
+
return;
|
|
23363
|
+
}
|
|
23364
|
+
setQuoteQueryData(quoteId, null);
|
|
23365
|
+
setQuoteId(undefined);
|
|
23366
|
+
},
|
|
23367
|
+
onError: () => {
|
|
23368
|
+
setErrorUpdatingQuantity(true);
|
|
23369
|
+
},
|
|
23370
|
+
});
|
|
23371
|
+
const { mutate: createQuote, isPending: isCreatingQuote } = reactQuery.useMutation({
|
|
23292
23372
|
mutationFn: (subscriptionId) => quoteSubscriptionUpdate([subscriptionId], apiHost, token),
|
|
23293
23373
|
onSuccess: quote => {
|
|
23294
23374
|
var _a, _b, _c;
|
|
@@ -23316,7 +23396,7 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23316
23396
|
setErrorUpdatingQuantity(true);
|
|
23317
23397
|
},
|
|
23318
23398
|
});
|
|
23319
|
-
const updateQuoteCharge = reactQuery.useMutation({
|
|
23399
|
+
const { mutate: updateQuoteCharge, isPending: isUpdatingQuoteCharge } = reactQuery.useMutation({
|
|
23320
23400
|
mutationFn: ({ quoteChargeId, quantity, }) => {
|
|
23321
23401
|
if (!quoteChargeId)
|
|
23322
23402
|
throw new Error('quoteChargeId is required');
|
|
@@ -23338,26 +23418,35 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23338
23418
|
});
|
|
23339
23419
|
const onChangeQuantity = (value) => {
|
|
23340
23420
|
var _a;
|
|
23421
|
+
// Cancel all debounced functions first
|
|
23422
|
+
debouncedQuantityUpdate.cancel();
|
|
23423
|
+
debouncedDeleteQuote.cancel();
|
|
23341
23424
|
// Handle empty string - don't convert to 0, keep it as undefined
|
|
23342
23425
|
const quantity = value === '' ? undefined : isNaN(parseInt(value)) ? 0 : parseInt(value);
|
|
23343
23426
|
setQuantity(quantity);
|
|
23344
23427
|
if (quantity === undefined) {
|
|
23345
23428
|
setUpdatingChargeQuantityId(undefined);
|
|
23429
|
+
if (quoteId) {
|
|
23430
|
+
// Only delete the quote if it exists
|
|
23431
|
+
debouncedDeleteQuote(quoteId);
|
|
23432
|
+
}
|
|
23346
23433
|
}
|
|
23347
23434
|
else {
|
|
23348
23435
|
if (!(charge === null || charge === void 0 ? void 0 : charge.priceListChargeId)) {
|
|
23349
23436
|
showErrorNotification('Charge ID is not found');
|
|
23350
23437
|
return;
|
|
23351
23438
|
}
|
|
23352
|
-
//
|
|
23439
|
+
// Used to disable all other quantity inputs for this subscription
|
|
23353
23440
|
setUpdatingChargeQuantityId(getUpdatingChargeQuantityId(charge.priceListChargeId, subscription.id));
|
|
23354
23441
|
const quantityDelta = quantity - ((_a = charge.quantity) !== null && _a !== void 0 ? _a : 0);
|
|
23355
|
-
debouncedQuantityUpdate.
|
|
23356
|
-
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, quantity, subscription.id, quote, quoteId);
|
|
23442
|
+
debouncedQuantityUpdate(charge.priceListChargeId, quantityDelta, subscription.id, quote, quoteId);
|
|
23357
23443
|
}
|
|
23358
23444
|
};
|
|
23359
|
-
const
|
|
23360
|
-
|
|
23445
|
+
const debouncedDeleteQuote = react.useCallback(lodashExports.debounce((quoteId) => {
|
|
23446
|
+
deleteQuote({ id: quoteId, apiHost, token });
|
|
23447
|
+
}, DEBOUNCE_TIME$1), []);
|
|
23448
|
+
const debouncedQuantityUpdate = react.useCallback(lodashExports.debounce((priceListChargeId, quantityDelta, subscriptionId, quote, quoteId) => {
|
|
23449
|
+
var _a;
|
|
23361
23450
|
if (quantityDelta === 0) {
|
|
23362
23451
|
setErrorUpdatingQuantity(true);
|
|
23363
23452
|
showErrorNotification('New quantity cannot be the same as current');
|
|
@@ -23365,37 +23454,22 @@ const QuantityInput = ({ charge: maskedCharge, subscription: maskedSubscription,
|
|
|
23365
23454
|
}
|
|
23366
23455
|
// If we are not editing a quote, we create a new one
|
|
23367
23456
|
if (quoteId === undefined) {
|
|
23368
|
-
createQuote
|
|
23457
|
+
createQuote(subscriptionId);
|
|
23369
23458
|
}
|
|
23370
23459
|
else {
|
|
23371
23460
|
const quoteChange = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.find(quoteChange => { var _a, _b; return ((_a = quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.priceList) === null || _a === void 0 ? void 0 : _a.id) === ((_b = subscription.priceList) === null || _b === void 0 ? void 0 : _b.id); });
|
|
23372
23461
|
const quoteCharge = quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.charges.find(charge => { var _a; return ((_a = charge === null || charge === void 0 ? void 0 : charge.priceListCharge) === null || _a === void 0 ? void 0 : _a.id) === priceListChargeId; });
|
|
23373
23462
|
if (quoteCharge) {
|
|
23374
|
-
updateQuoteCharge
|
|
23463
|
+
updateQuoteCharge({
|
|
23375
23464
|
quoteChargeId: quoteCharge.id,
|
|
23376
23465
|
quantity: quantityDelta,
|
|
23377
23466
|
});
|
|
23378
23467
|
}
|
|
23379
|
-
else {
|
|
23380
|
-
const subscriptionCharge = (_c = (_b = quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.subscription) === null || _b === void 0 ? void 0 : _b.charges) === null || _c === void 0 ? void 0 : _c.find(subscriptionCharge => { var _a; return ((_a = subscriptionCharge === null || subscriptionCharge === void 0 ? void 0 : subscriptionCharge.priceListCharge) === null || _a === void 0 ? void 0 : _a.id) === priceListChargeId; });
|
|
23381
|
-
if (!(subscriptionCharge === null || subscriptionCharge === void 0 ? void 0 : subscriptionCharge.id))
|
|
23382
|
-
throw new Error('subscriptionCharge id is required');
|
|
23383
|
-
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id))
|
|
23384
|
-
throw new Error('quoteChange id is required');
|
|
23385
|
-
createCharge({
|
|
23386
|
-
apiHost,
|
|
23387
|
-
quantity, // This is a new charge so use quantity instead of quantityDelta
|
|
23388
|
-
quoteChangeId: quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id,
|
|
23389
|
-
startDate: formatDateForApi(dayjs()),
|
|
23390
|
-
subscriptionChargeId: subscriptionCharge.id,
|
|
23391
|
-
token,
|
|
23392
|
-
});
|
|
23393
|
-
}
|
|
23394
23468
|
}
|
|
23395
23469
|
}, DEBOUNCE_TIME$1), []);
|
|
23396
|
-
return (jsxRuntime.
|
|
23397
|
-
|
|
23398
|
-
|
|
23470
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(antd.Input, { className: "bunny-text-right", disabled: quantityDisabled, onChange: e => {
|
|
23471
|
+
onChangeQuantity(e.target.value);
|
|
23472
|
+
}, style: { width: '96px' }, value: value }), jsxRuntime.jsx(QuoteIsLoadingUpdater, { quoteIsPending: isCreatingCharge || isDeletingQuote || isCreatingQuote || isUpdatingQuoteCharge })] }));
|
|
23399
23473
|
};
|
|
23400
23474
|
|
|
23401
23475
|
const QuantityChangeGridRow_SubscriptionChargeFragment = t(`
|
|
@@ -23522,6 +23596,46 @@ function invalidateSubscriptionsQueryKeys(queryClient, token) {
|
|
|
23522
23596
|
});
|
|
23523
23597
|
}
|
|
23524
23598
|
|
|
23599
|
+
const [QuoteRecalculateTaxesProvider, useQuoteRecalculateTaxes$2] = createValueContext();
|
|
23600
|
+
|
|
23601
|
+
const mutation$8 = t(`
|
|
23602
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
23603
|
+
quoteRecalculateTaxes(id: $id) {
|
|
23604
|
+
quote {
|
|
23605
|
+
...QuantityDrawer_QuoteFragment
|
|
23606
|
+
id
|
|
23607
|
+
}
|
|
23608
|
+
errors
|
|
23609
|
+
}
|
|
23610
|
+
}
|
|
23611
|
+
`, [QuantityDrawer_QuoteFragment]);
|
|
23612
|
+
const quoteRecalculateTaxes$1 = async ({ quoteId, apiHost, token, }) => {
|
|
23613
|
+
var _a;
|
|
23614
|
+
const response = await execute(mutation$8, { apiHost, token }, { id: quoteId });
|
|
23615
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
23616
|
+
};
|
|
23617
|
+
|
|
23618
|
+
const useQuoteRecalculateTaxes$1 = () => {
|
|
23619
|
+
const token = useToken();
|
|
23620
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
23621
|
+
const { setQuoteQueryData } = useSetQuoteQueryData$1();
|
|
23622
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = reactQuery.useMutation({
|
|
23623
|
+
mutationFn: async ({ quoteId }) => {
|
|
23624
|
+
return await quoteRecalculateTaxes$1({ quoteId, apiHost, token });
|
|
23625
|
+
},
|
|
23626
|
+
onSuccess: quote => {
|
|
23627
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
23628
|
+
throw new Error('Quote ID is undefined');
|
|
23629
|
+
}
|
|
23630
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
23631
|
+
},
|
|
23632
|
+
});
|
|
23633
|
+
return {
|
|
23634
|
+
quoteRecalculateTaxesMutation,
|
|
23635
|
+
isRecalculatingTaxes,
|
|
23636
|
+
};
|
|
23637
|
+
};
|
|
23638
|
+
|
|
23525
23639
|
const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23526
23640
|
const token = useToken();
|
|
23527
23641
|
const queryClient = reactQuery.useQueryClient();
|
|
@@ -23531,6 +23645,8 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23531
23645
|
const [payModalVisible, setPayModalVisible] = react.useState(false);
|
|
23532
23646
|
const [updatingChargeQuantityId, setUpdatingChargeQuantityId] = react.useState(undefined);
|
|
23533
23647
|
const quote = useQuoteQueryData(quoteId);
|
|
23648
|
+
// Context
|
|
23649
|
+
const onRecalculateTaxes = useQuoteRecalculateTaxes$2();
|
|
23534
23650
|
// Handlers
|
|
23535
23651
|
const onSuccess = () => {
|
|
23536
23652
|
setQuantityDrawerOpen(false);
|
|
@@ -23560,10 +23676,11 @@ const QuantityDrawerContent = ({ subscriptions, quantityDrawerOpen, setQuantityD
|
|
|
23560
23676
|
const handleOpenCheckout = () => {
|
|
23561
23677
|
setPayModalVisible(true);
|
|
23562
23678
|
};
|
|
23563
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(QuantityChangeDrawerDesktop, { onClose: handleDrawerClose, open: quantityDrawerOpen, openCheckout: handleOpenCheckout, subscriptions: subscriptions, setUpdatingChargeQuantityId: setUpdatingChargeQuantityId, updatingChargeQuantityId: updatingChargeQuantityId }), jsxRuntime.jsx(Checkout, { onCancel: onCancel, onSuccess: onSuccess, onFail: onFail, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: false })] }));
|
|
23679
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(QuantityChangeDrawerDesktop, { onClose: handleDrawerClose, open: quantityDrawerOpen, openCheckout: handleOpenCheckout, subscriptions: subscriptions, setUpdatingChargeQuantityId: setUpdatingChargeQuantityId, updatingChargeQuantityId: updatingChargeQuantityId }), jsxRuntime.jsx(Checkout, { onCancel: onCancel, onSuccess: onSuccess, onFail: onFail, onRecalculateTaxes: onRecalculateTaxes, open: payModalVisible, quote: quote, token: token, isUpdatingQuote: false })] }));
|
|
23564
23680
|
};
|
|
23565
23681
|
const QuantityDrawer = ({ subscriptions, quantityDrawerOpen, setQuantityDrawerOpen, handlePortalErrors, setShowInactive, }) => {
|
|
23566
|
-
|
|
23682
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes$1();
|
|
23683
|
+
return (jsxRuntime.jsx(QuoteIdProvider, { children: jsxRuntime.jsx(QuoteIsLoadingProvider, { children: jsxRuntime.jsx(QuoteRecalculateTaxesProvider, { value: quoteId => quoteRecalculateTaxesMutation({ quoteId }), children: jsxRuntime.jsx(QuantityDrawerContent, { subscriptions: subscriptions, quantityDrawerOpen: quantityDrawerOpen, setQuantityDrawerOpen: setQuantityDrawerOpen, handlePortalErrors: handlePortalErrors, setShowInactive: setShowInactive }) }) }) }));
|
|
23567
23684
|
};
|
|
23568
23685
|
|
|
23569
23686
|
const useCancelSubscription = () => {
|
|
@@ -23827,14 +23944,27 @@ const SubscriptionCardActions = ({ onChangePlanClick, onCancelSubscriptionClick,
|
|
|
23827
23944
|
const isInTrial = isSubscriptionTrial(subscription);
|
|
23828
23945
|
const isTrialExpired = isSubscriptionTrialExpired(subscription);
|
|
23829
23946
|
const isActiveOrPending = isSubscriptionActiveOrPending(subscription);
|
|
23947
|
+
const getButtonLabel = () => {
|
|
23948
|
+
if (isInTrial) {
|
|
23949
|
+
return 'Upgrade from trial';
|
|
23950
|
+
}
|
|
23951
|
+
if (isTrialExpired) {
|
|
23952
|
+
return 'Upgrade';
|
|
23953
|
+
}
|
|
23954
|
+
// If the subscription is an addon, we should show the "Adjust plan" button since we don't support changing add-on plans.
|
|
23955
|
+
if (subscription.priceList.plan.addon === true) {
|
|
23956
|
+
return 'Adjust plan';
|
|
23957
|
+
}
|
|
23958
|
+
return 'Change plan';
|
|
23959
|
+
};
|
|
23830
23960
|
if (isPaymentMethodLoading)
|
|
23831
23961
|
return null;
|
|
23832
23962
|
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isSelfServiceCancelable && onCancelSubscriptionClick && (isInTrial || isActiveOrPending) && (jsxRuntime.jsx(antd.Popconfirm, { icon: null, onConfirm: () => onCancelSubscriptionClick(subscription), title: "Cancel subscription", children: jsxRuntime.jsx(antd.Button, { className: "bunny-p-0", type: "link", children: "Cancel subscription" }) })), arePlansAvailable &&
|
|
23833
23963
|
onChangePlanClick &&
|
|
23834
|
-
(isActiveOrPending || isInTrial || isTrialExpired) && (jsxRuntime.jsx(antd.Button, { onClick: () => onChangePlanClick(subscription), type: 'primary', children:
|
|
23964
|
+
(isActiveOrPending || isInTrial || isTrialExpired) && (jsxRuntime.jsx(antd.Button, { onClick: () => onChangePlanClick(subscription), type: 'primary', children: getButtonLabel() })), !arePlansAvailable && isInTrial && jsxRuntime.jsx(antd.Tag, { color: "warning", children: "Cannot upgrade" })] }));
|
|
23835
23965
|
};
|
|
23836
23966
|
|
|
23837
|
-
const query$
|
|
23967
|
+
const query$4 = t(`
|
|
23838
23968
|
query priceListChangeOptions($productId: ID!) {
|
|
23839
23969
|
priceListChangeOptions(productId: $productId) {
|
|
23840
23970
|
...SubscriptionCardActions_PriceListChangeOptionsFragment
|
|
@@ -23842,7 +23972,7 @@ const query$2 = t(`
|
|
|
23842
23972
|
}
|
|
23843
23973
|
`, [SubscriptionCardActions_PriceListChangeOptionsFragment]);
|
|
23844
23974
|
const getPriceListChangeOptions$1 = async ({ apiHost, productId, token, }) => {
|
|
23845
|
-
const response = await execute(query$
|
|
23975
|
+
const response = await execute(query$4, { apiHost, token }, { productId });
|
|
23846
23976
|
return response.priceListChangeOptions;
|
|
23847
23977
|
};
|
|
23848
23978
|
|
|
@@ -23876,7 +24006,7 @@ const getSubscriptionStatusText = (subscription) => {
|
|
|
23876
24006
|
return `Trial expires on ${common.formatDate(trialEndDate)}`;
|
|
23877
24007
|
}
|
|
23878
24008
|
}
|
|
23879
|
-
if (evergreen) {
|
|
24009
|
+
if (evergreen && subscription.state === t.scalar('SubscriptionState', 'ACTIVE')) {
|
|
23880
24010
|
return `Renews on ${common.formatDate(endDate)}`;
|
|
23881
24011
|
}
|
|
23882
24012
|
return `Ends on ${common.formatDate(endDate || trialEndDate)}`;
|
|
@@ -23954,40 +24084,66 @@ const formatNumber = (num, decimals = 2) => {
|
|
|
23954
24084
|
});
|
|
23955
24085
|
};
|
|
23956
24086
|
|
|
24087
|
+
const getPricingModelDescription = (pricingModel) => {
|
|
24088
|
+
switch (pricingModel) {
|
|
24089
|
+
case 'TIERED':
|
|
24090
|
+
return 'units in each tier are priced separately.';
|
|
24091
|
+
case 'VOLUME':
|
|
24092
|
+
return 'the highest tier reached prices all units.';
|
|
24093
|
+
case 'BANDS':
|
|
24094
|
+
return 'the quantity indexes to a flat price.';
|
|
24095
|
+
default:
|
|
24096
|
+
return '';
|
|
24097
|
+
}
|
|
24098
|
+
};
|
|
24099
|
+
|
|
24100
|
+
const getPricingModelTitle = (pricingModel) => {
|
|
24101
|
+
switch (pricingModel) {
|
|
24102
|
+
case 'TIERED':
|
|
24103
|
+
return 'Tiered';
|
|
24104
|
+
case 'VOLUME':
|
|
24105
|
+
return 'Volume';
|
|
24106
|
+
case 'BANDS':
|
|
24107
|
+
return 'Bands';
|
|
24108
|
+
default:
|
|
24109
|
+
return '';
|
|
24110
|
+
}
|
|
24111
|
+
};
|
|
24112
|
+
|
|
23957
24113
|
const StyledTable = styled(antd.Table) `
|
|
23958
24114
|
.ant-table-cell {
|
|
23959
24115
|
border-bottom: none !important;
|
|
23960
24116
|
}
|
|
23961
24117
|
`;
|
|
23962
|
-
const TieredDisplayDropdown = ({ priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
24118
|
+
const TieredDisplayDropdown = ({ pricingModel, priceTiers, currencyId, priceDecimals, truncatedText, }) => {
|
|
23963
24119
|
const onlyHasOneTier = (priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers.length) === 1;
|
|
23964
24120
|
const dropdownTrigger = (jsxRuntime.jsx("div", { className: `w-full ${onlyHasOneTier ? '' : 'underline cursor-pointer'}`, children: truncatedText }));
|
|
23965
24121
|
if (onlyHasOneTier) {
|
|
23966
24122
|
return dropdownTrigger;
|
|
23967
24123
|
}
|
|
23968
24124
|
return (jsxRuntime.jsx(antd.Dropdown, { popupRender: () => {
|
|
23969
|
-
return (jsxRuntime.
|
|
23970
|
-
|
|
23971
|
-
|
|
23972
|
-
|
|
23973
|
-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
23979
|
-
|
|
24125
|
+
return (jsxRuntime.jsxs("div", { className: "rounded border border-solid border-slate-200 bg-white overflow-hidden", children: [jsxRuntime.jsxs("div", { className: "bunny-text-gray-400 bunny-p-2", children: [getPricingModelTitle(pricingModel), " pricing -", ' ', getPricingModelDescription(pricingModel)] }), jsxRuntime.jsx(StyledTable, { columns: [
|
|
24126
|
+
{
|
|
24127
|
+
dataIndex: 'starts',
|
|
24128
|
+
title: 'From # of units',
|
|
24129
|
+
align: 'right',
|
|
24130
|
+
render: (_, record, index) => {
|
|
24131
|
+
record = record;
|
|
24132
|
+
const nextRecord = priceTiers === null || priceTiers === void 0 ? void 0 : priceTiers[index + 1];
|
|
24133
|
+
const starts = record.starts;
|
|
24134
|
+
const ends = (nextRecord === null || nextRecord === void 0 ? void 0 : nextRecord.starts) ? nextRecord.starts - 1 : '+';
|
|
24135
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [formatNumber(starts, 0), typeof ends === 'number' ? formatNumber(ends, 0) : '+'] }));
|
|
24136
|
+
},
|
|
23980
24137
|
},
|
|
23981
|
-
|
|
23982
|
-
|
|
23983
|
-
|
|
23984
|
-
|
|
23985
|
-
|
|
23986
|
-
|
|
23987
|
-
|
|
24138
|
+
{
|
|
24139
|
+
dataIndex: 'price',
|
|
24140
|
+
title: 'Unit price',
|
|
24141
|
+
align: 'right',
|
|
24142
|
+
render: value => {
|
|
24143
|
+
return jsxRuntime.jsx(jsxRuntime.Fragment, { children: common.formatCurrency(value, currencyId, priceDecimals) });
|
|
24144
|
+
},
|
|
23988
24145
|
},
|
|
23989
|
-
}
|
|
23990
|
-
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" }) }));
|
|
24146
|
+
], dataSource: priceTiers, rowKey: "starts", pagination: false, size: "small" })] }));
|
|
23991
24147
|
}, children: dropdownTrigger }));
|
|
23992
24148
|
};
|
|
23993
24149
|
|
|
@@ -24038,7 +24194,7 @@ const SubscriptionChargeUnitPrice = ({ charge, currencyId, }) => {
|
|
|
24038
24194
|
? '-'
|
|
24039
24195
|
: common.formatCurrency(charge.discountedPrice, currencyId, charge.priceDecimals);
|
|
24040
24196
|
const isChargeDiscount = isDiscount$1(charge.kind);
|
|
24041
|
-
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: hasPriceTiers(charge) ? (jsxRuntime.jsx(TieredDisplayDropdown, { priceTiers: charge.priceTiers, currencyId: currencyId, priceDecimals: charge.priceDecimals, truncatedText: `${charge.kind === common.QuoteChangeKind.PRICE_UPDATE ? 'new ' : ''}${getApplicablePriceTier(charge, currencyId, charge.priceDecimals)}` })) : isChargeDiscount ? (`-${price}`) : (price) }));
|
|
24197
|
+
return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: hasPriceTiers(charge) ? (jsxRuntime.jsx(TieredDisplayDropdown, { pricingModel: charge.pricingModel, priceTiers: charge.priceTiers, currencyId: currencyId, priceDecimals: charge.priceDecimals, truncatedText: `${charge.kind === common.QuoteChangeKind.PRICE_UPDATE ? 'new ' : ''}${getApplicablePriceTier(charge, currencyId, charge.priceDecimals)}` })) : isChargeDiscount ? (`-${price}`) : (price) }));
|
|
24042
24198
|
};
|
|
24043
24199
|
|
|
24044
24200
|
const { Text: Text$e } = antd.Typography;
|
|
@@ -24175,7 +24331,7 @@ const SubscriptionCardDesktopRow = ({ charge, chargeIndex, charges, currencyId,
|
|
|
24175
24331
|
: (_b = charge.quantity) === null || _b === void 0 ? void 0 : _b.toLocaleString() }), jsxRuntime.jsx(SubscriptionsListCell, { right: true, children: jsxRuntime.jsx(SubscriptionChargeUnitPrice, { charge: charge, currencyId: currencyId }) }), jsxRuntime.jsx(SubscriptionsListCell, { right: true, children: jsxRuntime.jsx(SubscriptionChargeTotal, { charge: charge, currencyId: currencyId }) })] }));
|
|
24176
24332
|
};
|
|
24177
24333
|
|
|
24178
|
-
function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, subscription, showInactive, }) {
|
|
24334
|
+
function AddonSubscriptionsCards({ onCancelSubscriptionClick, onChangePlanClick, subscriptions, subscription, showInactive, }) {
|
|
24179
24335
|
const addonSubscriptions = findAddonSubscriptions(subscription, subscriptions);
|
|
24180
24336
|
if (addonSubscriptions.length === 0) {
|
|
24181
24337
|
return null;
|
|
@@ -24184,7 +24340,7 @@ function AddonSubscriptionsCards({ onCancelSubscriptionClick, subscriptions, sub
|
|
|
24184
24340
|
if (!showInactive && isSubscriptionNotActive(addonSubscription))
|
|
24185
24341
|
return null;
|
|
24186
24342
|
const isLast = addonSubscriptionIndex === addonSubscriptions.length - 1;
|
|
24187
|
-
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxRuntime.jsx(AddonIndentation, { isLast: isLast, indentation: ADDON_INDENTATION, verticalMargin: "-1rem" }), jsxRuntime.jsx("div", { className: "bunny-flex-1", children: jsxRuntime.jsx(SubscriptionCardDesktop, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: addonSubscription, isAddon: true }) })] }, addonSubscriptionIndex));
|
|
24343
|
+
return (jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row", children: [jsxRuntime.jsx(AddonIndentation, { isLast: isLast, indentation: ADDON_INDENTATION, verticalMargin: "-1rem" }), jsxRuntime.jsx("div", { className: "bunny-flex-1", children: jsxRuntime.jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: addonSubscription, isAddon: true }) })] }, addonSubscriptionIndex));
|
|
24188
24344
|
}) }));
|
|
24189
24345
|
}
|
|
24190
24346
|
|
|
@@ -24243,8 +24399,8 @@ const SubscriptionsList = ({ showInactive, onChangePlanClick, onCancelSubscripti
|
|
|
24243
24399
|
if (!showInactive && isSubscriptionNotActive(subscription))
|
|
24244
24400
|
return null;
|
|
24245
24401
|
if (isMobile)
|
|
24246
|
-
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsxRuntime.jsx(SubscriptionCard, { subscription: subscription }), jsxRuntime.jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24247
|
-
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsxRuntime.jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription }), jsxRuntime.jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24402
|
+
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsxRuntime.jsx(SubscriptionCard, { subscription: subscription }), jsxRuntime.jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, onChangePlanClick: onChangePlanClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24403
|
+
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-col bunny-gap-${gap}`, children: [jsxRuntime.jsx(SubscriptionCardDesktop, { onChangePlanClick: onChangePlanClick, onCancelSubscriptionClick: onCancelSubscriptionClick, subscription: subscription }), jsxRuntime.jsx(AddonSubscriptionsCards, { onCancelSubscriptionClick: onCancelSubscriptionClick, onChangePlanClick: onChangePlanClick, subscription: subscription, subscriptions: subscriptions, showInactive: showInactive })] }, subscriptionIndex));
|
|
24248
24404
|
}) }));
|
|
24249
24405
|
};
|
|
24250
24406
|
|
|
@@ -24315,7 +24471,7 @@ const FormattedQuoteFields_QuoteFragment = t(`
|
|
|
24315
24471
|
}
|
|
24316
24472
|
}
|
|
24317
24473
|
`);
|
|
24318
|
-
const query$
|
|
24474
|
+
const query$3 = t(`
|
|
24319
24475
|
query quote($id: ID, $includeHtmlField: Boolean!) {
|
|
24320
24476
|
quote(id: $id) {
|
|
24321
24477
|
...FormattedQuoteFields_QuoteFragment @include(if: $includeHtmlField)
|
|
@@ -24324,7 +24480,7 @@ const query$1 = t(`
|
|
|
24324
24480
|
}
|
|
24325
24481
|
`, [FormattedQuoteFields_QuoteFragment, QuoteContext_QuoteFragment]);
|
|
24326
24482
|
const getQuote = async ({ id, token, apiHost, includeHtmlField = false, }) => {
|
|
24327
|
-
const response = await execute(query$
|
|
24483
|
+
const response = await execute(query$3, { apiHost, token }, { id, includeHtmlField });
|
|
24328
24484
|
return response === null || response === void 0 ? void 0 : response.quote;
|
|
24329
24485
|
};
|
|
24330
24486
|
|
|
@@ -24429,7 +24585,7 @@ const calculateNewQuantity = (priceListCharge, currentQuantity = 1) => {
|
|
|
24429
24585
|
return quantityMin;
|
|
24430
24586
|
};
|
|
24431
24587
|
|
|
24432
|
-
const mutation$
|
|
24588
|
+
const mutation$7 = t(`
|
|
24433
24589
|
mutation QuoteChangeUpdate($id: ID!, $charges: [QuoteChargeAttributes!]!) {
|
|
24434
24590
|
quoteChangeUpdate(id: $id, charges: $charges) {
|
|
24435
24591
|
quoteChange {
|
|
@@ -24443,7 +24599,7 @@ const mutation$1 = t(`
|
|
|
24443
24599
|
`, [QuoteContext_QuoteFragment]);
|
|
24444
24600
|
const quoteChangeUpdate = async ({ quoteChangeId, charges, apiHost, token, }) => {
|
|
24445
24601
|
var _a, _b;
|
|
24446
|
-
const response = await execute(mutation$
|
|
24602
|
+
const response = await execute(mutation$7, {
|
|
24447
24603
|
apiHost,
|
|
24448
24604
|
token,
|
|
24449
24605
|
}, {
|
|
@@ -24499,6 +24655,19 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24499
24655
|
};
|
|
24500
24656
|
}
|
|
24501
24657
|
|
|
24658
|
+
const useSetQuoteQueryData = () => {
|
|
24659
|
+
const token = useToken();
|
|
24660
|
+
const queryClient = reactQuery.useQueryClient();
|
|
24661
|
+
const setQuoteQueryData = (quoteId, quote) => {
|
|
24662
|
+
queryClient.setQueryData(common.QueryKeyFactory.default.createObjectKey({
|
|
24663
|
+
id: quoteId,
|
|
24664
|
+
objectName: 'editingQuote',
|
|
24665
|
+
token,
|
|
24666
|
+
}), quote);
|
|
24667
|
+
};
|
|
24668
|
+
return { setQuoteQueryData };
|
|
24669
|
+
};
|
|
24670
|
+
|
|
24502
24671
|
// Functionality:
|
|
24503
24672
|
// 1: keep track of quantities set for features based on feature.id
|
|
24504
24673
|
// a. copy those quantities over to charges with same feature when initializing
|
|
@@ -24511,9 +24680,9 @@ function useFeatureQuantities({ onFeatureQuantitiesChanged, }) {
|
|
|
24511
24680
|
const showErrorNotification = common.useErrorNotification();
|
|
24512
24681
|
const DEBOUNCE_TIME = 1000;
|
|
24513
24682
|
const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
24514
|
-
const queryClient = reactQuery.useQueryClient();
|
|
24515
24683
|
const token = useToken();
|
|
24516
24684
|
const { apiHost } = react.useContext(BunnyContext);
|
|
24685
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24517
24686
|
// Derived state
|
|
24518
24687
|
const selectedPriceListQuoteChange = react.useMemo(() => {
|
|
24519
24688
|
var _a;
|
|
@@ -24532,23 +24701,27 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24532
24701
|
});
|
|
24533
24702
|
},
|
|
24534
24703
|
onSuccess: quoteChange => {
|
|
24535
|
-
|
|
24536
|
-
|
|
24537
|
-
|
|
24538
|
-
|
|
24539
|
-
|
|
24540
|
-
}
|
|
24704
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24705
|
+
throw new Error('Quote ID is undefined');
|
|
24706
|
+
}
|
|
24707
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote)) {
|
|
24708
|
+
throw new Error('Quote is undefined');
|
|
24709
|
+
}
|
|
24710
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.quote);
|
|
24541
24711
|
},
|
|
24542
24712
|
});
|
|
24543
24713
|
function handleUpdateQuoteQuantities(featureQuantities) {
|
|
24544
24714
|
if (!selectedPriceListQuoteChange) {
|
|
24545
|
-
|
|
24715
|
+
console.error('Quote change is undefined');
|
|
24716
|
+
return;
|
|
24546
24717
|
}
|
|
24547
24718
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24548
|
-
|
|
24719
|
+
console.error('Quote ID is undefined');
|
|
24720
|
+
return;
|
|
24549
24721
|
}
|
|
24550
24722
|
if (!(selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.id)) {
|
|
24551
|
-
|
|
24723
|
+
console.error('Quote change ID is undefined');
|
|
24724
|
+
return;
|
|
24552
24725
|
}
|
|
24553
24726
|
const featureIdsToUpdate = Object.keys(featureQuantities).filter(featureId => {
|
|
24554
24727
|
// If the quantities differ, then update quote with the quantities present in useFeatureQuantities
|
|
@@ -24560,20 +24733,24 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24560
24733
|
const quoteCharge = selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.charges.find(charge => { var _a; return ((_a = charge === null || charge === void 0 ? void 0 : charge.feature) === null || _a === void 0 ? void 0 : _a.id) === featureId; });
|
|
24561
24734
|
return quoteCharge !== undefined && localAndQuoteQuantitiesDiffer;
|
|
24562
24735
|
});
|
|
24563
|
-
const charges = featureIdsToUpdate
|
|
24736
|
+
const charges = featureIdsToUpdate
|
|
24737
|
+
.map(featureId => {
|
|
24564
24738
|
const quoteCharge = selectedPriceListQuoteChange === null || selectedPriceListQuoteChange === void 0 ? void 0 : selectedPriceListQuoteChange.charges.find(charge => { var _a; return ((_a = charge === null || charge === void 0 ? void 0 : charge.feature) === null || _a === void 0 ? void 0 : _a.id) === featureId; });
|
|
24565
24739
|
const quantity = getFeatureQuantity(featureId, featureQuantities);
|
|
24566
24740
|
if (!quantity) {
|
|
24567
|
-
|
|
24741
|
+
console.error('Quantity is undefined');
|
|
24742
|
+
return;
|
|
24568
24743
|
}
|
|
24569
24744
|
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id)) {
|
|
24570
|
-
|
|
24745
|
+
console.error('Quote charge for featureId is undefined');
|
|
24746
|
+
return;
|
|
24571
24747
|
}
|
|
24572
24748
|
return {
|
|
24573
24749
|
id: quoteCharge.id,
|
|
24574
24750
|
quantity: quantity,
|
|
24575
24751
|
};
|
|
24576
|
-
})
|
|
24752
|
+
})
|
|
24753
|
+
.filter(charge => charge !== undefined);
|
|
24577
24754
|
if (charges.length === 0) {
|
|
24578
24755
|
return;
|
|
24579
24756
|
}
|
|
@@ -24641,6 +24818,44 @@ const useQuoteQuantities = ({ selectedPriceList, quote, }) => {
|
|
|
24641
24818
|
};
|
|
24642
24819
|
};
|
|
24643
24820
|
|
|
24821
|
+
const mutation$6 = t(`
|
|
24822
|
+
mutation QuoteRecalculateTaxes($id: ID!) {
|
|
24823
|
+
quoteRecalculateTaxes(id: $id) {
|
|
24824
|
+
quote {
|
|
24825
|
+
...QuoteContext_QuoteFragment
|
|
24826
|
+
id
|
|
24827
|
+
}
|
|
24828
|
+
errors
|
|
24829
|
+
}
|
|
24830
|
+
}
|
|
24831
|
+
`, [QuoteContext_QuoteFragment]);
|
|
24832
|
+
const quoteRecalculateTaxes = async ({ quoteId, apiHost, token, }) => {
|
|
24833
|
+
var _a;
|
|
24834
|
+
const response = await execute(mutation$6, { apiHost, token }, { id: quoteId });
|
|
24835
|
+
return (_a = response.quoteRecalculateTaxes) === null || _a === void 0 ? void 0 : _a.quote;
|
|
24836
|
+
};
|
|
24837
|
+
|
|
24838
|
+
const useQuoteRecalculateTaxes = () => {
|
|
24839
|
+
const token = useToken();
|
|
24840
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
24841
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
24842
|
+
const { mutate: quoteRecalculateTaxesMutation, isPending: isRecalculatingTaxes } = reactQuery.useMutation({
|
|
24843
|
+
mutationFn: async ({ quoteId }) => {
|
|
24844
|
+
return await quoteRecalculateTaxes({ quoteId, apiHost, token });
|
|
24845
|
+
},
|
|
24846
|
+
onSuccess: quote => {
|
|
24847
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
24848
|
+
throw new Error('Quote ID is undefined');
|
|
24849
|
+
}
|
|
24850
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quote);
|
|
24851
|
+
},
|
|
24852
|
+
});
|
|
24853
|
+
return {
|
|
24854
|
+
quoteRecalculateTaxesMutation,
|
|
24855
|
+
isRecalculatingTaxes,
|
|
24856
|
+
};
|
|
24857
|
+
};
|
|
24858
|
+
|
|
24644
24859
|
function useFeatureAddonsPending() {
|
|
24645
24860
|
const [featureAddonsLoading, setFeatureAddonsLoading] = react.useState([]);
|
|
24646
24861
|
const addFeatureAddonLoading = (featureAddonId) => {
|
|
@@ -24664,6 +24879,7 @@ function QuoteProvider({ children }) {
|
|
|
24664
24879
|
// Hooks
|
|
24665
24880
|
const token = useToken();
|
|
24666
24881
|
const { isFeatureAddonsLoading, addFeatureAddonLoading, removeFeatureAddonLoading } = useFeatureAddonsPending();
|
|
24882
|
+
const { quoteRecalculateTaxesMutation } = useQuoteRecalculateTaxes();
|
|
24667
24883
|
const { quote: maskedQuote, isQuotePending } = useQuoteCreate({
|
|
24668
24884
|
upgradingSubscription,
|
|
24669
24885
|
selectedPriceList: selectedPriceList,
|
|
@@ -24699,6 +24915,7 @@ function QuoteProvider({ children }) {
|
|
|
24699
24915
|
onChangeSelectedPriceList: handleChangeSelectedPriceList,
|
|
24700
24916
|
onChangeQuantity,
|
|
24701
24917
|
getFeatureQuantity,
|
|
24918
|
+
onRecalculateTaxes: (id) => quoteRecalculateTaxesMutation({ quoteId: id }),
|
|
24702
24919
|
}, children: children }));
|
|
24703
24920
|
}
|
|
24704
24921
|
|
|
@@ -24725,40 +24942,6 @@ function priceDescriptionString({ unitName, showPriceAsMonthly, periodMonths, pr
|
|
|
24725
24942
|
return `Per ${unitName && !priceListHasFlatFeeCharges ? `${unitName.toLowerCase()} / ` : ''}${showPriceAsMonthly ? 'month' : periodLabel}`;
|
|
24726
24943
|
}
|
|
24727
24944
|
|
|
24728
|
-
var localizedFormat$2 = {exports: {}};
|
|
24729
|
-
|
|
24730
|
-
var localizedFormat$1 = localizedFormat$2.exports;
|
|
24731
|
-
|
|
24732
|
-
var hasRequiredLocalizedFormat;
|
|
24733
|
-
|
|
24734
|
-
function requireLocalizedFormat () {
|
|
24735
|
-
if (hasRequiredLocalizedFormat) return localizedFormat$2.exports;
|
|
24736
|
-
hasRequiredLocalizedFormat = 1;
|
|
24737
|
-
(function (module, exports) {
|
|
24738
|
-
!function(e,t){module.exports=t();}(localizedFormat$1,(function(){var e={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};return function(t,o,n){var r=o.prototype,i=r.format;n.en.formats=e,r.format=function(t){void 0===t&&(t="YYYY-MM-DDTHH:mm:ssZ");var o=this.$locale().formats,n=function(t,o){return t.replace(/(\[[^\]]+])|(LTS?|l{1,4}|L{1,4})/g,(function(t,n,r){var i=r&&r.toUpperCase();return n||o[r]||e[r]||o[i].replace(/(\[[^\]]+])|(MMMM|MM|DD|dddd)/g,(function(e,t,o){return t||o.slice(1)}))}))}(t,void 0===o?{}:o);return i.call(this,n)};}}));
|
|
24739
|
-
} (localizedFormat$2));
|
|
24740
|
-
return localizedFormat$2.exports;
|
|
24741
|
-
}
|
|
24742
|
-
|
|
24743
|
-
var localizedFormatExports = requireLocalizedFormat();
|
|
24744
|
-
var localizedFormat = /*@__PURE__*/getDefaultExportFromCjs(localizedFormatExports);
|
|
24745
|
-
|
|
24746
|
-
dayjs.extend(localizedFormat);
|
|
24747
|
-
const formatCurrency = (value, currencyIsoCode, decimals = 2) => {
|
|
24748
|
-
if (value !== 0 && !value)
|
|
24749
|
-
return '';
|
|
24750
|
-
const currencyValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
24751
|
-
if (isNaN(currencyValue))
|
|
24752
|
-
return value;
|
|
24753
|
-
const localeOptions = {
|
|
24754
|
-
minimumFractionDigits: decimals,
|
|
24755
|
-
maximumFractionDigits: decimals,
|
|
24756
|
-
};
|
|
24757
|
-
localeOptions.style = 'currency';
|
|
24758
|
-
localeOptions.currency = currencyIsoCode;
|
|
24759
|
-
return currencyValue.toLocaleString(navigator.language, localeOptions);
|
|
24760
|
-
};
|
|
24761
|
-
|
|
24762
24945
|
const { Text: Text$b } = antd.Typography;
|
|
24763
24946
|
const PriceTierPrice = ({ currencyId, priceDecimals, tier, }) => {
|
|
24764
24947
|
return (jsxRuntime.jsx(Text$b, { className: "bunny-text-white", children: formatCurrency(tier.price, currencyId, priceDecimals) }));
|
|
@@ -24782,32 +24965,6 @@ const PriceTierRow = ({ tier: maskedTier, nextTier: maskedNextTier, }) => {
|
|
|
24782
24965
|
return jsxRuntime.jsx(Text$a, { className: "bunny-text-white", children: text });
|
|
24783
24966
|
};
|
|
24784
24967
|
|
|
24785
|
-
const getPricingModelTitle = (pricingModel) => {
|
|
24786
|
-
switch (pricingModel) {
|
|
24787
|
-
case 'TIERED':
|
|
24788
|
-
return 'Tiered';
|
|
24789
|
-
case 'VOLUME':
|
|
24790
|
-
return 'Volume';
|
|
24791
|
-
case 'BANDS':
|
|
24792
|
-
return 'Bands';
|
|
24793
|
-
default:
|
|
24794
|
-
return '';
|
|
24795
|
-
}
|
|
24796
|
-
};
|
|
24797
|
-
|
|
24798
|
-
const getPricingModelDescription = (pricingModel) => {
|
|
24799
|
-
switch (pricingModel) {
|
|
24800
|
-
case 'TIERED':
|
|
24801
|
-
return 'units in each tier are priced separately.';
|
|
24802
|
-
case 'VOLUME':
|
|
24803
|
-
return 'the highest tier reached prices all units.';
|
|
24804
|
-
case 'BANDS':
|
|
24805
|
-
return 'the quantity indexes to a flat price.';
|
|
24806
|
-
default:
|
|
24807
|
-
return '';
|
|
24808
|
-
}
|
|
24809
|
-
};
|
|
24810
|
-
|
|
24811
24968
|
const { Text: Text$9 } = antd.Typography;
|
|
24812
24969
|
const ChargePriceTiers_PriceListChargeFragment = t(`
|
|
24813
24970
|
fragment ChargePriceTiers_PriceListChargeFragment on PriceListCharge {
|
|
@@ -25442,57 +25599,13 @@ const getAvailablePlansAndPriceLists = ({ availablePriceLists, priceListChangeOp
|
|
|
25442
25599
|
return {
|
|
25443
25600
|
availablePriceListsArray,
|
|
25444
25601
|
displayPriceLists,
|
|
25445
|
-
};
|
|
25446
|
-
};
|
|
25447
|
-
const everythingInPlusString = ({ priceList }) => {
|
|
25448
|
-
return `Everything in ${priceList.plan.name}, plus`;
|
|
25449
|
-
};
|
|
25450
|
-
|
|
25451
|
-
const QUOTE_CHARGE_CREATE = `
|
|
25452
|
-
${QUOTE_FIELDS()}
|
|
25453
|
-
mutation QuoteChargeCreate ($quoteChangeId: ID!, $startDate: ISO8601Date!, $endDate: ISO8601Date, $priceListChargeId: ID, $subscriptionChargeId: ID, $price: Float, $quantity: Int) {
|
|
25454
|
-
quoteChargeCreate(
|
|
25455
|
-
endDate: $endDate
|
|
25456
|
-
price: $price
|
|
25457
|
-
priceListChargeId: $priceListChargeId
|
|
25458
|
-
quantity: $quantity
|
|
25459
|
-
quoteChangeId: $quoteChangeId
|
|
25460
|
-
startDate: $startDate
|
|
25461
|
-
subscriptionChargeId: $subscriptionChargeId
|
|
25462
|
-
) {
|
|
25463
|
-
quoteCharge {
|
|
25464
|
-
quoteChange {
|
|
25465
|
-
id
|
|
25466
|
-
quoteId
|
|
25467
|
-
quote {
|
|
25468
|
-
...QuoteFields
|
|
25469
|
-
}
|
|
25470
|
-
}
|
|
25471
|
-
id
|
|
25472
|
-
}
|
|
25473
|
-
}
|
|
25474
|
-
}
|
|
25475
|
-
|
|
25476
|
-
`;
|
|
25477
|
-
const quoteChargeCreate = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
25478
|
-
var _a;
|
|
25479
|
-
const response = await gqlRequest({
|
|
25480
|
-
query: QUOTE_CHARGE_CREATE,
|
|
25481
|
-
vars: {
|
|
25482
|
-
price,
|
|
25483
|
-
priceListChargeId,
|
|
25484
|
-
quantity,
|
|
25485
|
-
quoteChangeId,
|
|
25486
|
-
startDate,
|
|
25487
|
-
subscriptionChargeId,
|
|
25488
|
-
},
|
|
25489
|
-
apiHost,
|
|
25490
|
-
token,
|
|
25491
|
-
});
|
|
25492
|
-
return (_a = response === null || response === void 0 ? void 0 : response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
25602
|
+
};
|
|
25603
|
+
};
|
|
25604
|
+
const everythingInPlusString = ({ priceList }) => {
|
|
25605
|
+
return `Everything in ${priceList.plan.name}, plus`;
|
|
25493
25606
|
};
|
|
25494
25607
|
|
|
25495
|
-
const mutation = t(`
|
|
25608
|
+
const mutation$5 = t(`
|
|
25496
25609
|
mutation QuoteChargeDelete($quoteChargeId: ID!) {
|
|
25497
25610
|
quoteChargeDelete(quoteChargeId: $quoteChargeId) {
|
|
25498
25611
|
errors
|
|
@@ -25510,21 +25623,76 @@ const mutation = t(`
|
|
|
25510
25623
|
`, [QuoteContext_QuoteFragment]);
|
|
25511
25624
|
const quoteChargeDelete = async ({ quoteChargeId, token, apiHost }) => {
|
|
25512
25625
|
var _a, _b, _c, _d;
|
|
25513
|
-
const response = await execute(mutation, { apiHost, token }, { quoteChargeId });
|
|
25626
|
+
const response = await execute(mutation$5, { apiHost, token }, { quoteChargeId });
|
|
25514
25627
|
if ((_a = response.quoteChargeDelete) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
25515
25628
|
throw new Error((_c = (_b = response.quoteChargeDelete) === null || _b === void 0 ? void 0 : _b.errors) === null || _c === void 0 ? void 0 : _c[0]);
|
|
25516
25629
|
}
|
|
25517
25630
|
return (_d = response.quoteChargeDelete) === null || _d === void 0 ? void 0 : _d.quoteCharge;
|
|
25518
25631
|
};
|
|
25519
25632
|
|
|
25520
|
-
const
|
|
25633
|
+
const mutation$4 = t(`
|
|
25634
|
+
mutation QuoteChargeCreate(
|
|
25635
|
+
$quoteChangeId: ID!
|
|
25636
|
+
$startDate: ISO8601Date!
|
|
25637
|
+
$endDate: ISO8601Date
|
|
25638
|
+
$priceListChargeId: ID
|
|
25639
|
+
$subscriptionChargeId: ID
|
|
25640
|
+
$price: Float
|
|
25641
|
+
$quantity: Int
|
|
25642
|
+
) {
|
|
25643
|
+
quoteChargeCreate(
|
|
25644
|
+
endDate: $endDate
|
|
25645
|
+
price: $price
|
|
25646
|
+
priceListChargeId: $priceListChargeId
|
|
25647
|
+
quantity: $quantity
|
|
25648
|
+
quoteChangeId: $quoteChangeId
|
|
25649
|
+
startDate: $startDate
|
|
25650
|
+
subscriptionChargeId: $subscriptionChargeId
|
|
25651
|
+
) {
|
|
25652
|
+
quoteCharge {
|
|
25653
|
+
quoteChange {
|
|
25654
|
+
id
|
|
25655
|
+
quoteId
|
|
25656
|
+
quote {
|
|
25657
|
+
...QuoteContext_QuoteFragment
|
|
25658
|
+
}
|
|
25659
|
+
}
|
|
25660
|
+
id
|
|
25661
|
+
}
|
|
25662
|
+
}
|
|
25663
|
+
}
|
|
25664
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25665
|
+
const quoteChargeCreate = async ({ price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId, token, apiHost, }) => {
|
|
25666
|
+
var _a;
|
|
25667
|
+
const response = await execute(mutation$4, { apiHost, token }, { price, priceListChargeId, quantity, quoteChangeId, startDate, subscriptionChargeId });
|
|
25668
|
+
return (_a = response === null || response === void 0 ? void 0 : response.quoteChargeCreate) === null || _a === void 0 ? void 0 : _a.quoteCharge;
|
|
25669
|
+
};
|
|
25670
|
+
|
|
25671
|
+
const useQuoteUpdateFeatureAddon = (maskedQuote, featureAddon) => {
|
|
25521
25672
|
const { apiHost } = react.useContext(BunnyContext);
|
|
25522
25673
|
const { addFeatureAddonLoading, removeFeatureAddonLoading } = react.useContext(QuoteContext);
|
|
25523
25674
|
const token = useToken();
|
|
25524
|
-
const
|
|
25675
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
25676
|
+
// Read fragments
|
|
25677
|
+
const quote = readFragment(useQuoteUpdateFeatureAddon_QuoteFragment, maskedQuote);
|
|
25525
25678
|
const addedQuoteChargeId = react.useRef();
|
|
25526
25679
|
function handleAddFeatureAddon() {
|
|
25527
|
-
|
|
25680
|
+
if (!token)
|
|
25681
|
+
throw new Error('Token is required');
|
|
25682
|
+
if (!quote)
|
|
25683
|
+
throw new Error('Editing quote is required');
|
|
25684
|
+
const quoteChangeId = findQuoteChangeForFeatureAddon(quote);
|
|
25685
|
+
if (!quoteChangeId)
|
|
25686
|
+
throw new Error('No available quote change for feature add-on');
|
|
25687
|
+
console.log('quote', quote);
|
|
25688
|
+
console.log('startDate', quote === null || quote === void 0 ? void 0 : quote.startDate);
|
|
25689
|
+
quoteChargeCreateMutation({
|
|
25690
|
+
quoteChangeId: quoteChangeId.id,
|
|
25691
|
+
priceListChargeId: featureAddon.id,
|
|
25692
|
+
startDate: quote === null || quote === void 0 ? void 0 : quote.startDate,
|
|
25693
|
+
apiHost,
|
|
25694
|
+
token,
|
|
25695
|
+
});
|
|
25528
25696
|
}
|
|
25529
25697
|
function handleRemoveFeatureAddon() {
|
|
25530
25698
|
if (!addedQuoteChargeId.current)
|
|
@@ -25532,30 +25700,16 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25532
25700
|
quoteChargeDeleteMutation({ quoteChargeId: addedQuoteChargeId.current });
|
|
25533
25701
|
}
|
|
25534
25702
|
const { mutate: quoteChargeCreateMutation, isPending: isCreatingFeatureAddon } = reactQuery.useMutation({
|
|
25535
|
-
mutationFn:
|
|
25536
|
-
|
|
25537
|
-
|
|
25538
|
-
if (!quote)
|
|
25539
|
-
throw new Error('
|
|
25540
|
-
|
|
25541
|
-
if (!
|
|
25542
|
-
throw new Error('
|
|
25543
|
-
|
|
25544
|
-
|
|
25545
|
-
priceListChargeId: featureAddon.id,
|
|
25546
|
-
startDate: quote === null || quote === void 0 ? void 0 : quote.startDate,
|
|
25547
|
-
apiHost,
|
|
25548
|
-
token,
|
|
25549
|
-
});
|
|
25550
|
-
return { quoteCharge };
|
|
25551
|
-
},
|
|
25552
|
-
onSuccess: ({ quoteCharge }) => {
|
|
25553
|
-
addedQuoteChargeId.current = quoteCharge.id;
|
|
25554
|
-
queryClient.setQueryData(common.QueryKeyFactory.default.createObjectKey({
|
|
25555
|
-
objectName: 'editingQuote',
|
|
25556
|
-
id: quote === null || quote === void 0 ? void 0 : quote.id,
|
|
25557
|
-
token,
|
|
25558
|
-
}), quoteCharge.quoteChange.quote);
|
|
25703
|
+
mutationFn: quoteChargeCreate,
|
|
25704
|
+
onSuccess: quoteCharge => {
|
|
25705
|
+
addedQuoteChargeId.current = quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.id;
|
|
25706
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25707
|
+
throw new Error('Quote ID is undefined');
|
|
25708
|
+
}
|
|
25709
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25710
|
+
throw new Error('Quote is undefined');
|
|
25711
|
+
}
|
|
25712
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25559
25713
|
},
|
|
25560
25714
|
});
|
|
25561
25715
|
const { mutate: quoteChargeDeleteMutation, isPending: isDeletingFeatureAddon } = reactQuery.useMutation({
|
|
@@ -25565,11 +25719,13 @@ const useQuoteUpdateFeatureAddon = (quote, featureAddon) => {
|
|
|
25565
25719
|
},
|
|
25566
25720
|
onSuccess: quoteCharge => {
|
|
25567
25721
|
addedQuoteChargeId.current = undefined;
|
|
25568
|
-
|
|
25569
|
-
|
|
25570
|
-
|
|
25571
|
-
|
|
25572
|
-
|
|
25722
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25723
|
+
throw new Error('Quote ID is undefined');
|
|
25724
|
+
}
|
|
25725
|
+
if (!(quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote)) {
|
|
25726
|
+
throw new Error('Quote is undefined');
|
|
25727
|
+
}
|
|
25728
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, quoteCharge === null || quoteCharge === void 0 ? void 0 : quoteCharge.quoteChange.quote);
|
|
25573
25729
|
},
|
|
25574
25730
|
});
|
|
25575
25731
|
const isPending = isCreatingFeatureAddon || isDeletingFeatureAddon;
|
|
@@ -25649,10 +25805,11 @@ const FeatureAddonRow_PriceListChargeFragment = t(`
|
|
|
25649
25805
|
}
|
|
25650
25806
|
`, [isAddonPurchased_PriceListChargeFragment, PricingTooltip_PriceListChargeFragment]);
|
|
25651
25807
|
function FeatureAddonRow({ featureAddon: maskedFeatureAddon, priceList: maskedPriceList, }) {
|
|
25808
|
+
const { quote: maskedQuote, selectedPriceList } = react.useContext(QuoteContext);
|
|
25652
25809
|
// Read fragments
|
|
25653
25810
|
const featureAddon = readFragment(FeatureAddonRow_PriceListChargeFragment, maskedFeatureAddon);
|
|
25654
25811
|
const priceList = readFragment(FeatureAddonRow_PriceListFragment, maskedPriceList);
|
|
25655
|
-
const
|
|
25812
|
+
const quote = readFragment(FeatureAddonRow_QuoteFragment, maskedQuote);
|
|
25656
25813
|
const { handleAddFeatureAddon, handleRemoveFeatureAddon, isPending, isChecked } = useQuoteUpdateFeatureAddon(quote, featureAddon);
|
|
25657
25814
|
const { brandColor } = useBrand();
|
|
25658
25815
|
const { upgradingSubscription } = react.useContext(SubscriptionsContext);
|
|
@@ -25867,107 +26024,84 @@ function AddonPlanModal({ onClose, priceList: maskedPriceList, }) {
|
|
|
25867
26024
|
return (jsxRuntime.jsx(StyledModal, { open: !!priceList, onCancel: onClose, footer: null, centered: true, children: jsxRuntime.jsxs("div", { className: `bunny-w-full bunny-overflow-hidden`, children: [jsxRuntime.jsx(GridTemplateColumnsWrapper, { className: "bunny-grid bunny-w-full", everythingInPlus: false, plansToDisplay: 1, children: priceList && (jsxRuntime.jsx(PriceListCard, { isSelected: true, priceList: priceList, noBorder: true, hideButton: true, disableCurrentPlan: true })) }), hasFeatureAddons && (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(antd.Divider, { className: "bunny-my-0" }), jsxRuntime.jsx("div", { className: "bunny-flex bunny-flex-col bunny-gap-4 bunny-p-4", children: jsxRuntime.jsx(FeatureAddonsList, { priceList: priceList }) })] }))] }) }));
|
|
25868
26025
|
}
|
|
25869
26026
|
|
|
25870
|
-
const
|
|
25871
|
-
${
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
) {
|
|
25877
|
-
|
|
25878
|
-
|
|
25879
|
-
|
|
25880
|
-
|
|
25881
|
-
|
|
25882
|
-
|
|
25883
|
-
|
|
25884
|
-
id
|
|
25885
|
-
quote {
|
|
25886
|
-
...QuoteFields
|
|
26027
|
+
const mutation$3 = t(`
|
|
26028
|
+
mutation QuoteChangeCreate($quoteId: ID!, $priceListId: ID!, $parentQuoteChangeId: ID!) {
|
|
26029
|
+
quoteChangeCreate(
|
|
26030
|
+
quoteId: $quoteId
|
|
26031
|
+
priceListId: $priceListId
|
|
26032
|
+
parentQuoteChangeId: $parentQuoteChangeId
|
|
26033
|
+
) {
|
|
26034
|
+
errors
|
|
26035
|
+
quoteChange {
|
|
26036
|
+
id
|
|
26037
|
+
quote {
|
|
26038
|
+
...QuoteContext_QuoteFragment
|
|
26039
|
+
}
|
|
26040
|
+
}
|
|
25887
26041
|
}
|
|
25888
26042
|
}
|
|
25889
|
-
|
|
25890
|
-
}
|
|
25891
|
-
`;
|
|
26043
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25892
26044
|
const quoteChangeCreate = async ({ parentQuoteChangeId, priceListId, apiHost, token, quoteId, }) => {
|
|
25893
|
-
|
|
25894
|
-
const vars = {
|
|
25895
|
-
parentQuoteChangeId,
|
|
25896
|
-
priceListId,
|
|
25897
|
-
quoteId,
|
|
25898
|
-
};
|
|
25899
|
-
const response = await gqlRequest({
|
|
25900
|
-
query: QUOTE_CHANGE_CREATE,
|
|
25901
|
-
token,
|
|
25902
|
-
vars,
|
|
25903
|
-
apiHost,
|
|
25904
|
-
});
|
|
25905
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeCreate) === null || _a === void 0 ? void 0 : _a.errors;
|
|
25906
|
-
if (errors)
|
|
25907
|
-
throw errors;
|
|
26045
|
+
const response = await execute(mutation$3, { apiHost, token }, { parentQuoteChangeId, priceListId, quoteId });
|
|
25908
26046
|
return response.quoteChangeCreate;
|
|
25909
26047
|
};
|
|
25910
26048
|
|
|
25911
|
-
const
|
|
25912
|
-
${
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
26049
|
+
const mutation$2 = t(`
|
|
26050
|
+
mutation QuoteChangeDelete($id: ID!) {
|
|
26051
|
+
quoteChangeDelete(id: $id) {
|
|
26052
|
+
errors
|
|
26053
|
+
quoteChange {
|
|
26054
|
+
quote {
|
|
26055
|
+
...QuoteContext_QuoteFragment
|
|
26056
|
+
}
|
|
25919
26057
|
}
|
|
25920
26058
|
}
|
|
25921
26059
|
}
|
|
25922
|
-
|
|
25923
|
-
`;
|
|
26060
|
+
`, [QuoteContext_QuoteFragment]);
|
|
25924
26061
|
const quoteChangeDelete = async ({ id, apiHost, token, }) => {
|
|
25925
|
-
|
|
25926
|
-
const vars = {
|
|
25927
|
-
id,
|
|
25928
|
-
};
|
|
25929
|
-
const response = await gqlRequest({
|
|
25930
|
-
query: QUOTE_CHANGE_DELETE,
|
|
25931
|
-
token,
|
|
25932
|
-
vars,
|
|
25933
|
-
apiHost,
|
|
25934
|
-
});
|
|
25935
|
-
const errors = (_a = response === null || response === void 0 ? void 0 : response.quoteChangeDelete) === null || _a === void 0 ? void 0 : _a.errors;
|
|
25936
|
-
if (errors)
|
|
25937
|
-
throw errors;
|
|
26062
|
+
const response = await execute(mutation$2, { apiHost, token }, { id });
|
|
25938
26063
|
return response.quoteChangeDelete;
|
|
25939
26064
|
};
|
|
25940
26065
|
|
|
25941
|
-
const useToggleAddonPlan = (
|
|
26066
|
+
const useToggleAddonPlan = (maskedQuote, addonPriceListId, selectedPriceList, setIsAddonPlanLoading) => {
|
|
25942
26067
|
const token = useToken();
|
|
25943
26068
|
const isAdded = react.useRef(false);
|
|
25944
|
-
const queryClient = reactQuery.useQueryClient();
|
|
25945
26069
|
const { apiHost } = react.useContext(BunnyContext);
|
|
26070
|
+
const { setQuoteQueryData } = useSetQuoteQueryData();
|
|
26071
|
+
// Read fragments
|
|
26072
|
+
const quote = readFragment(useToggleAddonPlan_QuoteFragment, maskedQuote);
|
|
25946
26073
|
const parentQuoteChange = react.useMemo(() => {
|
|
25947
|
-
|
|
26074
|
+
var _a;
|
|
26075
|
+
return (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.find(qc => { var _a; return ((_a = qc.priceList) === null || _a === void 0 ? void 0 : _a.id) === selectedPriceList.id; });
|
|
25948
26076
|
}, [quote, selectedPriceList]);
|
|
25949
26077
|
const { mutate: addAddonQuoteChange, isPending: isAddingAddonQuoteChange } = reactQuery.useMutation({
|
|
25950
26078
|
mutationFn: quoteChangeCreate,
|
|
25951
|
-
onSuccess:
|
|
26079
|
+
onSuccess: quoteChangeCreate => {
|
|
26080
|
+
var _a;
|
|
25952
26081
|
isAdded.current = true;
|
|
25953
|
-
const updatedQuote = quoteChangeCreate.quoteChange.quote;
|
|
25954
|
-
|
|
25955
|
-
|
|
25956
|
-
|
|
25957
|
-
|
|
25958
|
-
|
|
26082
|
+
const updatedQuote = (_a = quoteChangeCreate === null || quoteChangeCreate === void 0 ? void 0 : quoteChangeCreate.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26083
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26084
|
+
throw new Error('Updated quote ID not found');
|
|
26085
|
+
}
|
|
26086
|
+
if (!updatedQuote) {
|
|
26087
|
+
throw new Error('Updated quote not found');
|
|
26088
|
+
}
|
|
26089
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25959
26090
|
},
|
|
25960
26091
|
});
|
|
25961
26092
|
const { mutate: deleteQuoteChange, isPending: isDeletingQuoteChange } = reactQuery.useMutation({
|
|
25962
26093
|
mutationFn: quoteChangeDelete,
|
|
25963
|
-
onSuccess:
|
|
26094
|
+
onSuccess: quoteChangeDelete => {
|
|
26095
|
+
var _a;
|
|
25964
26096
|
isAdded.current = false;
|
|
25965
|
-
const updatedQuote = quoteChangeDelete.quoteChange.quote;
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
26097
|
+
const updatedQuote = (_a = quoteChangeDelete === null || quoteChangeDelete === void 0 ? void 0 : quoteChangeDelete.quoteChange) === null || _a === void 0 ? void 0 : _a.quote;
|
|
26098
|
+
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
26099
|
+
throw new Error('Updated quote ID not found');
|
|
26100
|
+
}
|
|
26101
|
+
if (!updatedQuote) {
|
|
26102
|
+
throw new Error('Updated quote not found');
|
|
26103
|
+
}
|
|
26104
|
+
setQuoteQueryData(quote === null || quote === void 0 ? void 0 : quote.id, updatedQuote);
|
|
25971
26105
|
},
|
|
25972
26106
|
});
|
|
25973
26107
|
function handleAddAddonQuoteChange() {
|
|
@@ -25977,6 +26111,9 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25977
26111
|
if (!(quote === null || quote === void 0 ? void 0 : quote.id)) {
|
|
25978
26112
|
throw new Error('Quote ID not found');
|
|
25979
26113
|
}
|
|
26114
|
+
if (!parentQuoteChange.id) {
|
|
26115
|
+
throw new Error('Parent quote change ID not found');
|
|
26116
|
+
}
|
|
25980
26117
|
addAddonQuoteChange({
|
|
25981
26118
|
parentQuoteChangeId: parentQuoteChange.id,
|
|
25982
26119
|
priceListId: addonPriceListId,
|
|
@@ -25986,9 +26123,10 @@ const useToggleAddonPlan = (quote, addonPriceListId, selectedPriceList, setIsAdd
|
|
|
25986
26123
|
});
|
|
25987
26124
|
}
|
|
25988
26125
|
function handleDeleteQuoteChange() {
|
|
25989
|
-
|
|
25990
|
-
|
|
25991
|
-
|
|
26126
|
+
var _a;
|
|
26127
|
+
const quoteChange = (_a = quote === null || quote === void 0 ? void 0 : quote.quoteChanges) === null || _a === void 0 ? void 0 : _a.find(qc => { var _a; return ((_a = qc.priceList) === null || _a === void 0 ? void 0 : _a.id) === addonPriceListId; });
|
|
26128
|
+
if (!(quoteChange === null || quoteChange === void 0 ? void 0 : quoteChange.id)) {
|
|
26129
|
+
throw new Error('Quote change ID not found');
|
|
25992
26130
|
}
|
|
25993
26131
|
deleteQuoteChange({
|
|
25994
26132
|
id: quoteChange.id,
|
|
@@ -26022,6 +26160,7 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26022
26160
|
plan {
|
|
26023
26161
|
description
|
|
26024
26162
|
name
|
|
26163
|
+
pricingDescription
|
|
26025
26164
|
}
|
|
26026
26165
|
...PriceListCardPriceDescription_PriceListFragment
|
|
26027
26166
|
...PriceListCardPrice_PriceListFragment
|
|
@@ -26035,16 +26174,18 @@ const AddonPlanRow_PriceListFragment = t(`
|
|
|
26035
26174
|
PriceListCardPriceDescription_PriceListFragment,
|
|
26036
26175
|
]);
|
|
26037
26176
|
function AddonPlanRow({ addonPriceList: maskedAddonPriceList, selectedPriceList, onClickSelect, isPurchased, }) {
|
|
26038
|
-
var _a, _b, _c, _d, _e, _f;
|
|
26177
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
26039
26178
|
// Read fragments
|
|
26040
26179
|
const addonPriceList = readFragment(AddonPlanRow_PriceListFragment, maskedAddonPriceList);
|
|
26041
|
-
const { quote, setIsAddonPlanLoading } = react.useContext(QuoteContext);
|
|
26180
|
+
const { quote: maskedQuote, setIsAddonPlanLoading } = react.useContext(QuoteContext);
|
|
26181
|
+
const quote = readFragment(AddonPlanRow_QuoteFragment, maskedQuote);
|
|
26042
26182
|
const { shadow, isInPreviewMode } = react.useContext(SubscriptionsContext);
|
|
26043
26183
|
const { isPending, addedQuoteChange, addAddonQuoteChange, deleteQuoteChange } = useToggleAddonPlan(quote, addonPriceList.id, selectedPriceList, setIsAddonPlanLoading);
|
|
26044
26184
|
const activeCharge = (_a = getActivePlanPriceData(addonPriceList, selectedPriceList)) === null || _a === void 0 ? void 0 : _a.activeCharge;
|
|
26045
26185
|
// Derived state
|
|
26046
26186
|
const switchDisabled = isInPreviewMode || isPurchased;
|
|
26047
|
-
|
|
26187
|
+
const hasCustomPrice = ((_b = addonPriceList.plan) === null || _b === void 0 ? void 0 : _b.pricingDescription) != null;
|
|
26188
|
+
return (jsxRuntime.jsxs("div", { className: `bunny-flex bunny-flex-row bunny-gap-2 bunny-justify-between bunny-items-center bunny-p-4 bunny-rounded-md bunny-bg-white ${shadow ? `shadow-${shadow}` : ''} bunny-mb-2`, children: [jsxRuntime.jsxs("div", { className: "bunny-flex bunny-flex-row bunny-gap-2 bunny-items-center", children: [jsxRuntime.jsx("div", { className: `bunny-font-medium bunny-text-center bunny-text-orange-600`, children: (_c = addonPriceList.plan) === null || _c === void 0 ? void 0 : _c.name }), jsxRuntime.jsx(PriceListCardDescription, { description: (_e = (_d = addonPriceList.plan) === null || _d === void 0 ? void 0 : _d.description) !== null && _e !== void 0 ? _e : '' }), !hasCustomPrice && (jsxRuntime.jsx(PriceListCardPrice, { priceList: addonPriceList, className: "bunny-text-sm bunny-font-medium bunny-text-gray-900" })), jsxRuntime.jsx(PriceListCardPriceDescription, { feature: activeCharge === null || activeCharge === void 0 ? void 0 : activeCharge.feature, priceList: addonPriceList }), jsxRuntime.jsx(antd.Button, { type: "link", onClick: onClickSelect, children: jsxRuntime.jsx(icons.InfoCircleOutlined, {}) })] }), jsxRuntime.jsx(antd.Switch, { id: addonPlanSwitchTestId((_g = (_f = addonPriceList.plan) === null || _f === void 0 ? void 0 : _f.name) !== null && _g !== void 0 ? _g : ''), loading: isPending && !switchDisabled, checked: addedQuoteChange || isPurchased, onChange: (checked) => {
|
|
26048
26189
|
if (checked) {
|
|
26049
26190
|
addAddonQuoteChange();
|
|
26050
26191
|
}
|
|
@@ -26068,7 +26209,7 @@ const AddonPlans_PlanFragment = t(`
|
|
|
26068
26209
|
}
|
|
26069
26210
|
`, [AddonPlanModal_PriceListFragment, AddonPlanRow_PriceListFragment]);
|
|
26070
26211
|
|
|
26071
|
-
const query = t(`
|
|
26212
|
+
const query$2 = t(`
|
|
26072
26213
|
query PriceList($id: ID!) {
|
|
26073
26214
|
priceList(id: $id) {
|
|
26074
26215
|
addonPlans {
|
|
@@ -26082,7 +26223,7 @@ const query = t(`
|
|
|
26082
26223
|
`, [AddonPlans_PlanFragment]);
|
|
26083
26224
|
const getAddonPlans = async ({ token, id, apiHost, }) => {
|
|
26084
26225
|
var _a;
|
|
26085
|
-
const response = await execute(query, { apiHost, token }, { id });
|
|
26226
|
+
const response = await execute(query$2, { apiHost, token }, { id });
|
|
26086
26227
|
const addonPlans = (_a = response === null || response === void 0 ? void 0 : response.priceList) === null || _a === void 0 ? void 0 : _a.addonPlans;
|
|
26087
26228
|
// for each addon plan, filter out the price lists that are not visible
|
|
26088
26229
|
const visibleAddonPlans = addonPlans === null || addonPlans === void 0 ? void 0 : addonPlans.map(addonPlan => {
|
|
@@ -26190,7 +26331,10 @@ const PriceListGrid = ({ availablePriceLists, priceListChangeOptions, priceListS
|
|
|
26190
26331
|
onClickPriceListCard: onClickPriceListCard })) : (jsxRuntime.jsx(PriceListGridDesktop, { availablePriceLists: availablePriceLists, priceListChangeOptions: priceListChangeOptions, priceListStart: priceListStart, selectedPriceList: selectedPriceList, selectedProduct: selectedProduct, setPriceListStart: setPriceListStart, subscriptions: subscriptions, trialRemainingDays: trialRemainingDays, selectedBillingPeriod: selectedBillingPeriod, onClickPriceListCard: onClickPriceListCard }));
|
|
26191
26332
|
};
|
|
26192
26333
|
|
|
26193
|
-
const createAvailableBillingPeriods = (priceLists, selectedProduct) => {
|
|
26334
|
+
const createAvailableBillingPeriods = (priceLists, selectedProduct, upgradingSubscription) => {
|
|
26335
|
+
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true) {
|
|
26336
|
+
return [upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.periodMonths];
|
|
26337
|
+
}
|
|
26194
26338
|
return priceLists === null || priceLists === void 0 ? void 0 : priceLists.filter(priceList => priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id)).map(priceList => priceList.periodMonths).sort((a, b) => a - b).filter((currentValue, index, array) => index === array.indexOf(currentValue));
|
|
26195
26339
|
};
|
|
26196
26340
|
const showInfoNotification$1 = common.useInfoNotification();
|
|
@@ -26204,11 +26348,18 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26204
26348
|
const [selectedBillingPeriod, setSelectedBillingPeriod] = react.useState(null);
|
|
26205
26349
|
const [priceListStart, setPriceListStart] = react.useState(0);
|
|
26206
26350
|
// Derived state
|
|
26207
|
-
const availableBillingPeriods = react.useMemo(() => createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct), [priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct]);
|
|
26351
|
+
const availableBillingPeriods = react.useMemo(() => createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct, upgradingSubscription), [priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, selectedProduct]);
|
|
26352
|
+
// TODO: clean up available pricelists calculation. We should calculate it once, not three times.
|
|
26353
|
+
const subscriptionIsAddon = (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.addon) === true;
|
|
26208
26354
|
const availablePriceLists = react.useMemo(() => {
|
|
26209
26355
|
var _a;
|
|
26210
|
-
|
|
26211
|
-
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id))
|
|
26356
|
+
const priceLists = (_a = priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists) === null || _a === void 0 ? void 0 : _a.filter(priceList => periodMonthsConverter(priceList.periodMonths) === selectedBillingPeriod &&
|
|
26357
|
+
priceList.product.id === (selectedProduct === null || selectedProduct === void 0 ? void 0 : selectedProduct.id));
|
|
26358
|
+
// If the subscription is an addon, we should only show its price lists because we don't support changing add-on plans.
|
|
26359
|
+
if (subscriptionIsAddon) {
|
|
26360
|
+
return ((priceLists === null || priceLists === void 0 ? void 0 : priceLists.filter(priceList => priceList.plan.id === (upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList.plan.id))) || []);
|
|
26361
|
+
}
|
|
26362
|
+
return priceLists.filter(priceList => priceList.plan.addon !== true) || [];
|
|
26212
26363
|
}, [priceListChangeOptions, selectedBillingPeriod, selectedProduct]);
|
|
26213
26364
|
// Handlers
|
|
26214
26365
|
const onChangeBillingPeriod = react.useCallback((billingPeriod) => {
|
|
@@ -26237,7 +26388,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26237
26388
|
}
|
|
26238
26389
|
}, [selectedPriceList, priceListChangeOptions, upgradingSubscription]);
|
|
26239
26390
|
const onChangeProduct = react.useCallback((product) => {
|
|
26240
|
-
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product);
|
|
26391
|
+
const newAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, product, upgradingSubscription);
|
|
26241
26392
|
if (selectedBillingPeriod &&
|
|
26242
26393
|
!(newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods.includes(billingPeriodConverter(selectedBillingPeriod)))) {
|
|
26243
26394
|
onChangeBillingPeriod(periodMonthsConverter((newAvailableBillingPeriods === null || newAvailableBillingPeriods === void 0 ? void 0 : newAvailableBillingPeriods[0]) !== undefined ? newAvailableBillingPeriods[0] : 1));
|
|
@@ -26248,7 +26399,7 @@ const PriceListSelector = ({ arePlanChangeOptionsLoading, areSubscriptionsLoadin
|
|
|
26248
26399
|
const initialProduct = (_a = priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.products) === null || _a === void 0 ? void 0 : _a[0];
|
|
26249
26400
|
const initialBillingPeriod = react.useMemo(() => {
|
|
26250
26401
|
var _a, _b, _c;
|
|
26251
|
-
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct);
|
|
26402
|
+
const initialAvailableBillingPeriods = createAvailableBillingPeriods(priceListChangeOptions === null || priceListChangeOptions === void 0 ? void 0 : priceListChangeOptions.priceLists, initialProduct, upgradingSubscription);
|
|
26252
26403
|
const periodMonthsConverted = periodMonthsConverter((_b = (_a = upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) === null || _a === void 0 ? void 0 : _a.periodMonths) !== null && _b !== void 0 ? _b : null);
|
|
26253
26404
|
if ((upgradingSubscription === null || upgradingSubscription === void 0 ? void 0 : upgradingSubscription.priceList) &&
|
|
26254
26405
|
periodMonthsConverted &&
|
|
@@ -26904,80 +27055,177 @@ const PageSubTitle = ({ title }) => {
|
|
|
26904
27055
|
return (jsxRuntime.jsx("div", { className: "bunny-shrink-0", style: { color: secondaryColor }, children: title }));
|
|
26905
27056
|
};
|
|
26906
27057
|
|
|
26907
|
-
const
|
|
26908
|
-
|
|
26909
|
-
|
|
26910
|
-
|
|
26911
|
-
|
|
26912
|
-
|
|
26913
|
-
|
|
26914
|
-
|
|
26915
|
-
|
|
26916
|
-
|
|
27058
|
+
const AccountContactsFragment = t(`
|
|
27059
|
+
fragment AccountContactsFragment on Contact {
|
|
27060
|
+
id
|
|
27061
|
+
email
|
|
27062
|
+
firstName
|
|
27063
|
+
}
|
|
27064
|
+
`, []);
|
|
27065
|
+
|
|
27066
|
+
const AddContactButton = ({ onClick }) => {
|
|
27067
|
+
return (jsxRuntime.jsx("div", { className: "bunny-border-t bunny-border-gray-200 bunny-p-2", children: jsxRuntime.jsx(antd.Button, { type: "text", className: "bunny-w-full bunny-text-left", onClick: onClick, children: "+ Add new contact" }) }));
|
|
27068
|
+
};
|
|
27069
|
+
|
|
27070
|
+
const useSetAccountContactsQueryData = () => {
|
|
27071
|
+
const token = useToken();
|
|
27072
|
+
const queryClient = reactQuery.useQueryClient();
|
|
27073
|
+
const setAccountContactsQueryData = (accountId, updater) => {
|
|
27074
|
+
queryClient.setQueryData(QueryKeyFactory.accountContactsKey({ accountId, token }), updater);
|
|
27075
|
+
};
|
|
27076
|
+
return { setAccountContactsQueryData };
|
|
27077
|
+
};
|
|
27078
|
+
|
|
27079
|
+
const mutation$1 = t(`
|
|
27080
|
+
mutation ContactCreate($attributes: ContactAttributes!) {
|
|
27081
|
+
contactCreate(attributes: $attributes) {
|
|
27082
|
+
contact {
|
|
27083
|
+
id
|
|
27084
|
+
account {
|
|
27085
|
+
contacts {
|
|
27086
|
+
...AccountContactsFragment
|
|
27087
|
+
}
|
|
26917
27088
|
}
|
|
26918
|
-
billingCountry
|
|
26919
|
-
billingState
|
|
26920
|
-
billingStreet
|
|
26921
|
-
billingZip
|
|
26922
|
-
name
|
|
26923
|
-
taxNumber
|
|
26924
27089
|
}
|
|
26925
27090
|
errors
|
|
26926
27091
|
}
|
|
26927
|
-
|
|
26928
|
-
|
|
26929
|
-
const
|
|
26930
|
-
var _a;
|
|
26931
|
-
const
|
|
26932
|
-
|
|
26933
|
-
|
|
26934
|
-
|
|
26935
|
-
|
|
26936
|
-
|
|
27092
|
+
}
|
|
27093
|
+
`, [AccountContactsFragment]);
|
|
27094
|
+
const contactCreate = async ({ attributes, apiHost, token }) => {
|
|
27095
|
+
var _a, _b;
|
|
27096
|
+
const response = await execute(mutation$1, { apiHost, token }, { attributes });
|
|
27097
|
+
if ((_a = response.contactCreate) === null || _a === void 0 ? void 0 : _a.errors) {
|
|
27098
|
+
throw new Error(response.contactCreate.errors[0]);
|
|
27099
|
+
}
|
|
27100
|
+
return (_b = response.contactCreate) === null || _b === void 0 ? void 0 : _b.contact;
|
|
27101
|
+
};
|
|
27102
|
+
|
|
27103
|
+
const AddContactModal = ({ open, onClose, accountId, onContactCreated, }) => {
|
|
27104
|
+
const [form] = antd.Form.useForm();
|
|
27105
|
+
const { apiHost } = react.useContext(BunnyContext);
|
|
27106
|
+
const token = useToken();
|
|
27107
|
+
const showErrorNotification = common.useErrorNotification();
|
|
27108
|
+
const showSuccessNotification = common.useSuccessNotification();
|
|
27109
|
+
const { setAccountContactsQueryData } = useSetAccountContactsQueryData();
|
|
27110
|
+
const { mutate: createContact, isPending: isCreatingContact } = reactQuery.useMutation({
|
|
27111
|
+
mutationFn: (attributes) => contactCreate({ attributes, apiHost, token }),
|
|
27112
|
+
onSuccess: newContact => {
|
|
27113
|
+
var _a, _b;
|
|
27114
|
+
showSuccessNotification('Contact created successfully');
|
|
27115
|
+
// Add the new contact to the cache
|
|
27116
|
+
if (newContact && accountId) {
|
|
27117
|
+
setAccountContactsQueryData(accountId, (_b = (_a = newContact === null || newContact === void 0 ? void 0 : newContact.account) === null || _a === void 0 ? void 0 : _a.contacts) !== null && _b !== void 0 ? _b : null);
|
|
27118
|
+
}
|
|
27119
|
+
onClose();
|
|
27120
|
+
form.resetFields();
|
|
27121
|
+
const newContactData = newContact ? readFragment(AccountContactsFragment, newContact) : null;
|
|
27122
|
+
if (newContactData === null || newContactData === void 0 ? void 0 : newContactData.id) {
|
|
27123
|
+
onContactCreated === null || onContactCreated === void 0 ? void 0 : onContactCreated(newContactData.id);
|
|
27124
|
+
}
|
|
27125
|
+
},
|
|
26937
27126
|
});
|
|
26938
|
-
const
|
|
26939
|
-
|
|
26940
|
-
|
|
26941
|
-
|
|
27127
|
+
const handleAddContact = () => {
|
|
27128
|
+
if (!accountId) {
|
|
27129
|
+
showErrorNotification('Account ID is required to create a contact');
|
|
27130
|
+
return;
|
|
27131
|
+
}
|
|
27132
|
+
form.validateFields().then(values => {
|
|
27133
|
+
createContact({
|
|
27134
|
+
email: values.email || null,
|
|
27135
|
+
firstName: values.firstName || null,
|
|
27136
|
+
lastName: values.lastName || null,
|
|
27137
|
+
accountId: accountId,
|
|
27138
|
+
portalAccess: true,
|
|
27139
|
+
});
|
|
27140
|
+
});
|
|
27141
|
+
};
|
|
27142
|
+
return (jsxRuntime.jsx(antd.Modal, { title: "Add new contact", open: open, onCancel: () => {
|
|
27143
|
+
onClose();
|
|
27144
|
+
form.resetFields();
|
|
27145
|
+
}, footer: [
|
|
27146
|
+
jsxRuntime.jsx(antd.Button, { onClick: () => {
|
|
27147
|
+
onClose();
|
|
27148
|
+
form.resetFields();
|
|
27149
|
+
}, children: "Cancel" }, "cancel"),
|
|
27150
|
+
jsxRuntime.jsx(antd.Button, { type: "primary", loading: isCreatingContact, onClick: handleAddContact, children: "Add contact" }, "submit"),
|
|
27151
|
+
], children: jsxRuntime.jsxs(antd.Form, { form: form, layout: "vertical", className: "bunny-flex bunny-flex-col bunny-gap-2", children: [jsxRuntime.jsx(antd.Form.Item, { label: "First name", name: "firstName", rules: [{ required: false }], children: jsxRuntime.jsx(antd.Input, { placeholder: "Enter first name" }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Last name", name: "lastName", rules: [{ required: false }], children: jsxRuntime.jsx(antd.Input, { placeholder: "Enter last name" }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Email", name: "email", rules: [
|
|
27152
|
+
{ required: true, message: 'Email is required' },
|
|
27153
|
+
{ type: 'email', message: 'Please enter a valid email' },
|
|
27154
|
+
], children: jsxRuntime.jsx(antd.Input, { placeholder: "Enter email" }) })] }) }));
|
|
26942
27155
|
};
|
|
26943
27156
|
|
|
26944
|
-
const
|
|
26945
|
-
|
|
26946
|
-
billingDetails {
|
|
26947
|
-
billingCity
|
|
26948
|
-
billingContact {
|
|
26949
|
-
email
|
|
26950
|
-
}
|
|
26951
|
-
billingCountry
|
|
26952
|
-
billingState
|
|
26953
|
-
billingStreet
|
|
26954
|
-
billingZip
|
|
26955
|
-
name
|
|
26956
|
-
taxNumber
|
|
26957
|
-
currency {
|
|
27157
|
+
const BillingDetailsSection_AccountFragment = t(`
|
|
27158
|
+
fragment BillingDetailsSection_AccountFragment on Account {
|
|
26958
27159
|
id
|
|
27160
|
+
name
|
|
27161
|
+
billingStreet
|
|
27162
|
+
billingCity
|
|
27163
|
+
billingState
|
|
27164
|
+
billingZip
|
|
27165
|
+
billingCountry
|
|
27166
|
+
taxNumber
|
|
27167
|
+
billingContactId
|
|
27168
|
+
secondaryBillingContactIds
|
|
27169
|
+
billingContact {
|
|
27170
|
+
email
|
|
27171
|
+
firstName
|
|
27172
|
+
}
|
|
26959
27173
|
}
|
|
26960
|
-
|
|
26961
|
-
|
|
26962
|
-
const
|
|
27174
|
+
`, []);
|
|
27175
|
+
|
|
27176
|
+
const mutation = t(`
|
|
27177
|
+
mutation AccountUpdate($id: ID!, $attributes: AccountAttributes!) {
|
|
27178
|
+
accountUpdate(id: $id, attributes: $attributes) {
|
|
27179
|
+
account {
|
|
27180
|
+
...BillingDetailsSection_AccountFragment
|
|
27181
|
+
}
|
|
27182
|
+
errors
|
|
27183
|
+
}
|
|
27184
|
+
}
|
|
27185
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27186
|
+
const accountUpdate = async ({ accountId, attributes, apiHost, token, }) => {
|
|
26963
27187
|
var _a;
|
|
26964
|
-
const response = await
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
26970
|
-
|
|
27188
|
+
const response = await execute(mutation, { apiHost, token }, { id: accountId, attributes });
|
|
27189
|
+
return (_a = response.accountUpdate) === null || _a === void 0 ? void 0 : _a.account;
|
|
27190
|
+
};
|
|
27191
|
+
|
|
27192
|
+
const query$1 = t(`
|
|
27193
|
+
query GetAccount($id: ID!) {
|
|
27194
|
+
account(id: $id) {
|
|
27195
|
+
...BillingDetailsSection_AccountFragment
|
|
27196
|
+
}
|
|
27197
|
+
}
|
|
27198
|
+
`, [BillingDetailsSection_AccountFragment]);
|
|
27199
|
+
const getAccount = async ({ accountId, apiHost, token, }) => {
|
|
27200
|
+
const response = await execute(query$1, { apiHost, token }, { id: accountId });
|
|
27201
|
+
return response.account;
|
|
27202
|
+
};
|
|
27203
|
+
|
|
27204
|
+
const query = t(`
|
|
27205
|
+
query GetAccountContacts($accountId: ID!) {
|
|
27206
|
+
account(id: $accountId) {
|
|
27207
|
+
id
|
|
27208
|
+
contacts {
|
|
27209
|
+
...AccountContactsFragment
|
|
27210
|
+
}
|
|
27211
|
+
}
|
|
26971
27212
|
}
|
|
26972
|
-
|
|
27213
|
+
`, [AccountContactsFragment]);
|
|
27214
|
+
const getAccountContacts = async ({ accountId, apiHost, token, }) => {
|
|
27215
|
+
var _a;
|
|
27216
|
+
const response = await execute(query, { apiHost, token }, { accountId });
|
|
27217
|
+
return (_a = response.account) === null || _a === void 0 ? void 0 : _a.contacts;
|
|
26973
27218
|
};
|
|
26974
27219
|
|
|
26975
27220
|
const { Text } = antd.Typography;
|
|
26976
27221
|
function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
27222
|
+
var _a, _b, _c;
|
|
26977
27223
|
// State
|
|
26978
27224
|
const [isFormEdited, setIsFormEdited] = react.useState(false);
|
|
26979
27225
|
const [form] = antd.Form.useForm();
|
|
26980
27226
|
const values = antd.Form.useWatch([], form);
|
|
27227
|
+
const [isAddContactModalOpen, setIsAddContactModalOpen] = react.useState(false);
|
|
27228
|
+
const [contactFieldType, setContactFieldType] = react.useState(null);
|
|
26981
27229
|
// Context
|
|
26982
27230
|
const { apiHost } = react.useContext(BunnyContext);
|
|
26983
27231
|
const token = useToken();
|
|
@@ -26986,14 +27234,37 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
26986
27234
|
const queryClient = reactQuery.useQueryClient();
|
|
26987
27235
|
const showErrorNotification = common.useErrorNotification();
|
|
26988
27236
|
const showSuccessNotification = common.useSuccessNotification();
|
|
27237
|
+
const { currentUser } = useCurrentUserData(token);
|
|
27238
|
+
const accountId = (_a = currentUser === null || currentUser === void 0 ? void 0 : currentUser.account) === null || _a === void 0 ? void 0 : _a.id;
|
|
26989
27239
|
// Queries
|
|
26990
|
-
const { data:
|
|
26991
|
-
queryKey:
|
|
26992
|
-
queryFn: () =>
|
|
27240
|
+
const { data: maskedAccount, isLoading: isLoadingAccount } = reactQuery.useQuery({
|
|
27241
|
+
queryKey: QueryKeyFactory.accountBillingDetailsKey({ accountId, token }),
|
|
27242
|
+
queryFn: () => {
|
|
27243
|
+
if (!accountId) {
|
|
27244
|
+
throw new Error('Account ID is required');
|
|
27245
|
+
}
|
|
27246
|
+
return getAccount({ accountId, apiHost, token });
|
|
27247
|
+
},
|
|
27248
|
+
enabled: !!accountId,
|
|
27249
|
+
});
|
|
27250
|
+
const account = readFragment(BillingDetailsSection_AccountFragment, maskedAccount);
|
|
27251
|
+
const { data: contacts, isLoading: isLoadingContacts } = reactQuery.useQuery({
|
|
27252
|
+
queryKey: QueryKeyFactory.accountContactsKey({ accountId, token }),
|
|
27253
|
+
queryFn: () => {
|
|
27254
|
+
if (!accountId) {
|
|
27255
|
+
throw new Error('Account ID is required');
|
|
27256
|
+
}
|
|
27257
|
+
return getAccountContacts({ accountId, apiHost, token });
|
|
27258
|
+
},
|
|
27259
|
+
enabled: !!accountId,
|
|
26993
27260
|
});
|
|
26994
|
-
const { mutate:
|
|
27261
|
+
const { mutate: updateAccount, isPending: isUpdatingAccount } = reactQuery.useMutation({
|
|
26995
27262
|
mutationFn: async (changedFormData) => {
|
|
26996
|
-
|
|
27263
|
+
if (!accountId) {
|
|
27264
|
+
throw new Error('Account ID is required');
|
|
27265
|
+
}
|
|
27266
|
+
const updatedAccount = await accountUpdate({
|
|
27267
|
+
accountId,
|
|
26997
27268
|
attributes: {
|
|
26998
27269
|
name: changedFormData.name,
|
|
26999
27270
|
billingStreet: changedFormData.billingStreet,
|
|
@@ -27001,77 +27272,92 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
27001
27272
|
billingZip: changedFormData.billingZip,
|
|
27002
27273
|
billingState: changedFormData.billingState,
|
|
27003
27274
|
billingCountry: changedFormData.billingCountry,
|
|
27004
|
-
billingContactEmail: changedFormData.billingContactEmail,
|
|
27005
27275
|
taxNumber: changedFormData.taxNumber,
|
|
27276
|
+
billingContactId: changedFormData.billingContactId || null,
|
|
27277
|
+
secondaryBillingContactIds: Array.isArray(changedFormData.secondaryBillingContactIds)
|
|
27278
|
+
? changedFormData.secondaryBillingContactIds
|
|
27279
|
+
: null,
|
|
27006
27280
|
},
|
|
27007
27281
|
token,
|
|
27008
27282
|
apiHost,
|
|
27009
27283
|
});
|
|
27010
|
-
queryClient.setQueryData(
|
|
27011
|
-
|
|
27012
|
-
...old,
|
|
27013
|
-
...updatedBillingDetails.billingDetails,
|
|
27014
|
-
};
|
|
27015
|
-
});
|
|
27016
|
-
return updatedBillingDetails;
|
|
27284
|
+
queryClient.setQueryData(QueryKeyFactory.accountBillingDetailsKey({ accountId, token }), updatedAccount);
|
|
27285
|
+
return updatedAccount;
|
|
27017
27286
|
},
|
|
27018
27287
|
onSuccess: () => {
|
|
27019
27288
|
showSuccessNotification('Your account details have been saved');
|
|
27020
27289
|
queryClient.invalidateQueries({
|
|
27021
|
-
queryKey:
|
|
27290
|
+
queryKey: QueryKeyFactory.taxationRequiredAccountFieldsKey({
|
|
27022
27291
|
token,
|
|
27023
27292
|
}),
|
|
27024
27293
|
});
|
|
27025
27294
|
},
|
|
27026
27295
|
});
|
|
27027
|
-
// Set form values when
|
|
27296
|
+
// Set form values when account is loaded
|
|
27028
27297
|
react.useEffect(() => {
|
|
27029
|
-
|
|
27030
|
-
if (billingDetails) {
|
|
27298
|
+
if (account) {
|
|
27031
27299
|
form.setFieldsValue({
|
|
27032
|
-
billingStreet:
|
|
27033
|
-
billingCity:
|
|
27034
|
-
billingZip:
|
|
27035
|
-
billingState:
|
|
27036
|
-
billingCountry:
|
|
27037
|
-
|
|
27038
|
-
|
|
27300
|
+
billingStreet: account.billingStreet,
|
|
27301
|
+
billingCity: account.billingCity,
|
|
27302
|
+
billingZip: account.billingZip,
|
|
27303
|
+
billingState: account.billingState,
|
|
27304
|
+
billingCountry: account.billingCountry,
|
|
27305
|
+
billingContactId: account.billingContactId,
|
|
27306
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27307
|
+
taxNumber: account.taxNumber,
|
|
27039
27308
|
});
|
|
27040
27309
|
}
|
|
27041
|
-
}, [
|
|
27310
|
+
}, [account]);
|
|
27042
27311
|
react.useEffect(() => {
|
|
27043
27312
|
form.validateFields({ validateOnly: true });
|
|
27044
27313
|
const isFormEdited = () => {
|
|
27045
|
-
|
|
27046
|
-
if (!billingDetails)
|
|
27314
|
+
if (!account)
|
|
27047
27315
|
return false;
|
|
27048
27316
|
const currentValues = form.getFieldsValue();
|
|
27049
27317
|
const accountValues = {
|
|
27050
|
-
billingStreet:
|
|
27051
|
-
billingCity:
|
|
27052
|
-
billingZip:
|
|
27053
|
-
billingState:
|
|
27054
|
-
billingCountry:
|
|
27055
|
-
|
|
27056
|
-
|
|
27318
|
+
billingStreet: account.billingStreet,
|
|
27319
|
+
billingCity: account.billingCity,
|
|
27320
|
+
billingZip: account.billingZip,
|
|
27321
|
+
billingState: account.billingState,
|
|
27322
|
+
billingCountry: account.billingCountry,
|
|
27323
|
+
billingContactId: account.billingContactId,
|
|
27324
|
+
secondaryBillingContactIds: account.secondaryBillingContactIds,
|
|
27325
|
+
taxNumber: account.taxNumber,
|
|
27057
27326
|
};
|
|
27058
|
-
return Object.keys(
|
|
27327
|
+
return Object.keys(accountValues).some(key => {
|
|
27059
27328
|
const value = accountValues[key];
|
|
27060
|
-
|
|
27329
|
+
const currentValue = currentValues[key];
|
|
27330
|
+
// Handle array comparison for secondaryBillingContactIds
|
|
27331
|
+
if (Array.isArray(value) && Array.isArray(currentValue)) {
|
|
27332
|
+
return JSON.stringify(value === null || value === void 0 ? void 0 : value.sort()) !== JSON.stringify(currentValue === null || currentValue === void 0 ? void 0 : currentValue.sort());
|
|
27333
|
+
}
|
|
27334
|
+
return currentValue !== value;
|
|
27061
27335
|
});
|
|
27062
27336
|
};
|
|
27063
27337
|
setIsFormEdited(isFormEdited());
|
|
27064
|
-
}, [form, values,
|
|
27338
|
+
}, [form, values, account]);
|
|
27065
27339
|
// Validate form fields when isFormEdited changes
|
|
27066
27340
|
react.useEffect(() => {
|
|
27067
27341
|
const validateOnly = isFormEdited ? false : true;
|
|
27068
27342
|
form.validateFields({ validateOnly: validateOnly });
|
|
27069
27343
|
}, [isFormEdited]);
|
|
27344
|
+
const handleContactCreated = (contactId) => {
|
|
27345
|
+
if (contactFieldType === 'primary') {
|
|
27346
|
+
form.setFieldValue('billingContactId', contactId);
|
|
27347
|
+
}
|
|
27348
|
+
else if (contactFieldType === 'secondary') {
|
|
27349
|
+
const currentSecondaryContacts = form.getFieldValue('secondaryBillingContactIds') || [];
|
|
27350
|
+
if (!currentSecondaryContacts.includes(contactId)) {
|
|
27351
|
+
form.setFieldValue('secondaryBillingContactIds', [...currentSecondaryContacts, contactId]);
|
|
27352
|
+
}
|
|
27353
|
+
}
|
|
27354
|
+
setContactFieldType(null);
|
|
27355
|
+
};
|
|
27070
27356
|
const saveBillingDetails = async () => {
|
|
27071
27357
|
form.validateFields({ validateOnly: false }).then(async () => {
|
|
27072
27358
|
try {
|
|
27073
27359
|
await form.validateFields();
|
|
27074
|
-
|
|
27360
|
+
updateAccount(form.getFieldsValue());
|
|
27075
27361
|
}
|
|
27076
27362
|
catch (error) {
|
|
27077
27363
|
if (error instanceof Error) {
|
|
@@ -27089,21 +27375,38 @@ function BillingDetailsSection({ hidePaymentMethodForm, countryListFilter, }) {
|
|
|
27089
27375
|
const filteredCountryList = react.useMemo(() => {
|
|
27090
27376
|
return countryListFilter ? common.Lists.COUNTRY_LIST.filter(countryListFilter) : common.Lists.COUNTRY_LIST;
|
|
27091
27377
|
}, [countryListFilter]);
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27099
|
-
((
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27104
|
-
|
|
27105
|
-
|
|
27106
|
-
|
|
27378
|
+
const isLoading = isLoadingAccount || isLoadingContacts;
|
|
27379
|
+
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", requiredMark: false, children: [jsxRuntime.jsx(antd.Form.Item, { label: "Street address", name: "billingStreet", rules: [{ required: true, message: 'Street address is required' }], children: jsxRuntime.jsx(antd.Input, {}) }), jsxRuntime.jsxs("div", { className: "bunny-flex bunny-gap-4", children: [jsxRuntime.jsx(antd.Form.Item, { label: "City", name: "billingCity", rules: [{ required: true, message: 'City is required' }], className: "bunny-flex-1", children: jsxRuntime.jsx(antd.Input, {}) }), jsxRuntime.jsx(antd.Form.Item, { label: "Zipcode", name: "billingZip", rules: [{ required: true, message: 'Zipcode is required' }], 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", rules: [
|
|
27380
|
+
{
|
|
27381
|
+
required: false,
|
|
27382
|
+
},
|
|
27383
|
+
], 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) => {
|
|
27384
|
+
var _a, _b;
|
|
27385
|
+
return ((_a = option === null || option === void 0 ? void 0 : option.label) !== null && _a !== void 0 ? _a : '').toLowerCase().includes(input.toLowerCase()) ||
|
|
27386
|
+
((_b = option === null || option === void 0 ? void 0 : option.value) !== null && _b !== void 0 ? _b : '').toLowerCase().includes(input.toLowerCase());
|
|
27387
|
+
} }) }) })] }), jsxRuntime.jsx(antd.Form.Item, { label: "Primary billing contact", name: "billingContactId", rules: [{ required: true, message: 'Primary billing contact is required' }], children: jsxRuntime.jsx(antd.Select, { className: "bunny-w-full", placeholder: "Select a contact", options: (_b = contacts === null || contacts === void 0 ? void 0 : contacts.map(contact => {
|
|
27388
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27389
|
+
return {
|
|
27390
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27391
|
+
? `${contactData.firstName}`
|
|
27392
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27393
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27394
|
+
};
|
|
27395
|
+
})) !== null && _b !== void 0 ? _b : [], popupRender: menu => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menu, jsxRuntime.jsx(AddContactButton, { onClick: () => setIsAddContactModalOpen(true) })] })) }) }), jsxRuntime.jsx(antd.Form.Item, { label: "Secondary billing contacts", name: "secondaryBillingContactIds", children: jsxRuntime.jsx(antd.Select, { className: "bunny-w-full", mode: "multiple", maxTagCount: "responsive", placeholder: "Select contacts", options: (_c = contacts === null || contacts === void 0 ? void 0 : contacts.map(contact => {
|
|
27396
|
+
const contactData = readFragment(AccountContactsFragment, contact);
|
|
27397
|
+
return {
|
|
27398
|
+
label: (contactData === null || contactData === void 0 ? void 0 : contactData.firstName)
|
|
27399
|
+
? `${contactData.firstName}`
|
|
27400
|
+
: contactData === null || contactData === void 0 ? void 0 : contactData.email,
|
|
27401
|
+
value: contactData === null || contactData === void 0 ? void 0 : contactData.id,
|
|
27402
|
+
};
|
|
27403
|
+
})) !== null && _c !== void 0 ? _c : [], popupRender: menu => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menu, jsxRuntime.jsx(AddContactButton, { onClick: () => {
|
|
27404
|
+
setContactFieldType('secondary');
|
|
27405
|
+
setIsAddContactModalOpen(true);
|
|
27406
|
+
} })] })) }) }), 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", rules: [{ required: false }], 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: () => {
|
|
27407
|
+
setIsAddContactModalOpen(false);
|
|
27408
|
+
setContactFieldType(null);
|
|
27409
|
+
}, accountId: accountId, onContactCreated: handleContactCreated })] }));
|
|
27107
27410
|
}
|
|
27108
27411
|
|
|
27109
27412
|
const BillingDetails = ({ className, countryListFilter, hideBillingDetailsForm = false, hidePaymentMethodForm = false, isCardEnabled = true, isUpgradeFromTrial = false, shadow = 'shadow-md', onSavePaymentMethod, }) => {
|